为什么要实现一个React?如果你进来看了这篇文章,相信你我的想法是一致的,为了更好的理解和使用React。这一篇是这个文章系列的第一篇,主要说下实现React之前需要掌握和明白的地方,不单单是介绍,请耐心看完。这个系列需要足够的耐心去看,静下心来才能有更大的收获。本系列文章参考dialact系列文章,你可以直接去看dialact,它也足够精简。这个系列中我会调整部分结构来帮助理解。
预备知识
在React的实现中,有几种写法需要了解。
为dom元素添加Attribute
var dom = document.getElmentById('root');
dom['className'] = 'container'
dom['style'] = 'background-color: red';
复制代码
我们这里使用直接赋值的方法,而不是使用setAttribute
来给dom添加Attribute,是为了保证只有有效的Attribute
才能被赋值。这里涉及到attribute
和property
的区别。
attribute和property的区别
attribute
描述xml中的附加值如
<apple name='apple'></apple>
复制代码
这里的name
就是attribute
,property
在js中描述的是对象的属性如
var person = { name: 'chris' }
复制代码
这里的name
是property
。
对于dom元素来说,它是一个HTMLElement
类型的对象,它有很多property
,在其property
中有一个attributes
属性,该属性是NameNodeMap
类型,用来存储html展示的attributes
。
当我们使用setAttribute
函数时,会直接为attributes
赋值,不论其名称如何。而如果我们使用dom['property'] = value
的形式的时候,它会根据名称寻找和attributes
之间的对应关系,如果有对应则在赋值的同时为dom
添加attribute
,如果没有则只添加property
而不会添加attribute
。
property
和attribute
之间的对象关系根据不同的元素类型来确定,同时对应名称也不是一定相同,如
// property => attribute
style => style
className => class
htmlFor => html
复制代码
其他要用到的方法
// 为元素绑定事件
dom.addEventListener('click', function() {});
// 为文本节点赋值
dom['nodeValue'] = value;
// 寻找节点
var dom = document.getElementById('root');
// 创建节点
var dom = document.createElement('div');
// 创建文本节点
var dom = document.createTextNode('');
复制代码
jsx
jsx的本质是一个语法糖,例如有如下jsx语法
<div className="container">
<h1>hello world</h1>
</div>
复制代码
在React中会被解析成如下形式:
React.createElement({
type: 'div',
props: {
className: 'container',
children: [
React.createElement({
type: 'h1',
children: ['hello world']
})
]
}
})
复制代码
这个转换我们可以借助babel-plugin-transform-react-jsx来帮助我们实现,我们所需要做的就是实现React.createElement
。
diff
由于操作dom要付出的代价很大,React最大限度的来利用已经生成的dom,避免重复渲染。React中用到了虚拟dom的概念,它其实就是一个对象,类似于我们上面jsx中写到的
{
type: 'h1'
children: ['hello world']
}
复制代码
实际的React中更加复杂,配合diff算法可以减少dom操作。传统比较两棵树的算法是O(n^3)
,React有两个假设:
- 不同类型的节点会产生不同的树
- 开发者能够通过赋值
key
属性来区分列表中不同的节点
在这两个假设的基础上,React只需要比较两棵dom树中同一层对应的节点就可以,将算法复杂度降低到O(n)
,同时能覆盖到绝大部分的情况,这种diff算法在React中被称作Reconciliation
下一篇,我们开始实现我们自己的React。接下来我会持续更新,这是github原文地址,欢迎star,欢迎watch。