by 09 react学习感悟 - nuanxin1111/react GitHub Wiki

#React学习

##React学习路线

1.关于React的学习,首先看视频,7节视频。1.5~2倍速度快速过一遍
然后根这个中文网,快速理解一下。
http://reactjs.cn/react/docs/getting-started.html

2.这里的文章都不错。至少先看快速入门的前三章节

快速入门,教程,深入理解React这三节,务必把代码粘到sublime上,
亲自体验一把。

3.理解一些关键点,尝试写代码。。。

##React需要理解的要点

###React需要理解的两个东东

props属性字段,用来存一些父组件传给子组件的数据,子组件可以通
过this.props.属性名 的方式获取父组件传递给子组件的值,一般可用
来初始化静态数据,即下文中不期望会改变的值

state状态字段,用来存放将来可能会因为某种情况改变的字段,例如
当界面有个字段1.当用户点击一下按钮时,这个字段就会变成2,为了
让它能在改变后及时渲染到页面上,可以将这个字段设置为一个state,
然后在鼠标的点击让其加1并且重新设置state
    construct(){
        super();
        this.state = {num:1};
    }
    
    onclick(){
        let num = this.state.num;
        this.setState({num:num++});
    }
当调用state时,与state相关联的组件会被重新render,就是所谓的React状态机
的机制,当state改变时,其相关的东东跟着变
在确定state的时候以尽量精简为原则,比如你已经有了列表,就没必要吧列表的
长度设置为state.因为你完全可以根据list.length得到。
如何确定state的值是一个值得深入思考的问题,需要在实践中慢慢感悟。。。

###关于父组件与子组件的传值

####父组件给子组件传值 这个比较简单可以直接通过props或者state

    //子组件
    class Child extends React.Component{
        render(){
            <div>
                {this.props.value}
            </div>
        }
    }
    //父组件
    class Parent extends React.Component{
        render(){
            <div>
                <Child value={1} />
            </div>
        }
    }
说明:父组件在render子组件的时候可以为子组件赋予一些自定义的属性,属性名
可以是任意的,比如在父组件里定义了value=... ,那么子组件就可以通过
this.props.value获取。也可以通过state给子组件传值
    //子组件
    class Child extends React.Component{
        render(){
            <div>
                {this.props.value}
            </div>
        }
    }
    //父组件
    class Parent extends React.Component{
        construct(){
            super();
            this.state = {value:1};
        }
    
        render(){
            <div>
                <Child value={this.state.value} />
            </div>
        }
    }
说明:这样一来,父组件的state.value的值改变后,子组件的值也将会跟着渲染
因为value值变化导致props.value的值也跟着变化,跟state有关的变化会跟着联动。

####子组件为父组件传值

亦或者,父组件获得子组件的值。
主要通过两种方式:

1.为子组件需要被父组件获得的地方加上ref,这样父组件就可以通过this.refs.子组件的ref名。
获得子组件的内容,可以通过子组件的ref找到子组件,然后通过它的ref再找到子组件的组件。
嵌套层次可以无限制,但是嵌套太深逻辑也将变得复杂。这种处理的方式有一个很大的限制就是
只能通过父组件主动的寻找子组件去获取值,不能更智能,这种方式一旦使用意味着,只有当父组件
主动调用方法时,才能获得值。与回调函数成对比

