03-React事件处理 & 生命周期 & Diffing算法

React事件处理

背景

1.通过onXxx属性指定事件处理函数(注意大小写)

  • React使用的是自定义(合成)事件, 而不是使用的原生DOM事件
比如原生onclick的事件在React中变成了onClick,这么搞是为了更好的兼容性
  • React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)
比如,div标签中有input,button等标签,这里面的事件最终都会被委托给最外层的div上

事件委托的原理是事件冒泡,这么做的原因是高效

2.通过event.target得到发生事件的DOM元素对象 ~~~ 不要过度使用ref

受控组件与非受控组件

功能:需求: 定义一个包含表单的组件
输入用户名密码后, 点击登录显示输入的信息
03-React事件处理 & 生命周期 & Diffing算法_第1张图片

非受控组件(不推荐)

非受控组件主要是用ref来做管理,而ref获取的是DOM,React官方建议少用ref

比如一个表单,点击button进行提交的这个动作,作为H5的默认动作,默认是不阻止提交的,这个就叫非受控组件

03-React事件处理 & 生命周期 & Diffing算法_第2张图片

<script type="text/babel">
    class Login extends React.Component{
        handleSubmit=()=>{
            //阻止默认的表单提交
            event.preventDefault()
            // 解构对象,拿到ref设置的DOM
            // 其实这是一种现用现取的逻辑,所以是非受控组件
           const {username,password} =this
           alert(`${username.value},${password.value}`)
        }
        render(){
            return (
                <div>
                    <form action="www.atguigu.com" onSubmit={this.handleSubmit}>
                        {/*将属性通过ref设置到对象身上,以便使用时获取*/}
                        用户名<input ref={(c)=>this.username=c} type="text" name="username"></input>
                        密码<input ref={(c)=>this.password=c} type="password" name="password"></input>
                        <button>登陆</button>
                    </form>
                </div>
            )
        }
    }
    ReactDOM.render(<Login/>,document.getElementById("test"))
</script>

受控组件(推荐)

页面中所有输入的DOM(input,radio…等等),输入的时候,就把输入的内容,set到state里面,等需要用的时候,再取出来
而不是像非受控组件一样,等到需要用的时候,再去现获取。而且非受控组件写了大量的ref属性,在React看来也是不推荐的写法(类似vue双向绑定)

例子:
03-React事件处理 & 生命周期 & Diffing算法_第3张图片
03-React事件处理 & 生命周期 & Diffing算法_第4张图片

稍加修改,我们把数据暂存到state里面,用state来暂存可以达到同样的效果
03-React事件处理 & 生命周期 & Diffing算法_第5张图片
如果是多个的属性,用ref获得到大量的DOM元素就会很乱,不如统一扔进state更方便

最后代码:

<script type="text/babel">
    class Login extends React.Component{
        //初始化一下state,如果不写也可以
        state={
            username:"",
            password:""
        }

        // 管理表单中的n多个属性
        saveUsername=(event)=>{
            //set的时候用this.setState({key:value})
            this.setState({username:event.target.value})
        }
        savePassword=(event)=>{
            // 注意要用setState的API,如果是this.state就会被认为是更新操作
            this.setState({password:event.target.value})
        }
        showValue=(event)=>{
            //阻止提交后发生跳转
            event.preventDefault()
            // 解构,这时就得到的属性,而不是之前的DOM了
            const {username,password}=this.state
            //所以就不再需要再像ref一样去DOM.value,因为直接获取到的就是属性,而不是DOM
            console.log(username,password)
        }
        render(){
            return (
                <div>
                    <form onSubmit={this.showValue}>
                        {/*每次change的时候都会实时同步到state里面*/}
                        用户名<input onChange={this.saveUsername} type="text" name="username"></input>
                        密码<input onChange={this.savePassword} type="password" name="password"></input>
                        <button>登陆</button>
                    </form>
                </div>
            )
        }
    }
    ReactDOM.render(<Login/>,document.getElementById("test"))
</script>

03-React事件处理 & 生命周期 & Diffing算法_第6张图片

着重注意一下这里,其实就是ref 解构出来DOMstate 解构出来属性上的区别
03-React事件处理 & 生命周期 & Diffing算法_第7张图片

