1. 对组件化的理解
首先谈,组件封装:封装数据、视图、变化逻辑;
其次说,组件复用:通过props传值
2. JSX的本质
第一,JSX的语法。它以html标签的形式存在,引入js变量和表达式,if语法,for循环,style样式和className,并且支持事件
第二,JSX语法根本无法被浏览器解析,开发环境会把JSX语法解析成js对象
第三,通过React.createElement方法把JSX语法解析成JS代码。方法参数接收(标签名,属性,子元素)。如何解析的?
解析前:
// render函数
render() {
const list = this.props.list
return (
<ul>
{list.map((item, index) => {
return <li key="index">{item}</li>
})}
</ul>
)
}
解析后:
// 解析后
function render() {
const list = this.props.list
React.createElement('ul',
null,
list.map((item, index) => {
return React.createElement('li', { key: index }, item)
}))
}
3. JSX和vdom的关系
- 关于为什么要用vdom?JSX模板需要解析成html,数据驱动视图
- 其中React.createElement()和h()函数都生成vnode【见上个问题】 第一次渲染是在ReactDOM.render(,document.getElementById(‘root’))的时候,通过dispatch(container,vnode)把vnode渲染在容器上。
// 第一次 dispatch(container,vnode)
ReactDOM.render(<App />, document.getElementById('root'))
重新渲染是在使用setState()修改data的时候触发re-render生成新的newVnode,然后通过dispatch(vnode,newVnode)用新生成的替代旧的。
addTodo(title) {
const currentList = this.state.list
// 重新 dispatch(vnode,newVnode)
this.setState({
list: currentList.concat(title)
})
}
- 关于生成的vnode的本质就是js对象,对于我们平常使用的标签(如div,p等),React.createElement()的时候生成对应的标签。
对于自定义的组件,则生成自定义组件的实例,通过实例的render函数再次生成新的vnode,依次的循环迭代下去,直到变成最底层我们平常使用的标签。
带自定义组件的render:
// render函数
render() {
const list = this.props.list
return (
<div>
<p>普通标签</p>
<List data={this.state.list} />
</div>
)}
自定义组件解析后:
// 解析后
function render() {
const list = this.props.list
React.createElement('div',
null,
React.createElement('p', null, '普通标签'),
React.createElement(List, { data: this.state.list })
// List是自定义组件,一般是先初始化List组件的实例,然后调用实例的render函数生成vnode,依次循环,知道没有自定义组件
// var list = new List({data:this.state.list})
// var vnode = list.render()
)}
4.setState的过程
首先,setState是异步的,为了避免多次修改引发dom的re-render。
其次,每个组件都继承了顶层React.Component组件中的renderComponent方法,重新执行实例的render
最后,根据render返回的newVnode和preVnode进行对比,通过dispatch函数新的节点替代旧的节点