zoukankan      html  css  js  c++  java
  • React 精要面试题讲解(二) 组件间通信详解

    单向数据流与组件间通信

     上文我们已经讲述过,react 单向数据流的原理和简单模拟实现。结合上文中的代码,我们来进行这节面试题的讲解: react中的组件间通信。
    
     那么,首先我们把看上文中的原生js代码:
    
            function child(props){
               this.props = props;
            }
           function parent(props){ 
               this.props = props              
               this.state = '这是父函数的一个状态'
               this.childNodes  = new child(this.state); 
            }
           console.log(new parent('这是一个属性'));
    
     ok,经过运行,我们发现打印结果的结构 和 react父子组件的关系结构是极为类似的,子函数通过props形参接受到父函数的state。
     这个好理解吧?那么在说react组件通信之前,我们基于原生继续模拟父子组件间的通信。
     如上文代码所示,我们已经实现了父函数通过props这个形参向子函数传递数据——是的,相对而言,在react中,父组件通过props(规定了只能通过props传递及获取)向子组件进行数据传递。换句话讲,props这个实例属性,表面唯一的作用就是参数传值…
    

    那么,我们接来下要思考一个问题,如何在上述代码中实现 子函数向父函数传递数据?

     如果我们把函数玩的够熟练,那么很容易会思考到以下实现方式:
    
            function child(props){
               this.data = '我是子函数中的data'
               props.getChildData(this.data);
               this.props = props;
            }
           function parent(props){ 
               this.props = props;             
               this.dataFromChild = null;
               this.getChildData = (data)=>{
                    console.log('这个函数被运行了,我们拿到了传过来的参数:'+data);
                    this.dataFromChild = data;
               }
               this.childNodes  = new child({
                    getChildData:this.getChildData
                }); 
            }
           console.log(new parent('这是一个属性'));   
    
    (别偷懒!f12,复制上述代码到控制台运行!)
    好的,简单说下上述代码做出的更改: 
    1  父函数中定义了一个函数,通过参数对象(实则就是props啊)传递给了子函数;
    2  这个函数一旦被执行,会把参数data赋值给父函数中的实例属性data;
    3  子函数通过props接收到了这个函数,运行了它,并且把自己的data作为参数传递了进去;
    
    ok,那么我们经过运行,发现控制台打印的内容:
    

    哦!!!于是我们明白了,我们写原生js的时候,就是通过:
    在父函数中定义方法,通过参数传递给子函数,子函数调用这个方法并且把自己数据作为参数,那么父函数就可以通过形参拿到了~
    什么?有点绕?那么说的再简单点:
    父函数的方法传递给子函数,被子函数传参调用。
    那么赶紧用内存不足的大脑思考思考react中是不是也可以啊?

            class Child extends React.Component{
                data =  '我是子组件中的data'
                render(){
                    this.props.getChildData(this.data);
                    return <div>我是Child组件</div>
                }
            }
           class Parent extends React.Component{
                childData=null
                getChildData = (data)=>{
                    this.childData = data;
                     console.log(data);
                }
                render(){
                    return <Child getChildData = { this.getChildData }  />
                }
            }
        console.log(<Parent  />)
    
     上面的代码够简练了吧(比中指)!
     那么我们运行上述代码发现——乖乖,真的拿到了~~这不还是一样吗?我们玩的不是react吗?怎么成原生js 了啊?啥啊谁啊我在哪啊??
    

     实则所有单向数据流的js框架都可以通过上述的方式进行子组件向父组件的通信。
     非常好,现在我们来整理一下react的父子组件间通信规则: 
     *父传子:  父组件通过props传参呗……*
     *子传父 : 父组件通过props传参呗……*
     啥? 我写重了? 
     (哼哼一声我露出了鄙视的微笑,并在下面多写了一行)
     ***子传父完整版: 父组件中定义函数,通过props传递给子组件,子组件调用这个函数并传参。***
    嗯…经过思考,我们得出了这样一个结论: 子传父这样的逆向通信,实际也是符合单向数据流的概念。无非就是把函数当做参数传递下去而已啊!!!(重点是这句啊~~~react中的逆向通信的方式和单向数据流完全不冲突啊~)
    

    子传父(逆向通信)的其他方式

      除开上面讲过的 父组件中定义函数传递给子组件并被其调用 这种js通用方式,在react中我们还可以怎样玩?
      在Vue,React中都有ref 这样一个特殊的实例属性。
      react中 ref 具备两种作用: 
      1   标记dom的话,能获取dom实例;
      2    标记子组件的话,能获取子组件实例的所有数据(包括子组件的props,state,定义的方法,实例…)。
      那么也就是说,父组件通过this.ref就拿到子组件的任何数据了…就这么简单啊。
      当然,依照react的尿性,文档中特意提到了一点:不要轻易用这玩意啊,危险啊,别冲动啊小伙子们~
      事实上,经过react的版本变化,ref赋值目前有三种方式 :  字符串、回调、 CreateRef() //这个是16.3后的新增api
      迭代维护做的都很到位啊~ 凭啥只用在表单控件里啊~
      当然,关于ref的花式玩法我们会在本系列后面内容讲到。
    

    远亲组件的通信

      其实无论做react还是vue或者其他项目,我们必须要明确,写的还是js。(这也是为什么我一直把原生和react放在一起讲)
      那么远亲组件的通信,我们即时对react毫无了解,也能至少说出一万种方式…
     例如: 
          1   通过缓存  :  组件A把数据存到缓存中,组件B就可以从中取出; 
          2   通过url  :  通过location对象拿到…; 
          3   通过与后端配合: 组件A把数据扔到接口里去,组件B可以从中拿到…;
      以上方式,我称之为通过第三方媒介的形式。
      (插一句: 有木有觉得redux中store共享跟session级别缓存很类似?)
      也就是说,远亲组件的通信,我们抛开react去思考得出一个结论:
      ——通过第三方媒介作为一个存储地点,实现数据共享。
     
       ok我们把话题转回来。react中,同系远亲的话(太太爷爷到重重孙子),完全可以通过context嘛(上一篇有讲,后面也会出context的专章)…
       至于不是很远的关系, 利用props一层一层往内传啊。 (例如爷爷传到孙子)
       
       逆向: 子调用爷爷的函数并传参就实现了子传爷爷;
       同级 : 子1传父,父传子2 ; 
       很远关系: 1 context(自己实现试试啊~)  2 通过第三方媒介共享( 缓存,url,服务端,以及后面我们会讲到的redux,react-redux,dva等全局状态存储管理插件);
       我们发现,就单单react的话,传来传去还是 父传子 子传父啊……最多特殊情况用到context(无论多远的关系,最终肯定有个统一的祖宗啊<App ==!/>)而已啊~
    

    总结

       这章讲述了react的基础必面的面试题:
       如何在react项目中实现组件间的通信。
       也可能会引发一些react与项目与原生的思考(这是我想要的)。
       
    
       如果本章内容对您有帮助,请点个推荐哦~
  • 相关阅读:
    css伪类和伪对象
    多浏览器css兼容分析小结
    Hibernate3源码分析之hibernate.cfg.xml配置文件与SessionFactory类
    php示例代码之使用mysqli对象
    C#中Web Service身份验证
    未能转换为类型库。类型库导出程序在处理,时遇到了错误。错误: 找不到元素
    MS RDLC reportview 在 Chrome中不显示查询结果的原因
    C# 创建ActiveX
    How to rebuild performance counters on Windows Vista/Server2008/7/Server2008R2
    jqGrid中文说明文档——选项设置
  • 原文地址:https://www.cnblogs.com/sanchang/p/10516067.html
Copyright © 2011-2022 走看看