最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React 的四种常见通信场景

    正文概述 掘金(coolFish)   2020-12-13   329

    React 通信:

    父组件传给子组件:

    • 看例子前,先说一个通俗的理解,就是子组件在父组件中,自己的标签内定义一个键值对,值可以是父组件的参数,然后在子组件中,this.props.属性名字,就可以获取到这个值
    //这个是父组件
    export default class App extends Component{

        render(){
            return(
                <div>
                    <Sub title = "今年过节不收礼" />
                </div>
            )
        }
    }
    //这里是子组件
    const Sub = (props) => {
        return(
            <h1>
                { props.title }
            </h1>
        )
    }

    小结:在父组件中,子组件可以在自己的标签中,键值对的形式添加待传递的值,然后子组件内部,使用this.props.属性名字获取,

    子组件向父组件传值

    • 父组件将一个函数作为 props 传递给子组件,子组件调用该回调函数,便可以向父组件通信 ,有点像jsonp的那种感觉
    //父组件
    export default class App extends Component{
        callback(msg){
            console.log(msg);
        }
        render(){
            return(
                <div>
                    <Sub callback = { this.callback.bind(this) } />
                </div>
            )
        }
    }
    //子组件
    const Sub = (props) => {
        const cb = (msg) => {
            return () => {
                props.callback(msg)
            }
        }
        return(
            <div>
                <button onClick = { cb("我们通信把") }>点击我</button>
            </div>
        )
    }

    小结:过程就是父组件将一个回调函数传给子组件,然后子组件调用把要传的值放进函数参数,这个回调函数最终在父组件中执行,然后父组件通过操作argument,获取值

    跨级组件通信

    • 跨级组件就是父组件向子组件的子组件传值,当然也可以更深
    • 我们可以一层层的父传子,但是这样有点傻,而且难以维护,所以有了context对象
    • context 相当于一个全局变量,是一个大容器,我们可以把要通信的内容放在这个容器中,这样一来,不管嵌套有多深,都可以随意取用。
    • 整体步骤:父组件中定义要传的属性类型,和属性的键值对--->子组件定义要接受的属性类型,和属性的名字,this.context.属性名字取值
    // 父组件
    export default class App extends Component{
      // 父组件声明自己支持 context,并且准备传两个属性,color和callback回调函数
      static childContextTypes = {
          color:PropTypes.string,
          callback:PropTypes.func,
      }
      // 父组件提供一个函数,用来返回相应的 context 对象,要传的color和callback回调函数在里面
      getChildContext(){
          return{
              color:"red",
              callback:this.callback.bind(this)
          }
      }
      callback(msg){
          console.log(msg)
      }
      render(){
          return(
              <div>
                  <Sub></Sub>
              </div>
          );
      }

    // 子组件
    const Sub = (props) =>{
      return(
          <div>
              <SubSub />
          </div>
      );
    }
    //最小子组件
    export default class SubSub extends Component{
      // 子组件声明自己需要使用 context,并且定义需要属性的名字和类型
      static contextTypes = {
          color:PropTypes.string,
          callback:PropTypes.func,
      }
      render(){
          // 直接this.context.属性名字使用
          const style = { color:this.context.color }
          const cb = (msg) => {
              return () => {
                  this.context.callback(msg);
              }
          }
          return(
              <div style = { style }>
                  SUBSUB
                  <button onClick = { cb("我胡汉三又回来了!") }>点击我</button>
              </div>
          );
      }
    }

    小结:注意要使用context时候,先声明自己要传的值得名称和属性,然后定义一个对象,里面有要传的内容,然后取的时候声明自己要取的值得名称和属性,然后直接this.context.属性名来用

    改变context对象

    • 想要改变context对象,只有让其和父组件的state或者props进行关联,也就是让context中的属性,与其结合,类似在context的回调函数值里面调用setState,这样state变化的时候,会更新context,然后子组件更新渲染
    export default class App extends Component{
      constructor(props) {
          super(props);
          this.state = {
              color:"red"
          };
      }
      // 父组件声明自己支持 context
      static childContextTypes = {
          color:PropTypes.string,
          callback:PropTypes.func,
      }
      // 父组件提供一个函数,用来返回相应的 context 对象
      getChildContext(){
          return{
              color:this.state.color,
              callback:this.callback.bind(this)
          }
      }
      // 在此回调中修改父组件的 state,这里context对象和state绑定,所以值改变了,视图也会更新
      callback(color){
          this.setState({
              color,
          })
      }
      render(){
          return(
              <div>
                  <Sub></Sub>
              </div>
          );
      }

    // 子组件
    return(
      <div style = { style }>
          SUBSUB
          <button onClick = { cb("blue") }>点击我</button>
      </div>
    );

    非嵌套组件通信

    • 解决方案为:使用事件订阅 :声明一个自定义事件,然后触发第二个参数是传递的值
    //首先下载events包
    npm install events --save
    //然后新建一个ev.js,引入包,并向外提供一个事件对象,供通信使用
    import { EventEmitter } from "events";
    export default new EventEmitter();
    //这是主页面,Foo和Boo组件非嵌套关系
    export default class App extends Component{
        render(){
            return(
                <div>
                    <Foo />
                    <Boo />
                </div>
            );
        }

    //这是Foo页面
    export default class Foo extends Component{
        constructor(props) {
            super(props);
            this.state = {
                msg:null,
            };
        }
        componentDidMount(){
            // 在组件装载完成以后// 声明一个自定义事件
                this.eventEmitter = emitter.addListener("callMe",(msg)=>{
                this.setState({
                    msg
                })
            });
        }
        // 组件销毁前移除事件监听
        componentWillUnmount(){
            emitter.removeListener(this.eventEmitter);
        }
        render(){
            return(
                <div>
                    { this.state.msg }
                    我是非嵌套 1 号
                </div>
            );
        }
    }
    //Boo页面
    export default class Boo extends Component{
        render(){
            const cb = (msg) => {
                return () => {
                    // 触发自定义事件
                    emitter.emit("callMe","Hello")
                }
            }
            return(
                <div>
                    我是非嵌套 2 号
                    <button onClick = { cb("blue") }>点击我</button>
                </div>
            );
        }
    }

    小结:就是定义一个自定义事件,然后触发传参,那边用方法接受参数,并且使用


    起源地下载网 » React 的四种常见通信场景

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元