vue render函數初級學習使用

render函數的基本使用

render函數能夠接受三個參數,其中第一個參數是必填的能夠是String | Object | Function
好比說直接寫一個div的字符串javascript

render(createElement) {
    return createElement("div")
}

上邊的代碼你在審查代碼的時候你會發現他渲染出來了一個div的標籤,或者你輸入了一個你不認識的字符串,他也會渲染成一個html標籤好比說html

render(createElement) {
    return createElement("xxx")
}

他會渲染出一個XXX的標籤vue

因此若是render函數的第一個參數是String的話,表示的是HTML 標籤java

另外這個參數能夠是一個組件的名字好比說咱們須要渲染一個element的input組件json

render(createElement) {
    return createElement("el-input")
}

上邊的代碼中你會獲得一個el-input的組件,其實原本的初衷就是看到以前項目中用到的大表單千篇一概,想改造一下,感受用template太累贅因此才學習的render,render函數並不能所有替代template,你須要在合適的場景下選擇使用它,好比element源碼中tag標籤數組

render(h) {
   const classes = [ 'el-tag', this.type ? `el-tag--${this.type}` : '',
     this.tagSize ? `el-tag--${this.tagSize}` : '',
     {'is-hit': this.hit},
     {'is-circle': this.circle}
   ];
   const tagEl = (<span class={classes} style={{backgroundColor: this.color}} on-click={this.handleClick}>
     { this.$slots.default }
     {
       this.closable && <i class={{'el-tag__close': !this.circle, 'el-icon-close': !this.circle }}on-click={this.handleClose}></i>
     }
   </span>);
   
   return this.disableTransitions ? tagEl : <transition name="el-zoom-in-center">{ tagEl }</transition>;
 }

這個組件中 他們用的就是renderdom

在封裝組件時,不知道到底須要一個什麼樣的標籤組件。若是去加一堆的判斷的話,代碼量太大,但用render()函數來實現就很簡單。函數

待會咱們再來講一個不適合用render函數的地方學習

上邊element的源碼中能夠看到 render函數中 是容許使用jsx語法的,其實jsx語法說白了,我感受他就是一個語法糖,它會被編譯成一個樹狀的json樹,裏邊有被渲染出來的標籤所須要的屬性,是一個對象this

最後你能夠選擇傳入一個方法 把你的json數據return出去好比說

fun() {
     return {template: '<div></div>'}
 };
 return createElement(fun());

render函數的第二個和第三個參數是可選的,若是大家動手去使用一下上邊的代碼大家會發現,若是傳入的是字符串的話,被渲染的這個標籤除了一個標籤之外什麼都沒有,那麼第二個參數就是用來定義這個標籤上邊的屬性的

舉例說明比較常見的幾個屬性classstyle,attrs,domPropson

  • class style 這倆不用解釋

  • attrs 這個能夠定義標籤上的屬性 好比說id啊 src啊 placeholder什麼什麼的

  • domProps 這個是原生的一些屬性 好比說value 可是這個是根據你渲染的標籤有關的,加入你渲染了一個el-input的話 加value是不起做用的

  • on 標籤的原生方法

舉個例子

//高級搜索搜索圖標按鈕樣式
 let iconSearchClass = ["search-icon","icon-sousuo", "iconfont"];
// 等待渲染的原生屬性
 let componentProps = {};
// 高級搜索的input事件
 let selectInputOn={
   input:this.change,
   keyup:this.keyup,
   focus:this.focus,
   blur:this.blur
 }
 
  // 父組件屬性存儲
 for (const key in this.$attrs) {
   componentProps[key] = this.$attrs[key];
 }
 // 搜索圖標
 let searchIcon =createElement('div',{
   class: iconSearchClass
 })
 
 // 渲染input
 let searchInput = createElement("input", {
   props: componentProps,
   on: selectInputOn
 });

上邊是我以前寫的一個小demo,還有一些其餘的屬性好比說

  • props 組件的props

  • directives 自定義指令

  • scopedSlots 做用域插槽

還有一些不經常使用的屬性,具體的請參考vue官網的vue屬性那一篇

另外 在render函數裏邊是沒有v-for v-if v-model v-show 什麼什麼的這些指令的
能夠經過本身封裝函數達到相應的效果,這篇博客先作一個簡單的介紹,下一篇我會把全部的屬性作一個demo分享出來

第三個參數能夠給上邊那個標籤裏邊添加東西 好比

<div>
    <div></div>
</div>

若是你想實現這樣的效果 你能夠在第三個參數裏邊再寫一個div的字符串,第三個參數正常來說接收的是一個字符串或者一個數組,通常數組用的是比較多的,我以前的用法是數組裏邊放的是一個返回一個標籤的變量,代碼以下

// 父組件屬性存儲
 for (const key in this.$attrs) {
   componentProps[key] = this.$attrs[key];
 }
 // 搜索圖標
 let searchIcon =createElement('div',{
   class: iconSearchClass
 })
 
 // 渲染input
 let searchInput = createElement("input", {
   props: componentProps,
   on: selectInputOn
 });

 // 高級搜索圖標按鈕
 let iconBtn = createElement("div", {
   class: iconBtnClass
 });

 // 高級搜索圖標按鈕盒子
 let iconBtnBox = createElement(
   "div",
   {
     class: iconBtnBoxClass
   },
   [iconBtn]
 );
 
 // 高級搜索input欄
 let inputRow = createElement(
   "div",
   {
     class: searchBoxClass
   },
   [searchIcon,searchInput, iconBtnBox]
 );


// 渲染高級搜索
 return createElement(
   "div",
   {
     attrs: {
       id: "advancedSearch"
     }
   },
   [inputRow, (this.listShow||this.notDestruc)&&searchSlotBox]
 );

大概就是這個意思 代碼就不全沾出來了,有充字數的嫌疑,同時也能夠看到,這是一個沒有必要使用render函數的地方。。。。不靈活 並且我也沒有使用jsx,使用jsx可能還好些 被咱們組長一頓噴 沒有後續了

我這個demo巴拉巴拉寫了100多行 實際生成了大概15行html包括一些事件,並非說render很差,是要提醒你們不要爲了用而去用,要找到適合的地方再去用

render函數中插槽

  • 插槽用法
render(createElement) {
  // 等同於:<div><slot></slot></div>
  return createElement('div', this.$slots.default)
}
  • 插槽傳值
props: ['message'],
render(createElement) {
  // 等同於`<div><slot :text="message"></slot></div>`
  return createElement('div', [
    this.$scopedSlots.default({
      text: this.message
    })
  ])
}

放一個雙向數據綁定demo

render: function(createElement) {
    var self = this;
    return createElement("input", {
      domProps: {
        value: self.name
      },
      on: {
        input: function(event) {
          self.$emit("input", event.target.value);
        }
      }
    });
  },

外邊組件

<template>
        <demo :value='value' @input="demoInput"></demo>
        {{value}}
    </template>
    export default {
    data(){
        return{
         value:null,//demo  
        }
    },
    methods:{
        demoInput(val){
          this.value=val
        },
    }

效果圖

今天說了一下render的基本使用 ,下一篇會分享一個render函數的demo和其餘的用法,若有不足之處,但願批評指正

相關文章
相關標籤/搜索