溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

淺談vue渲染方式render和template

發(fā)布時(shí)間:2020-07-18 13:34:14 來(lái)源:億速云 閱讀:248 作者:小豬 欄目:web開(kāi)發(fā)

小編這次要給大家分享的是淺談vue渲染方式render和template,文章內(nèi)容豐富,感興趣的小伙伴可以來(lái)了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。

render函數(shù)詳解

Vue中的Render函數(shù)中有一個(gè)參數(shù),這個(gè)參數(shù)是一個(gè)函數(shù)通常我們叫做h。其實(shí)這個(gè)h叫做createElement。Render函數(shù)將createElement的返回值放到了HTML中

createElement這個(gè)函數(shù)中有3個(gè)參數(shù)

第一個(gè)參數(shù)(必要參數(shù)):主要用于提供DOM的html內(nèi)容,類(lèi)型可以是字符串、對(duì)象或函數(shù)

第二個(gè)參數(shù)(類(lèi)型是對(duì)象,可選):用于設(shè)置這個(gè)DOM的一些樣式、屬性、傳的組件的參數(shù)、綁定事件之類(lèi)

第三個(gè)參數(shù)(類(lèi)型是數(shù)組,數(shù)組元素類(lèi)型是VNode,可選):主要是指該結(jié)點(diǎn)下還有其他結(jié)點(diǎn),用于設(shè)置分發(fā)的內(nèi)容,包括新增的其他組件。注意,組件樹(shù)中的所有VNode必須是唯一的

// @return {VNode}
createElement(
 // {String | Object | Function}
 // 一個(gè)HTML標(biāo)簽字符串,組件選項(xiàng)對(duì)象,或者一個(gè)返回值類(lèi)型為String/Object的函數(shù)。該參數(shù)是必須的
 'div',

 // {Object}
 // 一個(gè)包含模板相關(guān)屬性的數(shù)據(jù)對(duì)象,這樣我們可以在template中使用這些屬性,該參數(shù)是可選的。
{
   attrs: {
    name: headingId,
    href: '#'+headingId
  },
   style: {
    color: 'red',
    fontSize: '20px'
  },
   'class': {
    foo: true,
    bar: false
   },
   // DOM屬性
   domProps: {
     innerHTML: 'baz'
   },
   // 組件props
    props: {
     myProp: 'bar'
   },
    // 事件監(jiān)聽(tīng)基于 'on'
    // 所以不再支持如 'v-on:keyup.enter' 修飾語(yǔ)
    // 需要手動(dòng)匹配 KeyCode 
    on: {
      click: function(event) {
        event.preventDefault();
        console.log(111);
     }
    }
 }

 // {String | Array}
 // 子節(jié)點(diǎn)(VNodes)由 createElement() 構(gòu)建而成??蛇x參數(shù)
 // 或簡(jiǎn)單的使用字符串來(lái)生成的 "文本節(jié)點(diǎn)"。
[
  'xxxx',
  createElement('h2', '一則頭條'),
  createElement(MyComponent, {
   props: {
    someProp: 'xxx'
  }
 }),
  this.$slots.default
]
)

什么時(shí)候用render函數(shù)?

假設(shè)我們要封裝一套按鈕組件,按鈕有四個(gè)樣式(success、error、warning、default)。首先,你可能會(huì)想到如下實(shí)現(xiàn)

<template>
<divclass="btn btn-success"v-if="type === 'success'">{{ text }}</div>
<divclass="btn btn-danger"v-else-if="type === 'danger'">{{ text }}</div>
<divclass="btn btn-warning"v-else-if="type === 'warning'">{{ text }}</div>
</template>

雖然我們這樣實(shí)現(xiàn)沒(méi)有問(wèn)題,但是如果現(xiàn)在有十幾個(gè)樣式的情況下我們就需要寫(xiě)N多個(gè)判斷,如果遇到了這種情況我們就可以選擇使用render函數(shù)。

其實(shí)簡(jiǎn)單的來(lái)說(shuō)就是template適合簡(jiǎn)單的組件封裝,然后render函數(shù)適合復(fù)雜的組件封裝