柯里化概念

只有函数才有柯里化

高阶函数: 如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数。

  • 若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。
  • 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
    常见的高阶函数有: Promise、setTimeout、arr.map()等等

函数的柯里化: 通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式

高阶函数——函数柯里化

上面的内容其实不难发现,有很大优化空间

比如:
如果有大量的属性,那么复用性很差,有大量冗余,所以不建议这么搞

   // 管理表单中的n多个属性
   saveUsername=(event)=>{
       //set的时候用this.setState({key:value})
       this.setState({username:event.target.value})
   }
   savePassword=(event)=>{
       // 注意要用setState的API,如果是this.state就会被认为是更新操作
       this.setState({password:event.target.value})
   }
<input onChange={this.saveUsername} type="text" name="username"></input>

理所当然的就想着抽共同调用,抽共通的话就需要把当前的key的名字传进去

重点来了

从这样

<input onChange={this.saveUsername} type="text" name="username"></input>

到这样

<input onChange={this.saveUsername("username")} type="text" name="username"></input>

会有一个问题,就是this.saveUsername是一个属性this.saveUsername("username")是一个函数,而这个函数是没有返回值的!
这样就会导致onChange得到的函数return一个undefined。这里的undefined是因为没有标记return

所以怎么办呢,就是把函数的return用箭头函数改造一下!我让return有返回值,但是返回一个空的箭头处理,即有了返回值,又有了处理。

 // 管理表单中的n多个属性
 saveValue = (value) => {
   //这个event是React自动传入,我们无法手动set,所以不能在方法里传入
   return (event) => {
     this.setState({ [value]: event.target.value });
   };
 };
 //调用时传入key
<input onChange={this.saveUsername("username")} type="text" name="username"/>

这里为什么value要用[ ]套一下?

this.setState({ [value]: event.target.value });
这里的value用[]套一下是因为它是当前对象的一个变量,而不是一个字符串。在JavaScript中,当你使用方括号([])来访问对象的属性时,如果属性名是一个变量,那么你需要将变量放在方括号内。这样,你就可以动态地访问和设置对象的属性值。
换句话说,这个方括号([]),直接把value从字符串转换成对象的一个属性了

03-React事件处理 & 生命周期 & Diffing算法_第8张图片

贴上完整代码:

<!--JSX转换成JS用的依赖,因为浏览器不认识JSX,只认识JS-->
<script type="text/babel">
  class Login extends React.Component {
    //初始化一下state,如果不写也可以
    state = {
      username: "",
      password: "",
    };

    // 管理表单中的n多个属性
    saveValue = (value) => {
      //这个event是React自动传入,我们直接取值即可
      return (event) => {
        this.setState({ [value]: event.target.value });
      };
    };

    render() {
      return (
        <div>
          <form>
            用户名
            <input
              onChange={this.saveValue("username")}
              type="text"
              name="username"
            ></input>
            密码
            <input
              onChange={this.saveValue("password")}
              type="password"
              name="password"
            ></input>
            <button>登陆</button>
          </form>
        </div>
      );
    }
  }
  ReactDOM.render(<Login />, document.getElementById("test"));
</script>

不用柯里化的写法

不用柯里化对其进行改造,也就是不再采用上面的return箭头函数

关键在于在标签里就把event传进去
改造一下,此时event就直接传入方法了:

