• React 从0开始 消息传递


    React笔记

    React 数据决定DOM
    以往的做法是通过JS去操作DOM 将数据填充

    JSX

    Jsx javascript xml
    HTML的结构组装到js中
    jsx使用style的时候 不能直接使用style=""
    而是通过{} 的方式

    style={{ this.state.ele_w, height: this.state.ele_h}}
    

    React生命周期

    每一个功能可以认为是一个React组件
    不可变的设置为 property 可变的设置为state
    一个组件就是一个状态机 各种状态都是根据state变化的

    React声明周期分为三个阶段
    Mounting 创建
    Updating 更新
    Unmouting 销毁

    创建

    当首次使用一个组件的时候 将会依次call下面的函数
    getDefaultProps
    getInitialState 设置state属性初始化值
    componentWillMount 将要显示在页面的组件
    Render 渲染Jsx的结构
    compoonectDidMount render渲染完毕吧

    非第一次使用这个组件 越过getDefaultProps这一步

    更新

    更新时依次触发下面的函数
    componentWillReceiveProps 父组件属性变化
    shouldComponentUpdate 针对不常改变的组件如需更新则在这个函数的返回值设置为false
    componentWillUpdate 组件将要改变时调用(更新前调用)
    render
    componentDidUpdate 组件更新完成

    componentWillUpdate 是使用最多的函数
    在一个组建的props states 改变后调用

    销毁

    componentWillUnmount 组件即将销毁

    setState replaceState不同
    replaceState({})是将整个state都替换成{}中的内容

    React 同构实践

    SPA有什么不好的地方
    典型的SPA都是由 js 渲染得到的 因此对于SEO并不友好
    另外js的下载和执行需要时间

    React可以同时在客户端和服务端渲染,解决了之前服务端 客户端逻辑重复 更新时容易有bug的问题

    Babel 可以运行jsx 和 ES6

    start

    可以直接用script标签引入react.js 不过官方的推荐做法是结合browserify 或者 webpack 一起用 name我们还是使用官方推荐的做法吧

    下面是一个检测文本框值变化的例子
    react 针对onChange 事件做了优化 使input是有改动就触发的
    而平常onchange只有改动了值且失去焦点后才触发

          var Input = React.createClass({
            getInitialState: function() {
              return {value: 'Hello!'};
            },
            handleChange: function(event) {
              this.setState({value: event.target.value});
            },
            render: function () {
              var value = this.state.value;
              return (
                <div>
                  <input type="text" value={value} onChange={this.handleChange} />
                  <p>{value}</p>
                </div>
              );
            }
          });
    
          React.render(<Input/>, document.body);
    

    React组件之间的消息传递

    React各个组件之间的消息针对不同的情形 传递消息有很多种办法

    父子组件消息传递

    父 --> 子 直接通过props写入数据
    子 --> 父 调用父组件的函数 将值传给父组件

    var Container1, Inner1;
    Container1 = React.createClass({
      getInitialState: function(){
        return {
          val1: this.props.val1 ||'',
          val2:''
        }
      },
      setVal2Fn: function(value){
        // console.log('te!!st',value);
        this.setState({
          val2:value
        })
      },
      render: function(){
        return (
          <div class="container">
            From inner is {this.state.val2}
            <Inner1 val1={this.state.val1} setVal2Fn={this.setVal2Fn} />
          </div>
        )
      }
    });
    
    Inner1 = React.createClass({
      getInitialState: function(){
        return {}
      },
      handleSubmit: function(e){
        var target = e.target;
    
        //prenode是寻找submit按钮之前的一个元素  也就是文本输入框
        var prenode= (function(){
          var node = target.previousSibling;
          while(node.nodeType!=1){
               node=node.previousSibling;
               if(!node) return null;
          };
          return node;
        })();
        //调用父组件的函数  并将值以参数的形式传给父组件
        this.props.setVal2Fn(prenode.value);  //将值传给父组件
      },
      render:function(){
        return (
          <div>
            From container is {this.props.val1}
            <input type="text" ref="innerValue"/>
            <button onClick={this.handleSubmit}>Submit</button>
          </div>
        )
      }
    })
    
    

    同一个父组件内的子组件之间的消息传递

    也就是借助父组件作为桥梁来传递数据

    由于兄弟组件之间不能相互传递数据 所以数据都放在父组件中
    数据的获取 由父组件传递给子组件
    数据的更改 由父组件传递修改函数给子组件

    var Container2, Inner2, Inner3;
    Container2 = React.createClass({
      getInitialState: function(){
        return{
          val3:'val3',
          val2:'val2'
        }
      },
      changeVal2: function(value){
        this.setState({
          val2: value
        })
      },
      changeVal3: function(value){
        this.setState({
          val3: value
        })
      },
      render: function(){
        //本例子是Inner2 和 Inner3 之间的消息传递
        //Inner2 的消息传给 Inner3  实际上就是传给父组件  
        //然后Inner3 使用的是父组件读取这个父组件的变量
        return <div>
          <Inner2  val2={this.state.val2}  val3={this.state.val3}
          changeVal3Fn={this.changeVal3}/>
          <Inner3  val2={this.state.val2}  val3={this.state.val3}
          changeVal2Fn={this.changeVal2}/>
        </div>
      }
    });
    
    Inner2=React.createClass({
      textChange: function(e){
        var val = e.target.value;
        this.props.changeVal3Fn(val);
      },
      render: function(){
        return (
        <div>
          {this.props.val2}
          <input type="text" onChange={this.textChange} />
        </div>
        )
      }
    });
    
    Inner3 = React.createClass({
      textChange: function(e){
        var val = e.target.value;
        this.props.changeVal2Fn(val);
      },
      render: function(){
        return (
        <div>
          {this.props.val3}
          <input type="text" onChange={this.textChange} />
        </div>
        )
      }
    });
    
    
    

    全局通信

    Inner4 Inner5之间通信 直接改变两个子组件的上下文环境 都直接指向父组件
    那么两个子组件就能直接访问父组件的变量

    
    var Container3, Inner4,Inner5;
    Container3 = React.createClass({
      getInitialState: function(){
        return{
          val:'val'
        }
      },
      childContextTypes: {
        val: React.PropTypes.any,
        changeValFn: React.PropTypes.any
      },
      //设置子组件的val和changeValFn对象的上下文
      getChildContext: function(){
        return {
          val: this.state.val,
          changeValFn: this.changeValFn
        }
      },
      changeValFn: function(e){
        console.log('val' ,e.target.value);
        this.setState({
          val: e.target.value
        })
      },
      render: function(){
        return <div>
          <Inner4 val={this.state.val}
          changeValFn={this.changeValFn}/>
        </div>
      }
    });
    Inner4 = React.createClass({
      contextTypes: {
        val: React.PropTypes.any,
        changeValFn:React.PropTypes.any
      },
    
      render: function(){
        return (
          <div>
            -- { this.context.val } --
            <input onChange={this.context.changeValFn} />
          </div>
        )
      }
    });
    
    

    使用事件 订阅发布模式

    如果觉得前面的方式太过于繁琐, 可以使用这个模式, 它的逻辑独立在React组件之外 官方也建议使用这种模式来处理(特别是嵌套层次较深的组件之间的消息传递)

    
    //使用PubSub 订阅发布模式来处理消息传递
    //在一个组件ComponentDidMount函数触发后就绑定
    var Container4, Container5;
    var messagePubSub = new PubSub();
    var MSGCHANGED = 'msg_changed';
    Container4 = React.createClass({
      getInitialState: function(){
        return {
          text: 'default'
        }
      },
      componentDidMount: function(){
        messagePubSub.addEvent(MSGCHANGED, this.msgHandler);
      },
      msgHandler: function(value){
        console.log('test', value);
        this.setState({
          text:value
        })
      },
      render: function(){
        return (
          <div>
            -- {this.state.text} --
          </div>
        )
      }
    });
    Container5 = React.createClass({
      changeHandler: function(e){
        messagePubSub.fireEvent(MSGCHANGED, null, e.target.value);
      },
      render: function(){
        return (
          <div>
            <input class="container5-input" onChange={this.changeHandler}/>
          </div>
        )
      }
    });
    
    
  • 相关阅读:
    阅读《Android 从入门到精通》(29)——四大布局
    UISegmentedControl 修改字体大小 和 颜色
    UITableView Scroll to top 手动设置tableview 滚动到 顶部
    xcode arc 下使用 block警告 Capturing [an object] strongly in this block is likely to lead to a retain cycle” in ARC-enabled code
    iOS key value coding kvc在接收json数据与 model封装中的使用
    NSData 转 bytes 字节数据
    git commit 出现 changes not staged for commit 错误
    iOS exit(),abort(),assert()函数区别
    ios 程序发布使用xcode工具Application Loader 正在通过ITUNES STORE进行鉴定错误
    iOS mac添加证书 不能修改“System Roots”钥匙串错误
  • 原文地址:https://www.cnblogs.com/cart55free99/p/5182584.html
Copyright © 2020-2023  润新知