Vue核心知識-Vue的元件之render函式

littlebirdflying發表於2018-09-08

render function

  • 型別(createElement: () => VNode) => VNode

  • 詳細

    字串模板的代替方案,允許你發揮 JavaScript 最大的程式設計能力。該渲染函式接收一個 createElement 方法作為第一個引數用來建立 VNode

    如果元件是一個函式元件,渲染函式還會接收一個額外的 context 引數,為沒有例項的函式元件提供上下文資訊。

    Vue 選項中的 render 函式若存在,則 Vue 建構函式不會從 template 選項或通過 el 選項指定的掛載元素中提取出的 HTML 模板編譯渲染函式

元件中的 template 會被編譯成 render function。

下例中,直接用 render function 代替 template,結果相同。

import Vue from 'vue'

const component = {
  name: 'comp',
  // template: `
  //   <div :style="style">
  //     <slot></slot>
  //   </div>
  // `,
  render (createElement) {
    return createElement('div', {
      style: this.style
    }, this.$slots.default)
  },
  data () {
    return {
      style: {
        width: '200px',
        height: '200px',
        border: '1px solid #aaa'
      },
      value: 'component value'
    }
  }
}

new Vue({
  components: {
    CompOne: component
  },
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },
  mounted () {
    console.log(this.$refs.comp, this.$refs.span, this.$refs.comp.value)
  },
  template: `
    <div>
      <comp-one ref="comp">
        <span ref="span">{{value}}</span>
      </comp-one>
    </div>
  `,
  render (createElement) {
    return createElement(
      'comp-one',
      {
        ref: 'comp'
      },
      [
        createElement('span', {
          ref: 'span'
        }, this.value)
      ])
  }
})
複製程式碼

createElement

createElement,是 vue 虛擬 DOM 的概念,建立出來的並不是 html 節點,而是 VNode 的一個類,類似 DOM 結構的一個結構,並存在記憶體中,它會和真正的 DOM 進行對比,若發現需要更新的 DOM,才會去轉換這部分 DOM 內容,並填到真正的 DOM 中,從而提高效能

createElement 可使用的屬性

指令

傳值 props

render (createElement) {
    return createElement(
      'comp-one',
      {
        ref: 'comp',
        props: { // props 傳值
          props1: this.value
        }
      },
      [
        createElement('span', {
          ref: 'span'
        }, this.value)
      ])
  }
複製程式碼

繫結事件

on

render (createElement) {
    return createElement(
      'comp-one',
      {
        ref: 'comp',
        on: { // 事件監聽(一),這裡是元件上監聽,需要 $emit
          click: this.handleClick
        },
      },
      [
        createElement('span', {
          ref: 'span'
        }, this.value)
      ])
  }
複製程式碼

nativeOn

render (createElement) {
    return createElement(
      'comp-one',
      {
        ref: 'comp',
        nativeOn: {
          click: this.handleClick
        }
      },
      [
        createElement('span', {
          ref: 'span'
        }, this.value)
      ])
  }
複製程式碼

nativeOn 與 on 的區別

nativeOn 也是繫結到元件上,但是不需要元件發 $emit,它會自動繫結到這個元件的根節點的原生 DOM 上,如果本身就是原生 DOM,直接繫結。

slot

// 元件中
render (createElement) {
    return createElement('div', {
      style: this.style,
      on: {
        click: () => { this.$emit('click') }
      }
    }, [
      this.$slots.header, // 通過 $slot拿到 header,如果沒命名就是 default
      this.props1
    ])
  }
// new Vue()
[
    createElement('span', {
        ref: 'span',
        slot: 'header' // 指定具名插槽
    }, this.value)
]
複製程式碼

domProps

類似原生 DOM 操作,把 span 覆蓋掉了。

[
        createElement('span', {
          ref: 'span',
          slot: 'header',
          domProps: {
            innerHTML: '<span>345</span>'
          }
        }, this.value)
      ]
複製程式碼

attrs

給 span 加一個 id。

[
        createElement('span', {
          ref: 'span',
          slot: 'header',
          // domProps: {
          //   innerHTML: '<span>345</span>'
          // }
          attrs: {
            id: 'test-id'
          }
        }, this.value)
      ]
複製程式碼

等等

總結

寫元件的方式

  • template
  • render function
  • jsx

相關文章