<input onChange={(event) => {this.saveValue("username", event)} type="text" name="username" ></input>

saveValue = (value, event) => {
  this.setState({ [value]: event.target.value });
};

测试效果是一样的,好用

全部代码:

<script type="text/babel">
 class Login extends React.Component {
    //初始化一下state,如果不写也可以
    state = {
      username: "",
      password: "",
    };

    // 管理表单中的n多个属性
    saveValue = (value, event) => {
      this.setState({ [value]: event.target.value });
    };

    render() {
      return (
        <div>
          <form>
            用户名
            <input
              onChange={(event) => {
                this.saveValue("username", event);
              }}
              type="text"
              name="username"
            ></input>
            密码
            <input
              onChange={(event) => {
                this.saveValue("password", event);
              }}
              type="password"
              name="password"
            ></input>
            <button>登陆</button>
          </form>
        </div>
      );
    }
  }
  ReactDOM.render(<Login />, document.getElementById("test"));
</script>

React生命周期

React生命周期可以分为旧版和新版,这里旧版生命周期并非弃用,新版只是在旧版生命周期的上面,废弃了三个API,新增了两个API,所以还是有学习旧版生命周期的必要性。

旧版生命周期

可以看到,可以分为两大部分,分别为挂载初始化时组件更新时

render函数贯穿两大部分,因为无论是初始化,还是组件更新,都需要重新渲染,diffing差分等等。

每个部分都有对应的函数供我们使用。

03-React事件处理 & 生命周期 & Diffing算法_第9张图片

初始化阶段API(由ReactDOM.render()触发—初次渲染)

主要集中于这四个API,无论代码的顺序如何,都会按照这个生命周期的顺序进行执行。
03-React事件处理 & 生命周期 & Diffing算法_第10张图片

  • 1、constructor()
    完成了React数据的初始化,state设值等等。

  • 2、componentWillMount()
    组件已经完成初始化数据,但是还未渲染DOM时执行的逻辑,主要用于服务端渲染,网络请求等。

  • 3、render()
    组件开始渲染真实DOM。

  • 4、componentDidMount()
    组件第一次渲染完成时执行的逻辑,此时DOM节点已经生成了。

代码:

<script type="text/babel">
  class Login extends React.Component {
    constructor(Props) {
      super(Props);
      console.log("constructor 执行");
    }

    componentWillMount() {
      console.log("componentWillMount 执行");
    }

    componentDidMount() {
      console.log("componentDidMount 执行");
    }

    render() {
      console.log("render 执行");
      return <div>123</div>;
    }
  }
  ReactDOM.render(<Login />, document.getElementById("test"));
</script>

执行可以发现,按照生命周期的顺序输出
03-React事件处理 & 生命周期 & Diffing算法_第11张图片

更新阶段API(由组件内部this.setSate()或父组件重新render触发)

一般来说,更新阶段API都是在属性变更时触发,比如state属性变化,页面上组件变化,就会触发更新阶段的API
03-React事件处理 & 生命周期 & Diffing算法_第12张图片

  • 1、componentWillReceiveProps(nextProps)
    接收父组件新的props时,重新渲染组件执行的逻辑,括号里的参数可以选择接收之后打印一下。注意,这个API在初次接收的时候是不会更新的,只有第二次接收之前才会触发

  • 2、shouldComponentUpdate(nextProps, nextState)
    在setState以后,state发生变化,组件会进入重新渲染的流程时执行的逻辑。在这个生命周期中return false可以阻止组件的更新,主要用于性能优化。

  • 3、componentWillUpdate(nextProps, nextState)
    shouldComponentUpdate返回true以后,组件进入重新渲染的流程时执行的逻辑。

  • 4、render()
    页面渲染执行的逻辑,render函数把jsx编译为函数并生成虚拟dom,然后通过其diff算法比较更新前后的新旧DOM树,并渲染更改后的节点。

  • 5、componentDidUpdate(prevProps, prevState)
    重新渲染后执行的逻辑。

父子组件传值例子:

定义了两个类组件(A组件 , B组件),B组件在A组件内使用,A组件向B组件传值,每次只要值更新,就会触发更新生命周期函数

<script type="text/babel">
  class A extends React.Component {
    // 给state默认值
    state = {
      car: "宝马",
    };
    // 更新传入值
    changeCar = () => {
      this.setState({ car: "奥迪" });
    };

    render() {
      return (
        <div>
          <div>A组件</div>
          <button onClick={this.changeCar}>更新组件,给B传值触发更新</button>
          {"B组件传入A的state属性"}
          <B car={this.state.car} />
        </div>
      );
    }
  }

  class B extends React.Component {
    render() {
      return <div>{this.props.car}</div>;
    }
  }

  ReactDOM.render(<A />, document.getElementById("test"));
引出API

在这个传值的过程中会触发很多生命周期API,挨个试验一下

  • 1、componentWillReceiveProps(nextProps)
    接收父组件新的props时,重新渲染组件执行的逻辑,括号里的参数可以选择接收之后打印一下。注意,这个API在初次接收的时候是不会更新的,只有第二次接收之前才会触发

03-React事件处理 & 生命周期 & Diffing算法_第13张图片


  • 2、shouldComponentUpdate(nextProps, nextState) 参数不传也完全可以
    setState操作就会触发这个钩子,,state发生变化,组件会进入重新渲染的流程时执行的逻辑。在这个生命周期中return false或不指定返回内容(默认undefined) 可以阻止组件的更新相当于更新组件的阀门

03-React事件处理 & 生命周期 & Diffing算法_第14张图片
稍微修改一下代码,手动return true,就可以继续更新组件了

 shouldComponentUpdate() {
   console.log("shouldComponentUpdate 执行了!");
   return true;
 }

03-React事件处理 & 生命周期 & Diffing算法_第15张图片


  • 3、componentWillUpdate(nextProps, nextState)参数不传也完全可以
    shouldComponentUpdate返回true以后,组件进入重新渲染的流程时执行的逻辑。通俗讲就是渲染前的钩子
  • 4、render()
    页面渲染执行的逻辑,render函数把jsx编译为函数并生成虚拟dom,然后通过其diff算法比较更新前后的新旧DOM树,并渲染更改后的节点。
  • 5、componentDidUpdate(prevProps, prevState)参数不传也完全可以
    重新渲染后执行的逻辑。通俗讲就是渲染完毕后的钩子
    03-React事件处理 & 生命周期 & Diffing算法_第16张图片

代码(这里只有更新阶段钩子)

<script type="text/babel">
    class A extends React.Component {
      // 给state默认值
      state = {
        car: "宝马",
      };
      // 更新传入值
      changeCar = () => {
        this.setState({ car: "奥迪" });
      };

      shouldComponentUpdate() {
        console.log("A标签的 shouldComponentUpdate 执行了!");
        return true;
      }

      componentWillUpdate() {
        console.log("A标签的 componentWillUpdate 执行了!(组件渲染前)");
        return false;
      }

      componentDidUpdate() {
        console.log("A标签的 componentDidUpdate 执行了!(组件渲染完毕)");
        return false;
      }

      render() {
        console.log("A标签的 render 执行了!");
        return (
          <div>
            <div>A组件{this.state.car}</div>
            <button onClick={this.changeCar}>更新A组件</button>
          </div>
        );
      }
    }
    ReactDOM.render(<A />, document.getElementById("test"));
  </script>
组件卸载(由ReactDOM.unmountComponentAtNode()触发)

最后一个API,在组件卸载之前触发

  • componentWillUnmount()

组件卸载方法:ReactDOM.unmountComponentAtNode()

组件的卸载前执行的逻辑,比如进行“清除组件中所有的setTimeout、setInterval等计时器”或“移除所有组件中的监听器removeEventListener”等操作。

旧版生命周期总结

03-React事件处理 & 生命周期 & Diffing算法_第17张图片

1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
		1.	constructor()
		2.	componentWillMount()
		3.	render()
		4.	componentDidMount() =====> 常用
			一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
2. 更新阶段: 由组件内部this.setSate()或父组件render触发
		1.	shouldComponentUpdate()
		2.	componentWillUpdate()
		3.	render() =====> 必须使用的一个,不渲染没法显示
		4.	componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
		1.	componentWillUnmount()  =====> 常用
			一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

新旧生命周期对比

新版本生命周期相对于旧版本,废弃了三个带will的API(componentWillMount(),componentWillReceiveProps(),componentWillUpdate())
新增了两个API static getDerivedStateFromProps(),getSnapshotBeforeUpdate()

03-React事件处理 & 生命周期 & Diffing算法_第18张图片
注意:对于已经过时的API不会马上废弃,而是在控制台进行Warning提醒,并且在后续的React版本中,如果非要使用过时的API,就必须在API的前缀上加入UNSAFE_前缀,作为提醒。
比如,从React17版本开始就得加入前缀:
03-React事件处理 & 生命周期 & Diffing算法_第19张图片

注意,这里的API UNSAFE并不是说这个API就会有安全问题,而是说在未来的预计更新中有概率出现问题。
比如现在切换到React 17版本,再使用过期API就会有提示
在17版本下,使用过时的componentWillMount,PS:这里选的是不需要条件就可以触发的API,另外两个过时的API触发都需要条件

 componentWillMount() {
   console.log("componentWillMount执行");
 }

03-React事件处理 & 生命周期 & Diffing算法_第20张图片

这几个UNSAFE_ 的API本身用的频率就很低,所以了解一下即可

新版生命周期

初始化阶段API

03-React事件处理 & 生命周期 & Diffing算法_第21张图片


  • 1、constructor()

完成了React数据的初始化,state设值等等。之前写过就不赘述了


  • 2、static getDerivedStateFromProps()

首先这个组件是静态的,如果不用static,就会报错。看控制台报错,说明这个方法不属于对象,需要用static来进行声明
在这里插入图片描述

组件挂载阶段render前的最后一次调用,并且在初始挂载及后续更新时都会被调用。适用于第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子)。返回一个state就更新state,返回一个null就不做更新动作

