wns9778.com_威尼斯wns.9778官网

热门关键词: wns9778.com,威尼斯wns.9778官网
wns9778.com > 计算机教程 > React使用总结

原标题:React使用总结

浏览次数:70 时间:2019-05-10

react性能提升原理:虚拟DOM

React中的组件通信

  • react 中提供的 props 与回调函数。

    解决父子组件之间的通信。这是React官方提供的方式,父组件通过props向子组件传递数据,子组件向父组件可以使用此前通过props传递的函数以回调形式通信。

  • 以事件的形式,比如观察者模式

    可用来解决兄弟组件以及远亲组件之间的通信。其中兄弟组件,也可以通过借助共同的父组件按照父子组件的通信方式来通信。观察者模式对于血缘关系远的组件保持通信,并有效解耦。但是会使得数据流向不明朗,同时给debug带来困难。

  • 基于redux

    如果使用了Redux的话,就可以利用其只有一个全局状态树的特性来进行信息的传递。Redux内部也是使用了观察者模式,对组件间的解耦提供了很多帮助。

    //创建一个store
    function reducer(state={},action){}
    let store=createStore(reducer);
    //在组件A中发布
    store.dispatch({
        type:'child_1',
        data:'hello'
    })
    //在要通信的组件B中订阅
    constructor(props){
        super(props);
        state={
            msg:"aaa"
        }
    }
    compoenentDidMount(){
        store.subscribe(()=>{
            let new_state=store.getState();
            if(new_state.type==='child_1'){
                this.setState({
                    msg:new_state.data
                })
            }
        })
    }
    

父——>子 使用props。

子组件中(我的示例中,父组件1个,子组件3个):

class Input extends React.Component{ //input子组件,class类型的组件
  constructor(props) {
    super(props);
    this.onChangeFunc = this.onChangeFunc.bind(this)
    this.onBlur = this.onBlur.bind(this)
  }
  render (){
    return <input className={this.props.color} 
                  value = {this.props.value} 
                  onChange={this.onChangeFunc}
                  onBlur = {this.onBlur}
            />
  }
  onChangeFunc(e){
    this.props.inputValueFunc(e.target.value)  //这里使用了从父组件传进来的方法
  }
  onBlur(e){
    var value = parseInt(e.target.value,10);
    if (value) {
        alert('你输入了数字')
    } else {
      alert('你输入了字符串')
    }
  }
}

class Button extends React.Component{
  render(){
    return <button className={this.props.color}>{this.props.name}</button>
  }
}

function Hello(props){  //props是从父组件中传进来的。
  return <div className={props.color}>{props.children}</div>
}

上面示例代码中,有3个子组件,其中前两个是class类组件,props是从父组件中传进来的对象。

 

父组件中:

class App extends Component {
  constructor(props){
    super(props)
    this.state = {value:'please input something'}
    this.inputValueFunc = this.inputValueFunc.bind(this)
  }
  inputValueFunc(value){
    this.setState({
      value: value
    })
  }
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>

        <Hello color='blue'>
        <h3>啦啦啦</h3>
        <p>Thank you for visiting !</p>
        </Hello>

        <Input inputValueFunc={ this.inputValueFunc } value={this.state.value} color='blue'/> //传入的props可以有方法。

        <Button color='blue' name='submit' value = {this.state.value}></Button> // 在引入子组件时候,传入props,就是上面的属性。
      </div>
    );
  }
}

组件加载(初始化):

  • constructor()对state初始化工作

    constructor(props){
     super(props);
     this.state={}
    }
    
  • componentWillMount()
    render方法之前,只执行一次

  • render()
    渲染组件挂载到网页

  • componentDidMount()
    组件加载完之后立即执行,组件已经生成DOM结构,并且已经被挂载到了网页上,可以保证数据的加载。【常在该方法中加载外部数据】

    在这儿执行setTimeout或者AJAX请求()。如果是异步获取数据,可以在componentWillUnmount中取消发送请求。
    调用setState方法会重新渲染

    为何在这儿获取数据?

    constructor中会妨碍组件的渲染;
    componentWillMount中触发setState不会重新渲染;

正文:通信

一切皆组件

不仅仅是良好的组件封装与使用的易用性,更重要的是除了要渲染出来的UI也可以当做组件。比如只是定时向服务端发送当前页面数据的请求,除此之外没有任何渲染逻辑。

import {Component} from 'react';

class postMessage extends Component{
  constructor(props){
    super(props)
  }
  componentDidMount(){
    this.timer=setInterval(function(){
      fetch('/api/fetchData')
    },1000)
  }
  componentWillUnmount(){
    clearInterval(this.timer)
  }
  render(){
    return null;
  }
}
export default postMessage;

子——>父

react中,子不能直接向父通信,解决办法是:

直接把要传的数据保存在父组件的state中,例如本例子中APP组件的state,然后在父组件中写方法,用来改变自己的state。把方法inputValueFunc传给子组件,子组件调用该方法,并把数据作为参数传给inputValueFunc。

简介Virtual DOM

上文已经提到React能够实现DOM树和真实数据状态的一致,这主要归功于其Virtual DOM的实现,使其不用使用类似MVVM的双向绑定这种方式也能保持View和Model状态的一致性。

virtual DOM的基础是virtual Node,一般是树状结构,是一个轻量级的js对象。
其用于创建真实节点的数据包括:元素类型、元素属性、元素的子节点。
首先更新virtual Dom树,对比前后两颗树的区别,将差异部分映射到实际DOM。

//得到一个virtual Node
var tree=h('div',[
    h('span','hello'),
    h('span','world')
])
//通过virtual-dom提供的createElement创建真实节点
var rootNode=createElement(tree);
//追加到页面
document.body.appendChild(rootNode);

更新

//状态变更时,重新构造一颗用js表示的DOM树
var new_tree=render(new_state);
//使用高效的diff算法,比较两颗树,记录差异
var patches=diff(tree,new_tree);
//将差异应用到真实DOM
rootNode=patch(rootNode,patches);

诺,其主要思路就如上了,如有兴趣,可以进一步欣赏其源码,网上简易版的实现也有很多。

wns9778.com,PS:标准的diff算法(如版本控制工具Git的diff)时间复杂度为O(n^3),这种代价对于在前端运行来说来高了。react结合Web界面的特点做出了两个简单的假设,将其diff算法的时间复杂度降低到O(n)。

  • 两个相同组件产生类似的DOM结构,不同的组件产生不同的DOM结构;
  • 对于同一层次的一组子节点,它们可以通过唯一的id进行区分。

两个相同组件产生类似的DOM结构,不同的组件产生不同的DOM结构;
对于同一层次的一组子节点,它们可以通过唯一的id进行区分。

react把真是的DOM tree,转化成virtual DOM,每次数据更新后,重新计算virtual DOM并与上一次的作对比,然后对发生改变的部分进行批量更新。从此性能得到提升。

PropTypes

如果props是复杂类型,使用shape 和arrayOf()

{ text:'hello world', numbers:[1,2,3]}

检测内部对象:

propTypes: {
    myObject: React.PropTypes.shape({
        text: React.PropTypes.string,
        numbers: React.PropTypes.arrayOf(React.PropTypes.number)
    })
}

子——>子

寻找最近的父组件,通过父组件通信。或者使用context,但是官方并不推荐,有可能移除(感觉不是亲生的啊,官方文档各种理由不建议使用。。。)。因此,对于大的项目,还是使用状态管理工具吧。

使用immutable.js

除了针对shouldComponentUpdate进行修改,使用不可变数据也是应用提升的方法。

js 中的对象一般是可变的,因为使用了引用赋值,新的对象简单的使用了原始对象,改变新的对象也将影响到原始对象,如:

foo={a:1};bar=foo;bar.a=2

则foo.a也成了2,虽然这样可以节约内存,但是应用复杂之后,带来隐患。一般的解决方法是使用浅拷贝和深拷贝(针对Object /Array复杂对象)避免被修改,但造成了CPU和内存的浪费。

  • 浅拷贝:只复制一层对象的属性,而js存储对象都是存地址,所以浅拷贝的对象指向同一块内存地址,会同时修改。
  • 深拷贝:递归复制所有层级到新对象。
//方法1:通过递归
function deepCopy(o, c) {
   var c = c || {}
   for (var i in o) {
       if (typeof o[i] === 'object') {
           if (o[i].constructor === Array) {
               c[i] = []
           } else {
               c[i] = {}
           }
           deepCopy(c[i], o[i]);
       } else {
           c[i] = o[i]
       }
       return c;
   }
}
//方法2:通过json解析
var result = JSON.parse(JSON.stringify(test))

Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是 Persistent Data Structure(持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。

同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗,Immutable 使用了 Structural Sharing(结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。


高阶组件

const HoC = (WrappedComponent) => {
    const WrappingComponent = (props) => (
        <div className="foo">
            <WrappedCompoent {...props} />
        </div>
    );
    return WrappingComponent;
};

高阶组件中可以传入任意多个想要传入的组件。

const HoC = (WrappedComponent, LoginView) => {
    const WrappingComponent = () => {
         const {user} = this.props;  
         if (user) {
            return <WrappedComponent {...this.props} />
         } else {
            return <LoginView {...this.props} />
         }
    };
    return WrappingComponent;
};

本文由wns9778.com发布于计算机教程,转载请注明出处:React使用总结

关键词: wns9778.com

上一篇:C# 添加、修改以及删除Excel迷你图表的方法

下一篇:没有了