Use JSX without React 1: Virtual DOM

目錄

  • 1 前言
  • 2 實現(xiàn)Virtual DOM的2種形態(tài)
    • 1 純JSON格式
    • 2 非JSON格式
  • 3 下一篇
  • 4 參考

前言

回顧React創(chuàng)建組件的三種方式:(其中React.createClass 16版本后已廢棄)

react三種component.png

無論是純函數(shù)還是組件,都返回一個(<div>...</div>)HTML格式的內(nèi)容,這段代碼并不是合法的js代碼,它是一種被稱為jsx的語法擴展,通過它我們就可以很方便的在js代碼中書寫html片段。[1]

本質(zhì)上,JSX是語法糖,上面這段代碼會被babel轉(zhuǎn)換成如下代碼

const title = React.createElement(
    'h1',
    { className: 'title' },
    'Hello, world!'
);

你可以在babel官網(wǎng)提供的在線轉(zhuǎn)譯測試jsx轉(zhuǎn)換后的代碼,這里有一個稍微復雜一點的例子
如何將轉(zhuǎn)義后的數(shù)據(jù)渲染到瀏覽器中,本篇文章將介紹2種方式,這里為了更好理解,完整例子都模仿React寫法實現(xiàn)。

實現(xiàn)Virtual DOM的2種形態(tài)

不依賴第三方庫
用js對象模擬DOM樹可以有2種形態(tài):純JSON格式和非JSON格式

1.純JSON數(shù)據(jù)

{type:"...", props: {...}, children: [...]}

{
type:'ul', 
props:{}, 
children:[
    {
      type:'li',
      props:{class:'list'},
      children:[
          {
            type:'input', 
            props:{value:'Niko',class:'list',keyup:this.change},
            children:[]},
      ]
    },
    {
      type:'li', 
      props:{},
      children:['Bellic']}
  ]
}
屬性 類型 描述
type string DOM 節(jié)點名稱
props object DOM屬性attrs或events函數(shù)
children array[str/obj] 數(shù)組內(nèi)為對象時表示子節(jié)點,循環(huán)上述;字符串時為標簽內(nèi)容

設(shè)置type

let $el = document.createElement(type)

設(shè)置props

從上述表中可以看出,不僅可以添加class等attrs屬性,

$el.setAttribute(propName, propValue)

有些元素還有添加事件的需求。
但是JSON格式最終只能存儲字符串,不能存儲一個可執(zhí)行的函數(shù)更不用說this的作用域,所以處理事件可以使用addEventListener(…)注冊事件,值得注意的是這里的事件類型就不能添加on-*前綴了。

if(typeof propValue === 'function'){
  //props events
  $el.addEventListener(
    propName,
    propValue
  );
}else {
  //props attrs
  $el.setAttribute(propName, propValue)
}

設(shè)置children

當標簽內(nèi)不再添加標簽,children需要設(shè)置為[string]表示標簽的內(nèi)容。當標簽內(nèi)為一系列子標簽時,格式將和上一次一樣循環(huán)。在實現(xiàn)渲染時很容易想到利用遞歸進行插值

function createElement(node){
  node.children.map(child=>{
    $el.appendChild(createElement(child))
  });

  //最終目的是要返回$el
  return $el
}

完整代碼戳這里??
https://gist.github.com/1uokun/bcfaec28d8c5051be343ca390bb3001e

拓展

Virtual DOM差異化對比[2]
setState和props傳遞實現(xiàn)[4]

2.非JSON格式

JSX轉(zhuǎn)義格式,和1區(qū)別在于DOM樹每一層都有一個執(zhí)行函數(shù),

 var el = React.createElement;
 var ul = el('ul', {id: 'list'}, [
  el('li', {class: 'item'}, ['Item 1']),
  el('li', {class: 'item'}, ['Item 2']),
  el('li', {class: 'item'}, ['Item 3'])
])

這種格式實現(xiàn)就比較容易理解,針對每一層Virtual DOM進行解析

function createElement(tag, attrs, children) {...}

完整代碼戳這里??
https://gist.github.com/1uokun/e4ed774cb523bbc5425266119de520e5

下一篇

前面大致了解了JSX工作原理,不過都是用靜態(tài)HTML實現(xiàn),并且數(shù)據(jù)格式較繁瑣,如何舒舒服服寫JSX格式的代碼,又能自動轉(zhuǎn)換成合法的JavaScript?自然會想到前端工程化和webpack工具
下一節(jié)將介紹不依賴React如何使用webpack配置并打包JSX:Use JSX without React 2:編譯JSX和Component實現(xiàn)

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容