Render函數詳解


 

一.虛擬dom

  DOM是文檔對象模型(Document Object Model)的簡寫,在瀏覽器中通過js來操作DOM的操作性能很差,於是虛擬Dom應運而生。虛擬Dom就是在js中模擬DOM對象樹來優化DOM操作的一種技術或思路。React和Vue2都使用了虛擬DOM技術,虛擬DOM並不是真正意義上的DOM,它作為一個輕量級的JavaScript對象,在狀態發生變化時,會進行Diff運算,來更新發生變化的DOM,對於未發生變化的DOM節點,不予操作,由於不是全部重繪,大大提高更新渲染性能。當使用render函數描述虛擬DOM時,vue提供一個函數,這個函數是就構建虛擬DOM所需要的工具。官網上給他起了個名字叫 createElement。還有約定的簡寫叫 h, vm中有一個方法 _c, 也是這個函數的別名。

 

  在Vue2中,虛擬DOM就是通過一種VNode類表達,每個DOM元素或組件都對應一個VNode對象。

VNode節點解析:

  • children 子節點,數組,也是VNode類型。
  • text 當前節點的文本,一般文本節點或注釋節點會有該屬性。
  • elm 當前虛擬節點對應的真實的DOM節點。
  • ns 節點的namespace
  • content 編譯作用域
  • functionalContext 函數化組件的作用域
  • key 節點的key屬性,用於作為節點的標識,有利於patch的優化
  • componentOptions 創建組件實例時會用到的選項信息。
  • child 當前節點對應的組件實例。
  • parent 組件的占位節點。
  • raw 原始html
  • isStatic 靜態節點的標識
  • isRootInset 是否作為根節點插入,被<transition>包裹的節點,該屬性的值為false。
  • isConment 當前節點是否是注釋節點。
  • isCloned 當前節點是否為克隆節點。
  • isOnce 當前節點是否有v-once指令。

 

VNode主要可以分為以下幾類:

 

 

  • TextVNode 文本節點。
  • ElementVNode 普通元素節點。
  • ComponentVNode 組件節點。
  • EmptyVNode 沒有內容的注釋節點。
  • CloneVNode 克隆節點,可以是以上任意類型的節點,唯一的區別在於isCloned屬性為true。

 

二.CreateElement基本用法

1.基本參數

createElement構成了Vue虛擬DOM的模板,它有3個參數:

// @returns {VNode}
createElement(
  // {String | Object | Function}
  // 一個 HTML 標簽字符串,組件選項對象,或者
  // 解析上述任何一種的一個 async 異步函數。必需參數。
  'div',

  // {Object}
  // 一個包含模板相關屬性的數據對象
  // 你可以在 template 中使用這些特性。可選參數。
  {
    // (詳情見下一節)
  },

  // {String | Array}
  // 子虛擬節點 (VNodes),由 `createElement()` 構建而成,
  // 也可以使用字符串來生成“文本虛擬節點”。可選參數。
  [
    '創建h1標簽',
    createElement('h1', 'Render函數'),
    createElement(MyComponent, {
      props: {
        someProp: 'foobar'
      }
    })
  ]
)

 

2.函數模板各部分含義

a.'div':html節點

{String | Object | Function}

一個 HTML 標簽字符串,組件選項對象,或者

解析上述任何一種的一個 async 異步函數,必要參數。


b.{}:節點的屬性

{Object}

 一個包含模板相關屬性的數據對象

 這樣,您可以在 template 中使用這些屬性。可選參數。

 詳細屬性:

{
  // 和`v-bind:class`一樣的 API
  // 接收一個字符串、對象或字符串和對象組成的數組
  'class': {
    foo: true,
    bar: false
  },
  // 和`v-bind:style`一樣的 API
  // 接收一個字符串、對象或對象組成的數組
  style: {
    color: 'red',
    fontSize: '14px'
  },
  // 正常的 HTML 特性
  attrs: {
    id: 'foo'
  },
  // 組件 props
  props: {
    myProp: 'bar'
  },
  // DOM 屬性
  domProps: {
    innerHTML: 'baz'
  },
  // 事件監聽器基於 `on`
  // 所以不再支持如 `v-on:keyup.enter` 修飾器
  // 需要手動匹配 keyCode。
  on: {
    click: this.clickHandler
  },
  // 僅對於組件,用於監聽原生事件,而不是組件內部使用
  // `vm.$emit` 觸發的事件。
  nativeOn: {
    click: this.nativeClickHandler
  },
  // 自定義指令。注意,你無法對 `binding` 中的 `oldValue`
  // 賦值,因為 Vue 已經自動為你進行了同步。
  directives: [
    {
      name: 'my-custom-directive',
      value: '2',
      expression: '1 + 1',
      arg: 'foo',
      modifiers: {
        bar: true
      }
    }
  ],
  // 作用域插槽格式
  // { name: props => VNode | Array<VNode> }
  scopedSlots: {
    default: props => createElement('span', props.text)
  },
  // 如果組件是其他組件的子組件,需為插槽指定名稱
  slot: 'name-of-slot',
  // 其他特殊頂層屬性
  key: 'myKey',
  ref: 'myRef'
}

 

c.[ ]:html節點的子節點

{String | Array}

子節點 (VNodes),由 `createElement()` 構建而成,

或使用字符串來生成“文本節點”。可選參數。

 

3.使用JavaScript代替模板功能

  在Render函數中,不再需要Vue內置的指令,比如v-ifv-for。無論要實現什么功能,都可以使用原生JavaScript。render函數里沒有與v-model對應的API,需要自己來實現邏輯。

  對於事件修飾符和按鍵修飾符,基本需要自己實現:

修飾符 對應的句柄
.stop event.stopPropagation()
.prevent event.preventDefault()
.self if(event.target!==event.currentTarget) return
.ente.13 if(event.keyCode!==13) return 替換13位需要的keyCode
.ctrl.alt.shift.meta if(!event.ctrlKey) return 根據需要替換ctrlKeyaltKeyshiftKeymetaKey

  對於事件修飾符.capture和.once,Vue提供了特殊的前綴,可以直接寫在on的配置里。

修飾符 前綴
.capture !
.once ~
.capture.once.once.capture ~!

寫法如下:

on: {
    '!click': this.doThisInCapturingMode,
        '~keyup': this.doThisOnce,
        '~!mouseover': this.doThisOnceInCapturingMode
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM