最近一直写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对象上的一些属性和方法。
当调用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
与更新相关的属性和方法如下:
在调用this.setState()
以后,也是调用了一个map方法,根据传入参数不同,依然把要更新的标签分为文本、原生标签、自定义标签三类。具体处理过程如下。
文本
文本节点处理很简单,判断要更新后的文本与当前文本是否===
,不是全等就删除原来文本,插入新文本。
自定义标签
对于自定义标签,首先根据对象的引用、key是否相同,判断是否需要更新。如果需要更新,就继续调用上述map方法进行子组件的更新。又是一个递归。但是注意,这里的map方法和渲染部分的map方法不是一个方法哟。
原生标签
对于原生标签,首先更新组件的属性,然后update子树,用diff算法来比较新的子树与目前标签的子树的不同,形成一个差异树,然后用patch方法,把这个差异树更新到真正的DOM树上。
总结
很复杂的过程,让我用流水账写了一遍。没能道出其中精华。以后继续探索,写的详细一些。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 中国武警男声合唱团《辉煌之声1天路》[DTS-WAV分轨]
- 紫薇《旧曲新韵》[320K/MP3][175.29MB]
- 紫薇《旧曲新韵》[FLAC/分轨][550.18MB]
- 周深《反深代词》[先听版][320K/MP3][72.71MB]
- 李佳薇.2024-会发光的【黑籁音乐】【FLAC分轨】
- 后弦.2012-很有爱【天浩盛世】【WAV+CUE】
- 林俊吉.2012-将你惜命命【美华】【WAV+CUE】
- 晓雅《分享》DTS-WAV
- 黑鸭子2008-飞歌[首版][WAV+CUE]
- 黄乙玲1989-水泼落地难收回[日本天龙版][WAV+CUE]
- 周深《反深代词》[先听版][FLAC/分轨][310.97MB]
- 姜育恒1984《什么时候·串起又散落》台湾复刻版[WAV+CUE][1G]
- 那英《如今》引进版[WAV+CUE][1G]
- 蔡幸娟.1991-真的让我爱你吗【飞碟】【WAV+CUE】
- 群星.2024-好团圆电视剧原声带【TME】【FLAC分轨】