2.回调函数。例如子组件里有个文本框和按钮,父组件想要当子组件点击按钮时候获得到子组件的
文本框的值,那么父组件可以提前定义一个函数参数为一个的函数。以属性的方式传递给子组件,
子组件通过click事件,执行this.props.父组件预留的函数 的方式,这样就会执行到父组件提前
写好的逻辑里。是一种非常灵活的方法,但是同样由于层次太深,导致的不方便是存在的。这种方式
在react里将大量使用,习惯就好。。。
    //子组件
    class Child extends React.Component{
        myclick(msg){
            //此处调用父组件传给他的方法
            this.props.parentMed(this.refs.t1.value);
        }
    
        render(){
            <div>
                <input type='text' ref="t1"/>
                <input onClick={()=>{this.myclick()} />
            </div>
        }
    }
    //父组件
    class Parent extends React.Component{
        construct(){
            super();
        }
        
        Med(msg){
            alert(msg);
        }
        
        render(){
            <div>
                <Child value={this.state.value} parentMed={(msg)=>{this.Med(msg)}}/>
            </div>
        }
    }
    
这个demo演示父组件是如何通过回调函数获得子组件的值,当得到子组件的值后父组件就可以进行
编写相应的逻辑使用它的值

####兄弟节点的值得交互

A------B
    |
    |__C
    
假设B和C是兄弟组件,那么要想交互的话可以通过为它们建立公共的组件A,
然后通过A为双方提供数据。

##React组件编写实战经验

用React编程的重要体验就是不在是单纯的写html。而是用代码逻辑的方式去思考,怎么组织
组件可以被后面重复利用,当需要在使用相同功能的情况下,不是在去吧代码写一遍,而是
直接把代码拿过来用就可以。

###组件的设计构建

方案1:
在组件设计的时候,我有想过两种方案,一种是父组件得到的数据,当子组件需要的时候,直接
让父组件通过props属性传递给子组件,那么子组件就不需要访问网络,查询数据库,这种方案的
优点是一次性获取的数据,不需要再第二次重复获得,节省了带宽和与服务器的数据交互,当子
组件修改数据后,再通过父组件的回调函数,对父组件的一些数据做相应的同步,那么子组件与
父组件的整体就同步了。这种方案在实际当中编写起来相对复杂,但是一旦实现后可以做为独立
模块维护,但是缺点也很明显,数据耦合性太高,东西太死。很大的可能性就是在这个页面用完
以后,很难移植到下一个页面

方案2:
父组件设计的时候通过ajax请求获得想要的数据,当数据需要向下传递时候,子组件虽然也要用到
与父组件的相同一部分数据,但是子组件不接受全部数据。例如父组件需要订单的信息以及订单的
状态信息,这需要两张表的查询,子组件也需要这些数据,这时候只给子组件传递一个订单id,让子
组件根据订单id再次发送ajax请求去查询自己需要的数据。这种方式的好处就是父组件与子组件
的耦合性降低,当子组件被应用到其他场合时,不需要依赖父组件的数据,可以随时分离出来应用于
其他场合,但是缺点也显而易见,父组件已经获得到的数据,还需要子组件去请求一遍,增加了一次
与服务器的交互,与多花费了一些流量。如果服务器的响应速度比较慢,那么性能损失上还是比较明
显的。但是这种交互方式的好处就是配合路由使用的时候,每次发ajax请求,得到的都是最新的数据。
父子组件在数据更新时,不需要做太多处理,只要是数据提交到了服务器,那么另一个组件重新请求
时候获得的当时是最新的了。

方案3:
1和2的折中,既抽象部分的接口,又提供部分的数据,在解耦上面做文章。难度大,不易抽象出来
思考需要大量的时间,当需求提出变更时候,组件是否需要做相应的改动是个问题,维护起来比较费劲

个人倾向第二种解决方案,这样开发起来方便。需求变更时候更改起来容易

###组件设计的大小

当一个组件设计的足够大时候,它的功能也就意味着更加复杂,职责更加多。当然带来的便利性也是
显而易见的,当需要使用这一坨功能的时候,把它引入就OK。
当一个组件设计的太小的时候,会很灵活,但也可能会导致引用过多,变的麻烦
一切以需求为导向,在不断的尝试中找到合适的平衡点很重要。。。

###组件使用--套路

目前的解决套路:
1.组件类的构造函数内部初始化state为空或者默认值,为将来通过ajax请求获取数据做准备。

#####这里有个坑需要关注的是

如果数据不存入state中,很有可能页面渲染完了,ajax的请求的响应结果才过来,
虽然数据已经来了。但此时不会重新渲染界面。而导致非目标结果

2.在组件已经挂载时调用ajax请求数据,在success时候,更新state,渲染页面数据.

3.提前布局回调函数,当子组件触发某些事件,例如按钮点击,通过回调函数,将数据返回给父组件,
父组件内做相关逻辑处理。

###实现路由(路由原理)。

路由的本质还是通过对React状态机机制的一层包装,即在不同的情况下渲染不同的页面,
那么这个不同的体现就是通过state的值做判断

那么直接上代码,假设有页面A和页面B,初始化的时候是页面A,当点击A上的一个项时候跳到B。
在B中点返回,返回A
    class Manager extends React.Component{
        construct(){
            this.state = {pageName:'A'};
        }
        
        setPage(pageName,args){
            //args为页面参数,js对象做参数,可以传输大量信息
            this.setState({pageName:pageName,pageArgs:args});
        }
        
        render(){
            let child;
            if(this.state.pageName =='A'){
                child = <A setPage={(p,a)=>{this.setPage(p,a)}/>
            }else if(this.state.pageName =='B'){
                child = <B setPage={(p,a)=>{this.setPage(p,a)}/>
            }
        
            <div oncClick={}>
                {child}
            </div>
        }
    }
    

    
    class A extends React.Component{
        
        goToB(){
            this.props.setPage('B',{});
        }
        
        render(){
            <div onClick={()=>{this.goToB()}}>
                我是A组件,点我进入B组件
            </div>
        }
    }
    
    class B extends React.Component{
        construct(){
            super();
        }
        
        returnToA(){
            this.props.setPage('A',{});
        }
        
        render(){
            <div onClick={()=>{this.returnToA()}}>
                我是B组件,点我返回组件
            </div>
        }
    }

##后记

当做惯后端后,再去接触前端,会发现,前端东西很乱很杂,但是很多细节不会还真做不出来某些效果
确实是比较蛋疼的事情,有时候后台代码BUG见多了,一般无非就那些,一会就能调完,可是前端做起来
并不是那么一帆风顺,不熟是一个原因,但是其他因素也有很多,有时候确实会感觉,做前端也不比后端
简单多少。传统的HTML模板机制,mvc思想,给我们一种编程体验,让代码显得更有逻辑,更可控制,
React更是给了我们一种关于界面层的编程的新思想,深入学习REACT,不只是因为它太高大尚,更是学习
一种编程思想,至少通过这种组件化的编程体验带给我们的收获是,不断的写组件,复用组件,在这种
可以快速见效的东西面前,不断探索。一个组件设计的好坏,就是看下次遇到相同需求时候,能不能直接
复用自己的组件,虽然否定自己是件痛苦的事情。但是修改代码后获得更好的组件体验也很重要。
其实前端后端做久了,感觉编程思想还是蛮重要滴,不断地在实践中感悟吧。

##经典语录大放松

路叔,你可以的

路叔,你真棒

加油,路叔。

都快要猝死的人了。。。
⚠️ **GitHub.com Fallback** ⚠️