web前端

拜读Preact源码有感

2019-01-28  本文已影响26人  侬姝沁儿

jsx本质

JSX是一种嵌入式的类似XML的语法,它可以被转换成合法的JavaScript,转换的语义是依据不同的实现而定的。例如react有react的jsx语法和转换器babel-plugin-transform-react-jsx ,vue有vue的jsx语法和转换器babel-plugin-transform-vue-jsx,当然,这也意味你可以开发自己的jsx语法和转换器jsx

react本质

babel-plugin-transform-react-jsx

react通过babel-plugin-transform-react-jsx将jsx语法转换为可以被React.createElement识别的形式,即:

<div id="foo" name="bar">Hello!</div>

// 转换为

React.createElement('div', { id: 'foo', name : 'bar' }, 'Hello!');

也就是说,react的jsx只是React.createElement的语法糖而已,我们看起来在写jsx,实际上babel-plugin-transform-react-jsx已经将我们写的jsx语法转换了。

React.createElement

jsx语法被转换器转换后,变成可以被React.createElement所识别的内容。React.createElement(component, props, ...children) 则将能识别的相应内容解析为虚拟DOM。

React.createElement('div', { id: 'foo', name : 'bar' }, 'Hello!');

// 转换为

{
  $$typeof: Symbol(react.element),
  key: null,
  props: {id: "foo", name: "bar", children: "Hello!"},
  ref: null,
  type: "div",
  _owner: {},
  _store: {}
}

虚拟DOM的本质:(virtual-dom)

虚拟DOM从本质上将就是将复杂的DOM转化成轻量级的JavaScript对象,不同的渲染中却会生成同样的虚拟DOM对象,然后通过高效优化过的Diff算法,比较前后的虚拟DOM对象,以最小的变化去更新真实DOM。

{
  $$typeof: Symbol(react.element),
  key: null,
  props: {id: "foo", name: "bar", children: "Hello!"},
  ref: null,
  type: "div",
  _owner: {},
  _store: {}
}

// Hello 变为 Hello react

{
  $$typeof: Symbol(react.element),
  key: null,
  props: {id: "foo", name: "bar", children: "Hello react!"},
  ref: null,
  type: "div",
  _owner: {},
  _store: {}
}

对比对象我们可以看到,只有 props.children 发生了变化,利用高效的对比diff方法找到不同,并把不同的内容修改,进行一个真实dom上的映射改变。即:

<div id="foo" name="bar">Hello!</div>

// dom映射后

<div id="foo" name="bar">Hello react!</div>

结语

即react的核心思想就是利用jsx转换器,将jsx转换为React.createElement能理解的形式,然后React.createElement又将相应内容解析为虚拟DOM。不同的渲染中却会生成同样的虚拟DOM对象,然后通过高效优化过的Diff算法,比较前后的虚拟DOM对象,最后通过dom的相应方法以最小的变化去更新真实DOM。无外乎是:jsx组件到虚拟DOM的转化、以及虚拟DOM到真实DOM的映射。

上一篇 下一篇

猜你喜欢

热点阅读