可以传入props和state

static getDerivedStateFromProps(props,state){
	console.log('getDerivedStateFromProps',props,state);
	return null
}

03-React事件处理 & 生命周期 & Diffing算法_第22张图片

如果这个位置返回一个固定的state的对象,那么这个return的值就会一直影响state,导致其无法更新,因为其return的值是一个固定的state。那肯定就更新不了state了。

 static getDerivedStateFromProps(props, state) {
   console.log("getDerivedStateFromProps", props, state);
   return {"key":"value"};
 }

举一个props影响state的例子,用react的官方例子:
03-React事件处理 & 生命周期 & Diffing算法_第23张图片
03-React事件处理 & 生命周期 & Diffing算法_第24张图片


  • 3.render()

组件挂载依靠这个api,不render就不会重新渲染,之前说过,这里不赘述了


  • 4.componentDidMount()

组件挂载完毕之后触发的,也就是render之后

//组件挂载完毕的钩子
componentDidMount(){
	console.log('Count---componentDidMount');
}

03-React事件处理 & 生命周期 & Diffing算法_第25张图片

更新阶段API

主要集中在这5个钩子
03-React事件处理 & 生命周期 & Diffing算法_第26张图片


  • 1.getDerivedStateFromProps()
    贯穿于组件挂载阶段和更新阶段的API,React 会在初始挂载和后续更新时调用 render 之前调用它。它应该返回一个对象来更新 state,或者返回 null 就不更新任何内容。

比如我想做一个点击按钮就+1的,更新state就会触发组件更新,就会触发这个API
03-React事件处理 & 生命周期 & Diffing算法_第27张图片

<script type="text/babel">
	//创建组件
	class Count extends React.Component{
		//构造器
		constructor(props){
			console.log('Count---constructor');
			super(props)
			//初始化状态
			this.state = {count:0}
		}

		//加1按钮的回调
		add = ()=>{
			//获取原状态
			const {count} = this.state
			//更新状态
			this.setState({count:count+1})
		}
		
		//若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromProps
		static getDerivedStateFromProps(props,state){
			console.log('getDerivedStateFromProps',props,state);
			return null
		}

		render(){
			console.log('Count---render');
			const {count} = this.state
			return(
				<div>
					<h2>当前求和为:{count}</h2>
					<button onClick={this.add}>点我+1</button>
				</div>
			)
		}
	}
	
	//渲染组件
	ReactDOM.render(<Count count={199}/>,document.getElementById('test'))
</script>

  • 2.shouldComponentUpdate(nextProps, nextState)

和老版本的那个一样,当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。默认返回为true,返回false则阻止更新

控制组件自身或者子组件是否需要更新,尤其在子组件非常多的情况下
在之前的触发state更新的基础上加入API,查看更新时效果

shouldComponentUpdate(props, state) {
  console.log("shouldComponentUpdate 执行", props, state);
  // return false阻止更新
  return false;
}

03-React事件处理 & 生命周期 & Diffing算法_第28张图片

如果改为return true,那么就会没有问题,继续让state更新

shouldComponentUpdate(props, state) {
  console.log("shouldComponentUpdate 执行", props, state);
  // return true继续更新
  return true;
}

03-React事件处理 & 生命周期 & Diffing算法_第29张图片


  • 3.render()

