Skeanmy / Zero2One

学习笔记的仓库
0 stars 1 forks source link

【React】虚拟DOM #11

Open Skeanmy opened 4 years ago

Skeanmy commented 4 years ago

虚拟DOM

普通的数据变更带来的DOM更新过程:

  1. state数据
  2. JSX模板
  3. 数据 + 模板结合生成真实DOM,显示
  4. state改变
  5. 数据 + 模板结合生成真实DOM,并不直接替换原始的DOM
  6. 新DOM(DocumentFragment)和原始DOM做对比、找差异
  7. 找出input框发生变化
  8. 只用新DOM中input元素替换老DOM中的input元素

存在的问题:性能提升不明显

  1. state数据

  2. JSX模板

  3. 数据 + 模板结合生成真实DOM,显示

  4. 生成虚拟DOM,虚拟DOM是一个js对象,用于描述真实DOM,因此虚拟DOM的成本较低,可以适用于跨平台(提升性能的关键,js操作对象很容易,操作DOM就需要与浏览器底层api进行通信)

    <div id='abc'><span>hello world</span></div>
    const vdom = ['div', {id: 'abc'}, ['span', {}, 'hello world']]
  5. state发生变化

  6. 数据 + 模板生成新的虚拟DOM

    const vdom = ['div', {id: 'abc'}, ['span', {}, 'bye bye']]
  7. 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中内容的变化

  8. 直接操作DOM,改变span中的内容

React底层的实现是:先使用数据 + 模板生成虚拟DOM,再使用虚拟DOM结构生成真实DOM

JSX

React 并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式(vue采用了这种方式),而是通过将二者共同存放在称之为“组件”的松散耦合单元之中,来实现关注点分离

Babel 会把 JSX 转译成一个名为 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()

// 计时器
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);

优势

Diff算法

a 0 b 1 c 2
删除a后
b 0 c 1
匹配不上了
Skeanmy commented 3 years ago

yuque_diagram

Skeanmy commented 3 years ago

Jietu20210421-161915-HD

Skeanmy commented 3 years ago

图片 1

Skeanmy commented 3 years ago

图片 2

Skeanmy commented 3 years ago

图片 3

Skeanmy commented 3 years ago

图片 4

Skeanmy commented 3 years ago

图片 5

Skeanmy commented 3 years ago

图片 7