React 组件渲染和更新的实现代码示例


Posted in Javascript onFebruary 21, 2019

最近一直写React,慢慢就对里面的一些实现很好奇。最好奇的就是自定义标签的实现和this.setState的实现。这里不分析JSX是如何解析的,所有组件都用ES5方式编写。

组件渲染

渲染时候,我们会调用render方法。类似下面这样:

var SayHi = React.createClass({
 getInitialState: function() {
  return {verb: 'say:'};
 },
 componentWillMount: function() {
  console.log('I will mount');
 },
 componentDidMount: function() {
  console.log('I have mounted');
 },
 render: function() {
  return React.createElement("div", null,this.state.verb, "Hello ", this.props.name);
 }
});

React.render(React.createElement(SayHi, {name: "Cynthia"}), document.getElementById("container"));

结果:

页面打印:
say: Hello Cynthia
控制台打印:
I will mount
I have mounted

React 组件渲染和更新的实现代码示例

这是我画的React对象上的一些属性和方法。

当调用render方法时,render会去调用一个map方法,根据传入参数的不同,把被render的对象分为以下三类:
* 文本
* 原生
* 自定义标签

文本

对于文本,React会实例化一个文本节点的对象,并且调用该对象的mount方法。在这个mount方法中,把文本放到一个span中,调用容器组件的innerHTML,进行渲染。

原生标签

对于原生标签,React会实例化一个处理原生标签的对象,并且调用该对象的mount方法。在这个mount方法中,拼接一个字符串,并且不断递归上面的map方法,最后把拼接好的字符串放到容器组件的innerHTML中,进行渲染。

自定义标签

这个应该是大家最好奇的。自定义标签虽然叫标签,其实就是一个类。实例化一个处理自定义标签的对象后,首先React会处理自定义标签的生命周期方法,然后再次递归调用子组件的render方法进而调用map方法,直至把自定义标签分解为前两种标签。

更新

首先,我们统一一下认识。在React里调用this.setState()会使得组件更新,调用this.state = {}只会更改本组件的状态,但是不会使得组件更新。

如果我要更新一个组件,我会这样写。

var SayHi = React.createClass({
 getInitialState: function() {
  return {verb: 'say:'};
 },
 componentWillMount: function() {
  console.log('I will mount');
 },
 componentDidMount: function() {
  console.log('I have mounted');
 },
 changeVerb: function(){
  this.setState({verb: 'write:'});
 }
 render: function() {
  return React.createElement("div", this.changeVerb.bind(this),this.state.verb, "Hello ", this.props.name);
 }
});

React.render(React.createElement(SayHi, {name: "Cynthia"}), document.getElementById("container"));

执行结果:

页面打印:
say: Hello Cynthia
点击文本,页面内容更新成:
write: Hello Cynthia

与更新相关的属性和方法如下:

React 组件渲染和更新的实现代码示例

在调用this.setState()以后,也是调用了一个map方法,根据传入参数不同,依然把要更新的标签分为文本、原生标签、自定义标签三类。具体处理过程如下。

文本

文本节点处理很简单,判断要更新后的文本与当前文本是否===,不是全等就删除原来文本,插入新文本。

自定义标签

对于自定义标签,首先根据对象的引用、key是否相同,判断是否需要更新。如果需要更新,就继续调用上述map方法进行子组件的更新。又是一个递归。但是注意,这里的map方法和渲染部分的map方法不是一个方法哟。

原生标签

对于原生标签,首先更新组件的属性,然后update子树,用diff算法来比较新的子树与目前标签的子树的不同,形成一个差异树,然后用patch方法,把这个差异树更新到真正的DOM树上。

总结