这个没啥好说的, 前面的"阀门API"如果调用了,并且都return true了 render就会重新执行,如果不调用那就无所谓了,不会影响render()。
如果反过来, 前面的"阀门API"如果调用了,并且return false了,render后续就无法执行。


  • 4.getSnapshotBeforeUpdate()

在最后一次渲染(提交到dom节点)之前调用,getSnapshotBeforeUpdate(prevProps,prevState,),这两个参数就是DOM更新前的参数。
在更新之前获取快照,返回值传递给componentDidUpdate(prevProps,prevState,?snapshotValue)的snapshotValue上面。这个"快照"指的是在组件更新之前捕获的某个状态state或数据props的瞬时影像,可以取这个快照里对象的某一个属性,也可以return一个任意的数值。

如果单用这个getSnapshotBeforeUpdate(),是不行的,要搭配componentDidUpdate()使用,要接收参数的

如果单用getSnapshotBeforeUpdate()的话,控制台就会报警
在这里插入图片描述
两个搭配在一起使用

//在更新之前,render之后获取快照
getSnapshotBeforeUpdate(prevProps,prevState){
	console.log('getSnapshotBeforeUpdate');
	return 'atguigu'
}

//组件挂载完毕的钩子
componentDidUpdate(prevProps,precState,snapshot){
	console.log('componentDidUpdate 执行!',"getSnapshotBeforeUpdate传入的参数",snapshot);
}

在这里插入图片描述


  • 5.componentDidUpdate()

组件更新后触发的函数,和旧版本一样,这里先讨论单独使用componentDidUpdate()的场景
触发一下组件更新操作,触发API
在这里插入图片描述

如果是和getSnapshotBeforeUpdate()配合使用的话,我们将获取到其返回值

 // // 在更新之前,render之后获取快照
 getSnapshotBeforeUpdate(prevProps, prevState) {
   console.log("getSnapshotBeforeUpdate");
   return "atguigu";
 }

 // //组件挂载完毕的钩子
 componentDidUpdate(prevProps, precState, snapshot) {
   console.log("componentDidUpdate 执行 组件更新完毕", snapshot);
 }

点击更新操作
03-React事件处理 & 生命周期 & Diffing算法_第30张图片


最后验证一下新版本生命周期钩子的执行顺序
03-React事件处理 & 生命周期 & Diffing算法_第31张图片

组件卸载(由ReactDOM.unmountComponentAtNode()触发)
  • componentWillUnmount()

在组件卸载之前触发

组件卸载方法:ReactDOM.unmountComponentAtNode(),但是已经在18版本被取代
03-React事件处理 & 生命周期 & Diffing算法_第32张图片
例子:

<script type="text/babel">
  class Count extends React.Component {
    componentWillUnmount() {
      console.log("componentWillUnmount 执行,组件即将卸载");
    }

    unMount=()=>{
      ReactDOM.unmountComponentAtNode(document.getElementById("test"))
    }

    render() {
      return <div><button onClick={this.unMount}>卸载组件</button></div>;
    }
  }

  //渲染组件
  ReactDOM.render(<Count />, document.getElementById("test"));
</script>

03-React事件处理 & 生命周期 & Diffing算法_第33张图片

单击button,组件就会卸载,在真正卸载之前就会触发componentWillUnmount()执行
03-React事件处理 & 生命周期 & Diffing算法_第34张图片

虚拟DOM与DOM Diffing算法

颗粒度:DOM Diffing算法对比的最小粒度是标签,且逐层对比
03-React事件处理 & 生命周期 & Diffing算法_第35张图片

  • diffing算法应用在 react / vue 中,用于比较虚拟DOM和真实DOM。
  • 虚拟DOM中采用的算法,把树形结构按照层级分解,只比较同级元素,不同层级的节点只有创建和删除操作。
  • diffing算法会从根节点开始,一层层的向下比较,如果在某一层的某个节点发现不同了,他就会直接替换这个节点下面的所有子树。
  • 渲染真实DOM所消耗的性能是很大的,很多操作都会导致页面重新渲染。 通过diff算法对比新旧vdom之间的差异,可以最小化的执行dom操作,从而提高代码性能。

Diffing算法简单解析

你可能感兴趣的:(react.js,算法,javascript)