总结的内容:
- 对组件化的理解
- JSX的本质
- JSX和vdom的关系
- react中何时patch?
- 自定义组件的解析
- setState的过程
用react实现todolist demo,用demo来说明以上问题。
★对组件化的理解
- 组件的封装
- 组件的复用
组件的封装:
组件的封装包括视图封装、数据封装、变化逻辑封装(数据驱动视图),组件里的视图、数据和变化逻辑外界都不需要知道,只需要导入对应的组件就好了。
组件的复用,通过props传值体现:
★JSX的本质
JSX不是模板引擎,而是语法糖。JSX语法根本无法被浏览器解析,开发环境会将JSX编译成JS代码来运行(React.createElement())。(React.createElement()格式与vdom中的h函数、vue中的vm._c函数是一样的)
JSX语法:
JSX语法解析结果:
todolist demo中的JSX语法及解析结果:
React.createElement参数说明:
JSX语法大大降低了学习成本和编码工作量,同时JSX语法也增加了debug成本。JSX语法是react引入的,并不是react独有的,react已经将它作为一个独立标准开放,其他项目也可以使用。
★JSX和vdom的关系
- vdom和JSX是React初次推广开来的.
- JSX最终要渲染成html,要通过h函数来实现。
- 初次渲染+修改state后的re-render,要通过patch函数来实现
- 正好符合vdom的应用场景(数据驱动视图)
必须使用vdom的原因:JSX需要渲染成html,因为JSX需要转换成JS代码,JS代码在数据驱动视图下,不能亲自操作dom,它需要一个中间层vdom来操作渲染dom.
★React中何时patch?
- 初次渲染:ReactDOM.render(,container),会触发patch(container,vnode)
- setState:re-render会触发patch(vnode,newVnode)
★自定义组件的解析
- ‘div’-直接渲染
即可,vdom可以做到
- Input和List是自定义组件(class),vdom默认不认识
因此,Input和List定义的时候必须声明render函数,自定义组件根据props初始化实例,然后执行实例的render函数来实现对自定义组件的解析。
return (
<div>
<Todo/>
</div>
);
自定义组件的解析相当于
var todo = new Todo()
return todo.render()
若 带数据,要在实例化的时候把数据传进去。
React.createElement(
"div",
null,
React.createElement(Todo, null)
);
var todo = new Todo()
return todo.render()
自定义组件与html自带的标签进行对比,生成的JS代码中不同的是:
自定义组件:React.createElement()的第一个参数是构造函数;
html自带标签:React.createElement()的第一个参数是字符串;
遇到自定义组件解析时:初始化实例,然后执行render。从最高级、最抽象的组件一步步通过render函数找到最底层的html默认元素的组件
★setState的过程
首先需要说明setState的过程是异步的,vue修改data属性(set中执行updateComponent)也是异步的。
从上图代码中的两次console.log(this.state.list)的结果可以看出react修改state的过程是异步的。
setState为什么是异步的呢?
先看下面代码:
你无法规定用户如何使用setState,可能会一次执行多次setState,但是没必要每次setState都重新渲染,考虑性能,即使是每次重新渲染用户也看不到中间的效果,只看到最后的结果即可。
setState的过程:
- 每个组件实例都有renderComponent方法(在Component里写着)
- setState时会执行renderComponent方法,会重新执行实例的render
- render函数返回newVnode,然后拿到preVnode
- 执行patch(preVnode,newVnode)