Open Skeanmy opened 4 years ago
普通的数据变更带来的DOM更新过程:
存在的问题:性能提升不明显
state数据
JSX模板
数据 + 模板结合生成真实DOM,显示
生成虚拟DOM,虚拟DOM是一个js对象,用于描述真实DOM,因此虚拟DOM的成本较低,可以适用于跨平台(提升性能的关键,js操作对象很容易,操作DOM就需要与浏览器底层api进行通信)
<div id='abc'><span>hello world</span></div> const vdom = ['div', {id: 'abc'}, ['span', {}, 'hello world']]
state发生变化
数据 + 模板生成新的虚拟DOM
const vdom = ['div', {id: 'abc'}, ['span', {}, 'bye bye']]
比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中内容的变化
直接操作DOM,改变span中的内容
React底层的实现是:先使用数据 + 模板生成虚拟DOM,再使用虚拟DOM结构生成真实DOM
React 并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式(vue采用了这种方式),而是通过将二者共同存放在称之为“组件”的松散耦合单元之中,来实现关注点分离。
Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用。
React.createElement()
// jsx语法 const element = ( <h1 className="greeting"> Hello, world! </h1> ); // babel转义过 const element = React.createElement( 'h1', {className: 'greeting'}, 'Hello, world!' ); // 实际上创建的对象 const element = { type: 'h1', props: { className: 'greeting', children: 'Hello, world!' } }; // 后续去渲染真实DOM
React 元素是不可变对象(Immutable Object)。一旦被创建,你就无法更改它的子元素或者属性。更新 UI 唯一的方式是创建一个全新的元素,并将其传入ReactDOM.render()。
ReactDOM.render()
// 计时器 function tick() { const element = ( <div> <h1>Hello, world!</h1> <h2>It is {new Date().toLocaleTimeString()}.</h2> </div> ); ReactDOM.render(element, document.getElementById('root')); } setInterval(tick, 1000);
同级比较,带来了算法时间复杂度的提升,牺牲了子DOM的浪费
没有key值的话需要两层循环判断新旧的对应关系,提高了复用性
a 0 b 1 c 2 删除a后 b 0 c 1 匹配不上了
虚拟DOM
普通的数据变更带来的DOM更新过程:
存在的问题:性能提升不明显
state数据
JSX模板
数据 + 模板结合生成真实DOM,显示
生成虚拟DOM,虚拟DOM是一个js对象,用于描述真实DOM,因此虚拟DOM的成本较低,可以适用于跨平台(提升性能的关键,js操作对象很容易,操作DOM就需要与浏览器底层api进行通信)
state发生变化
数据 + 模板生成新的虚拟DOM
比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中内容的变化
直接操作DOM,改变span中的内容
JSX
React 并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式(vue采用了这种方式),而是通过将二者共同存放在称之为“组件”的松散耦合单元之中,来实现关注点分离。
Babel 会把 JSX 转译成一个名为
React.createElement()
函数调用。React 元素是不可变对象(Immutable Object)。一旦被创建,你就无法更改它的子元素或者属性。更新 UI 唯一的方式是创建一个全新的元素,并将其传入
ReactDOM.render()
。优势
Diff算法
同级比较,带来了算法时间复杂度的提升,牺牲了子DOM的浪费
没有key值的话需要两层循环判断新旧的对应关系,提高了复用性