很复杂的过程,让我用流水账写了一遍。没能道出其中精华。以后继续探索,写的详细一些。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
经验几则 推荐
Sep 05 Javascript
为javascript添加String.Format方法
Aug 11 Javascript
JS构建页面的DOM节点结构的实现代码
Dec 09 Javascript
对比分析json及XML
Nov 28 Javascript
使用JS画图之点、线、面
Jan 12 Javascript
JavaScript 中有关数组对象的方法(详解)
Aug 15 Javascript
Vue 2.0中生命周期与钩子函数的一些理解
May 09 Javascript
详解vue slot插槽的使用方法
Jun 13 Javascript
swiper 解决动态加载数据滑动失效的问题
Feb 26 Javascript
详解vue-cli下ESlint 配置说明
Sep 03 Javascript
django中使用vue.js的要点总结
Jul 07 Javascript
vue服务端渲染操作简单入门实例分析
Aug 28 Javascript
vue图片上传本地预览组件使用详解
Feb 20 #Javascript
Vue 后台管理类项目兼容IE9+的方法示例
Feb 20 #Javascript
浅谈小程序 setData学问多
Feb 20 #Javascript
9102年webpack4搭建vue项目的方法步骤
Feb 20 #Javascript
微信小程序五子棋游戏AI实现方法【附demo源码下载】
Feb 20 #Javascript
解决element ui select下拉框不回显数据问题的解决
Feb 20 #Javascript
微信小程序五子棋游戏的悔棋实现方法【附demo源码下载】
Feb 20 #Javascript
You might like
phpMyAdmin下载、安装和使用入门教程
2007/05/31 PHP
LotusPhp笔记之:Logger组件的使用方法
2013/05/06 PHP
Android AsyncTack 异步任务实例详解
2016/11/02 PHP
PHP环形链表实现方法示例
2017/09/15 PHP
Javascript常考语句107条收集
2010/03/09 Javascript
鼠标滑在标题上显示图片的JS代码
2013/11/19 Javascript
Javascript检查图片大小不要让大图片撑破页面
2014/11/04 Javascript
一张Web前端的思维导图分享
2015/07/03 Javascript
bootstrap网页框架的使用方法
2016/05/10 Javascript
JavaScript判断微信浏览器实例代码
2016/06/13 Javascript
JavaScript 函数节流详解及方法总结
2017/02/09 Javascript
jQuery实现一个简单的轮播图
2017/02/19 Javascript
es7学习教程之fetch解决异步嵌套问题的方法示例
2017/07/21 Javascript
微信小程序实现签到功能
2018/10/31 Javascript
详解vue父子组件关于模态框状态的绑定方案
2019/06/05 Javascript
uniapp 仿微信的右边下拉选择弹出框的实现代码
2020/07/12 Javascript
微信小程序实现时间戳格式转换
2020/07/20 Javascript
Python生成随机数的方法
2014/01/14 Python
Python实现带百分比的进度条
2016/06/28 Python
python logging日志模块以及多进程日志详解
2018/04/18 Python
Python 单元测试(unittest)的使用小结
2018/11/14 Python
python多进程重复加载的解决方式
2019/12/13 Python
python读取与处理netcdf数据方式
2020/02/14 Python
Django media static外部访问Django中的图片设置教程
2020/04/07 Python
jupyternotebook 撤销删除的操作方式
2020/04/17 Python
Python matplotlib绘制图形实例(包括点,曲线,注释和箭头)
2020/04/17 Python
python matplotlib实现将图例放在图外
2020/04/17 Python
全球知名鞋履品牌授权零售商:Journeys
2016/09/17 全球购物
丝芙兰香港官网:Sephora香港
2018/03/13 全球购物
拉飞逸官网:Lafayette 148 New York
2020/07/15 全球购物
介绍一下Java中的static关键字
2012/05/12 面试题
班级德育工作实施方案
2014/02/21 职场文书
论群众路线学习心得体会
2014/10/31 职场文书
世界水日宣传活动总结
2015/02/09 职场文书
nginx反向代理时如何保持长连接
2021/03/31 Servers
纯 CSS 自定义多行省略的问题(从原理到实现)
2021/11/11 HTML / CSS