<script>
Vue.component("A-button", {
    props: {
      type: {
        type: String,
        default: 'default'
     },
      text: {
        type: String,
        default: '按鈕'
     }
   },
    computed: {
      tag() {
        switch(this.type) {
          case'success':
            return1;
          case'danger':
            return2;
          case'warning':
            return3;
          default:
            return1;
       }
     }
   },
    render(h) {
      returnh('div', {
        class: {
          btn: true,
          'btn-success': this.type==='success',
          'btn-danger': this.type==='danger',
          'btn-warning': this.type==='warning'
       },
        domProps: {
          //innerText: this.text,
       },
        on: {
          click: this.handleClick
       }
     },
      this.$slots.default
     );
   },
    methods: {
      handleClick() {
        console.log('-----------------------');
        console.log('li');
     }
   }
 })

  letvm=newVue({
    el: "#app"
 })
</script>

template與render函數(shù)對(duì)比

template----html的方式做渲染
render----js的方式做渲染

render(提供)是一種編譯方式
render里有一個(gè)函數(shù)h,這個(gè)h的作用是將單文件組件進(jìn)行虛擬DOM的創(chuàng)建,然后再通過(guò)render進(jìn)行解析。
h就是createElement()方法:createElement(標(biāo)簽名稱(chēng),屬性配置,children)

template也是一種編譯方式,但是template最終還是要通過(guò)render的方式再次進(jìn)行編譯。

區(qū)別:
        1、render渲染方式可以讓我們將js發(fā)揮到極致,因?yàn)閞ender的方式其實(shí)是通過(guò)createElement()進(jìn)行虛擬DOM的創(chuàng)建。邏輯性比較強(qiáng),適合復(fù)雜的組件封裝。
        2、template是類(lèi)似于html一樣的模板來(lái)進(jìn)行組件的封裝。
        3、render的性能比template的性能好很多
        4、render函數(shù)優(yōu)先級(jí)大于template

案例一:template和render的方式渲染標(biāo)題標(biāo)簽:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <h-title level="1">標(biāo)題</h-title>
    <h-title level="2">標(biāo)題</h-title>
    <h-title level="3">標(biāo)題</h-title>
  </div>
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <script>
    Vue.component("h-title",{
      /*  template渲染  */
      // template:`
      //   <div>
      //     <h2 v-if="level==1"><slot></slot></h2>  
      //     <h3 v-else-if="level==2"><slot></slot></h3>  
      //     <h4 v-else-if="level==3"><slot></slot></h4>  
      //   </div>
      // `,
      
      /*  render渲染  */
      render:function(h){
        // createElement(標(biāo)簽名稱(chēng),屬性配置,children)
        return h("h"+this.level,
          {
            attrs:{
              "data-id":10
            }
          },
          // 相當(dāng)于<slot></slot>標(biāo)簽接收
          this.$slots.default
        )
      },
      props:{
        level:{
          type:String
        }
      }
    });
    let vm=new Vue({
      el:"#app"
    });
  </script>
</body>
</html>

案例二:render方式模擬button:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    *{margin: 0;padding: 0;}
    .btn{
      width: 80px;
      line-height: 40px;
      text-align: center;
      color:#fff;
      border-radius: 5px;
      background-color: #ccc;
    }
    .success{background-color: green;}
    .error{background-color: red;}
    .info{background-color: pink;}
  </style>
</head>
<body>
  <div id="app">
    <wql-button type="success">成功</wql-button>
    <wql-button type="info">提示</wql-button>
    <wql-button type="error">報(bào)錯(cuò)</wql-button>
    <wql-button>默認(rèn)</wql-button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    Vue.component("wql-button",{
      render:function(h){
        return h("div",{
          class:{
            btn:true,
            success:this.type=="success",
            error:this.type=="error",
            info:this.type=="info"
          }
        },this.$slots.default);
      },
      props:{
        type:{
          type:String
        }
      }
    });
    let vm=new Vue({
      el:"#app"
    });
  </script>
</body>
</html>

看完這篇關(guān)于淺談vue渲染方式render和template的文章,如果覺(jué)得文章內(nèi)容寫(xiě)得不錯(cuò)的話(huà),可以把它分享出去給更多人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI