Vue 中 render 函數有點意思

做者:Joshua Bemenderfer
譯者:前端小智
來源:vuejsbook.com
點贊再看,養成習慣

本文 GitHub https://github.com/qq44924588... 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。前端

咱們知道 Vue 模板是很是強大的,基本能夠完成咱們平常開發的全部任務。可是,有一些用例,如基於輸入或插槽值建立動態組件方式,render 函數會比模板完成的更好也更出色。vue

用過 React 開發的人對 render 函數應該很是熟悉,由於React組件經過 JSX和 render 函數來構建的。 儘管Vue render 函數也能夠用JSX編寫,但在這裏咱們使用原生 JS方式,由於這樣,咱們能夠更輕鬆地瞭解Vue組件系統的一些基礎。git

值得注意的是,Vue 的模板實際上在編譯時也是會先解析成 render 函數表示方式。 模板只是在render 函數之上提供了一個方便且熟悉的語法糖。 儘管 render 函數更強大,但render函數可讀性不好,相對用的也比較少了。github

建立組件

帶有 render 函數的組件沒有template標記或屬性。 相反,該組件定義了一個了名爲render的函數,該函數接收一個reateElement(renderElement: String | Component, definition: Object, children: String | Array)參數(因爲某種緣由,一般別名爲h,歸咎於JSX)並返回使用該函數建立的元素,其餘一切保持不變,來看看事例:面試

export default {
  data() {
    return {
      isRed: true
    }
  },

  /*
   * <template>
   *   <div :class="{'is-red': isRed}">
   *     <p>這是一個 render 事例</p>
   *   </div>
   * </template>
   */
  // render 中的渲染結果與上面等價
  render(h) {
    return h('div', {
      'class': {
        'is-red': this.isRed
      }
    }, [
      h('p', '這是一個 render 事例')
    ])
  }
}

render 函數中如何表示指令

Vue 模板具備各類便捷功能,以便向模板添加基本邏輯和綁定功能,如 v-ifv-forv-moel指令等。 在render函數中是沒法使用這些指令的。 取而代之的是以純 JS 來實現,對於大多數指令而言,這也是比較簡單的。數組

v-if

v-if 用純 JS 實現很簡單,只需圍繞createElement調用使用 if(expr)語句便可。微信

v-for

v-for可使用for-ofArray.mapArray.filter等的JS方法中的任何一種來實現。咱們能夠經過很是有趣的方式將它們組合在一塊兒,以實現過濾或狀態切片,而無需計算屬性。dom

例如,有如下 Vue 的模板代碼函數

<template>
  <ul>
    <li v-for="pea of pod">
      
    </li>
  </ul>
</template>

能夠用下面的 render 函數來實現上面的效果:工具

render(h) {
  return h('ul', this.pod.map(pea => h('li', pea.name)));
}

v-model

咱們知道,v-model只是bind屬性與value的語法糖,並在觸發input事件時設置數據屬性。可是,在render函數沒有這樣的簡寫,咱們須要本身實現。

假設,在 Vue 中,咱們有以下的結構:

<template>
  <input v-model='myBoundProperty'/>
</template>

上面代碼等價於:

<template>
  <input :value="myBoundProperty" @input="myBoundProperty = $event.target.value"/>
</template>

在 render 函數中能夠用下面方式來實現上面的代碼:

render(h) {
  return h('input', {
    domProps: {
      value: this.myBoundProperty
    },
    on: {
      input: e => {
        this.myBoundProperty = e.target.value
      }
    }
  })
}

v-bind

attributeproperty 這兩種類型的綁定被放在元素定義中,如arttrspropsdomProps( valueinnerHTML之類的東西)。

render(h) {
  return h('div', {
    attrs: {
      // <div :id="myCustomId">
      id: this.myCustomId
    },

    props: {
      // <div :someProp="someonePutSomethingHere">
      someProp: this.someonePutSomethingHere
    },

    domProps: {
       // <div :value="somethingElse">
      value: this.somethingElse
    }
  });
}

須要注意的是,對於 classstyle的綁定是直接在定義的根進行處理,而不是做爲attrspropsdomProps處理。

render(h) {
  return h('div', {
    // 「類」是JS中的保留關鍵字,所以必須引用它。
    'class': {
      myClass: true,
      theirClass: false
    },

    style: {
      backgroundColor: 'green'
    }
  });
}

v-on

對事件處理程也是直接添加到元素定義中 on 定義

render(h) {
  return h('div', {
    on: {
      click(e) {
        console.log('I got clickeded!')
      }
    }
  });
}

事件的修飾符能夠在處理程序內部實現:

  • .stop -> e.stopPropagation()
  • .prevent -> e.preventDefault()
  • .self -> if (e.target !== e.currentTarget) return

鍵盤修飾符

  • .[TARGET_KEY_CODE] -> if (event.keyCode !== TARGET_KEY_CODE) return
  • .[MODIFIER] -> if (!event.MODIFIERKey) return

特殊屬性

Slots 能夠經過this.$slots做爲createElement()節點的數組來訪問插槽。

做用域插槽存儲在this.$scopedSlots[scope](props:object) 中,做爲返回createElement()節點數組的函數。


代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

原文:https://vuejsbook.com/introdu...


交流

文章每週持續更新,能夠微信搜索「 大遷世界 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,另外關注公衆號,後臺回覆福利,便可看到福利,你懂的。

相關文章
相關標籤/搜索