11.更靈活的組件:Render 函數(shù)與 Functional Render

更靈活的組件:Render 函數(shù)與 Functional Render

Vue.js 2.x 與 Vue.js 1.x 最大的區(qū)別就在于 2.x 使用了 Virtual DOM(虛擬 DOM)來(lái)更新 DOM 節(jié)點(diǎn),提升渲染性能胆数。

一般來(lái)說(shuō),我們寫(xiě) Vue.js 組件踩晶,模板都是寫(xiě)在 <template> 內(nèi)的巫财,但它并不是最終呈現(xiàn)的內(nèi)容斜棚,template 只是一種對(duì)開(kāi)發(fā)者友好的語(yǔ)法拄氯,能夠一眼看到 DOM 節(jié)點(diǎn)火诸,容易維護(hù)锦针,在 Vue.js 編譯階段,會(huì)解析為 Virtual DOM惭蹂。

與 DOM 操作相比伞插,Virtual DOM 是基于 JavaScript 計(jì)算的割粮,所以開(kāi)銷(xiāo)會(huì)小很多盾碗。下圖演示了 Virtual DOM 運(yùn)行的過(guò)程:

image

正常的 DOM 節(jié)點(diǎn)在 HTML 中是這樣的:

<div id="main">
  <p>文本內(nèi)容</p>
  <p>文本內(nèi)容</p>
</div>

用 Virtual DOM 創(chuàng)建的 JavaScript 對(duì)象一般會(huì)是這樣的:

const vNode = {
  tag: 'div',
  attributes: {
    id: 'main'
  },
  children: [
    // p 節(jié)點(diǎn)
  ]
}

vNode 對(duì)象通過(guò)一些特定的選項(xiàng)描述了真實(shí)的 DOM 結(jié)構(gòu)。

在 Vue.js 中舀瓢,對(duì)于大部分場(chǎng)景廷雅,使用 template 足以應(yīng)付,但如果想完全發(fā)揮 JavaScript 的編程能力,或在一些特定場(chǎng)景下(后文介紹)航缀,需要使用 Vue.js 的 Render 函數(shù)商架。

Render 函數(shù)

正如上文介紹的 Virtual DOM 示例一樣,Vue.js 的 Render 函數(shù)也是類(lèi)似的語(yǔ)法芥玉,需要使用一些特定的選項(xiàng)蛇摸,將 template 的內(nèi)容改寫(xiě)成一個(gè) JavaScript 對(duì)象。

對(duì)于初級(jí)前端工程師灿巧,或想快速建站的需求赶袄,直接使用 Render 函數(shù)開(kāi)發(fā) Vue.js 組件是要比 template 困難的,原因在于 Render 函數(shù)返回的是一個(gè) JS 對(duì)象抠藕,沒(méi)有傳統(tǒng) DOM 的層級(jí)關(guān)系饿肺,配合上 if、else盾似、for 等語(yǔ)句敬辣,將節(jié)點(diǎn)拆分成不同 JS 對(duì)象再組裝,如果模板復(fù)雜零院,那一個(gè) Render 函數(shù)是難讀且難維護(hù)的溉跃。所以,絕大部分組件開(kāi)發(fā)和業(yè)務(wù)開(kāi)發(fā)门粪,我們直接使用 template 語(yǔ)法就可以了喊积,并不需要特意使用 Render 函數(shù),那樣只會(huì)增加負(fù)擔(dān)玄妈,同時(shí)也放棄了 Vue.js 最大的優(yōu)勢(shì)(React 無(wú) template 語(yǔ)法)乾吻。

很多學(xué)習(xí) Vue.js 的開(kāi)發(fā)者在遇到 Render 函數(shù)時(shí)都有點(diǎn)”躲避“,或直接放棄這部分拟蜻,這并沒(méi)有問(wèn)題绎签,因?yàn)椴挥?Render 函數(shù),照樣可以寫(xiě)出優(yōu)秀的 Vue.js 程序酝锅。不過(guò)诡必,Render 函數(shù)并沒(méi)有想象中的那么復(fù)雜,只是配置項(xiàng)特別多搔扁,一時(shí)難以記住爸舒,但歸根到底,Render 函數(shù)只有 3 個(gè)參數(shù)稿蹲。

來(lái)看一組 template 和 Render 寫(xiě)法的對(duì)照:

<template>
  <div id="main" class="container" style="color: red">
    <p v-if="show">內(nèi)容 1</p>
    <p v-else>內(nèi)容 2</p>
  </div>
</template>
<script>
  export default {
    data () {
      return {
        show: false
      }
    }
  }
</script>

export default {
  data () {
    return {
      show: false
    }
  },
  render: (h) => {
    let childNode;
    if (this.show) {
      childNode = h('p', '內(nèi)容 1');
    } else {
      childNode = h('p', '內(nèi)容 2');
    }
    
    return h('div', {
      attrs: {
        id: 'main'
      },
      class: {
        container: true
      },
      style: {
        color: 'red'
      }
    }, [childNode]);
  }
}

這里的 h扭勉,即 createElement,是 Render 函數(shù)的核心苛聘⊥垦祝可以看到忠聚,template 中的 v-if / v-else 等指令,都被 JS 的 if / else 替代了唱捣,那 v-for 自然也會(huì)被 for 語(yǔ)句替代两蟀。

h 有 3 個(gè)參數(shù),分別是:

  1. 要渲染的元素或組件震缭,可以是一個(gè) html 標(biāo)簽赂毯、組件選項(xiàng)或一個(gè)函數(shù)(不常用),該參數(shù)為必填項(xiàng)拣宰。示例:

    // 1. html 標(biāo)簽
    h('div');
    // 2. 組件選項(xiàng)
    import DatePicker from '../component/date-picker.vue';
    h(DatePicker);
    
    
  2. 對(duì)應(yīng)屬性的數(shù)據(jù)對(duì)象欢瞪,比如組件的 props、元素的 class徐裸、綁定的事件遣鼓、slot、自定義指令等重贺,該參數(shù)是可選的骑祟,上文所說(shuō)的 Render 配置項(xiàng)多,指的就是這個(gè)參數(shù)气笙。該參數(shù)的完整配置和示例次企,可以到 Vue.js 的文檔查看,沒(méi)必要全部記住潜圃,用到時(shí)查閱就好:createElement 參數(shù)缸棵。

  3. 子節(jié)點(diǎn),可選谭期,String 或 Array堵第,它同樣是一個(gè) h。示例:

    [
      '內(nèi)容',
      h('p', '內(nèi)容'),
      h(Component, {
        props: {
          someProp: 'foo'
        }
      })
    ]
    
    

約束

所有的組件樹(shù)中隧出,如果 vNode 是組件或含有組件的 slot踏志,那么 vNode 必須唯一。以下兩個(gè)示例都是錯(cuò)誤的:

// 局部聲明組件
const Child = {
  render: (h) => {
    return h('p', 'text');
  }
}

export default {
  render: (h) => {
    // 創(chuàng)建一個(gè)子節(jié)點(diǎn)胀瞪,使用組件 Child
    const ChildNode = h(Child);
    
    return h('div', [
      ChildNode,
      ChildNode
    ]);
  }
}

{
  render: (h) => {
    return h('div', [
      this.$slots.default,
      this.$slots.default
    ])
  }
}

重復(fù)渲染多個(gè)組件或元素针余,可以通過(guò)一個(gè)循環(huán)和工廠(chǎng)函數(shù)來(lái)解決:

const Child = {
  render: (h) => {
    return h('p', 'text');
  }
}

export default {
  render: (h) => {
    const children = Array.apply(null, {
      length: 5
    }).map(() => {
      return h(Child);
    });
    return h('div', children);
  }
}

對(duì)于含有組件的 slot,復(fù)用比較復(fù)雜凄诞,需要將 slot 的每個(gè)子節(jié)點(diǎn)都克隆一份圆雁,例如:

{
  render: (h) => {
    function cloneVNode (vnode) {
      // 遞歸遍歷所有子節(jié)點(diǎn),并克隆
      const clonedChildren = vnode.children && vnode.children.map(vnode => cloneVNode(vnode));
      const cloned = h(vnode.tag, vnode.data, clonedChildren);
      cloned.text = vnode.text;
      cloned.isComment = vnode.isComment;
      cloned.componentOptions = vnode.componentOptions;
      cloned.elm = vnode.elm;
      cloned.context = vnode.context;
      cloned.ns = vnode.ns;
      cloned.isStatic = vnode.isStatic;
      cloned.key = vnode.key;

      return cloned;
    }

    const vNodes = this.$slots.default === undefined ? [] : this.$slots.default;
    const clonedVNodes = this.$slots.default === undefined ? [] : vNodes.map(vnode => cloneVNode(vnode));
    
    return h('div', [
      vNodes,
      clonedVNodes
    ])
  }
}

在 Render 函數(shù)里創(chuàng)建了一個(gè) cloneVNode 的工廠(chǎng)函數(shù)帆谍,通過(guò)遞歸將 slot 所有子節(jié)點(diǎn)都克隆了一份伪朽,并對(duì) VNode 的關(guān)鍵屬性也進(jìn)行了復(fù)制。

深度克隆 slot 并非 Vue.js 內(nèi)置方法既忆,也沒(méi)有得到推薦驱负,屬于黑科技,在一些特殊的場(chǎng)景才會(huì)使用到患雇,正常業(yè)務(wù)幾乎是用不到的跃脊。比如 iView 組件庫(kù)的穿梭框組件 Transfer,就用到了這種方法:

image

它的使用方法是:

<Transfer
    :data="data"
    :target-keys="targetKeys"
    :render-format="renderFormat">
  <div :style="{float: 'right', margin: '5px'}">
    <Button size="small" @click="reloadMockData">Refresh</Button>
  </div>
</Transfer>

示例中的默認(rèn) slot 是一個(gè) Refresh 按鈕苛吱,使用者只寫(xiě)了一遍酪术,但在 Transfer 組件中,是通過(guò)克隆 VNode 的方法翠储,顯示了兩遍绘雁。如果不這樣做,就要聲明兩個(gè)具名 slot援所,但是左右兩個(gè)的邏輯可能是完全一樣的庐舟,使用者就要寫(xiě)兩個(gè)一模一樣的 slot,這是不友好的住拭。

Render 函數(shù)的基本用法還有很多挪略,比如 v-model 的用法、事件和修飾符滔岳、slot 等杠娱,讀者可以到 Vue.js 文檔閱讀。Vue.js 渲染函數(shù)

Render 函數(shù)使用場(chǎng)景

上文說(shuō)到谱煤,一般情況下是不推薦直接使用 Render 函數(shù)的摊求,使用 template 足以,在 Vue.js 中刘离,使用 Render 函數(shù)的場(chǎng)景室叉,主要有以下 4 點(diǎn):

  1. 使用兩個(gè)相同 slot。在 template 中硫惕,Vue.js 不允許使用兩個(gè)相同的 slot太惠,比如下面的示例是錯(cuò)誤的:

    <template>
      <div>
        <slot></slot>
        <slot></slot>
      </div>
    </template>
    
    

    解決方案就是上文中講到的約束,使用一個(gè)深度克隆 VNode 節(jié)點(diǎn)的方法疲憋。

  2. 在 SSR 環(huán)境(服務(wù)端渲染)凿渊,如果不是常規(guī)的 template 寫(xiě)法,比如通過(guò) Vue.extend 和 new Vue 構(gòu)造來(lái)生成的組件實(shí)例缚柳,是編譯不過(guò)的埃脏,在前面小節(jié)也有所介紹∏锩Γ回顧上一節(jié)的 $Alert 組件的 notification.js 文件彩掐,當(dāng)時(shí)是使用 Render 函數(shù)來(lái)渲染 Alert 組件,如果改成另一種寫(xiě)法灰追,在 SSR 中會(huì)報(bào)錯(cuò)堵幽,對(duì)比兩種寫(xiě)法:

    // 正確寫(xiě)法
    import Alert from './alert.vue';
    import Vue from 'vue';
    
    Alert.newInstance = properties => {
      const props = properties || {};
    
      const Instance = new Vue({
        data: props,
        render (h) {
          return h(Alert, {
            props: props
          });
        }
      });
    
      const component = Instance.$mount();
      document.body.appendChild(component.$el);
    
      const alert = Instance.$children[0];
    
      return {
        add (noticeProps) {
          alert.add(noticeProps);
        },
        remove (name) {
          alert.remove(name);
        }
      }
    };
    
    export default Alert;
    
    
    // 在 SSR 下報(bào)錯(cuò)的寫(xiě)法
    import Alert from './alert.vue';
    import Vue from 'vue';
    
    Alert.newInstance = properties => {
      const props = properties || {};
    
      const div = document.createElement('div');
      div.innerHTML = `<Alert ${props}></Alert>`;
      document.body.appendChild(div);
      
      const Instance = new Vue({
        el: div,
        data: props,
        components: { Alert }
      });
    
      const alert = Instance.$children[0];
    
      return {
        add (noticeProps) {
          alert.add(noticeProps);
        },
        remove (name) {
          alert.remove(name);
        }
      }
    };
    
    export default Alert;
    
    
  3. 在 runtime 版本的 Vue.js 中狗超,如果使用 Vue.extend 手動(dòng)構(gòu)造一個(gè)實(shí)例,使用 template 選項(xiàng)是會(huì)報(bào)錯(cuò)的朴下,在第 9 節(jié)中也有所介紹努咐。解決方案也很簡(jiǎn)單,把 template 改寫(xiě)為 Render 就可以了殴胧。需要注意的是渗稍,在開(kāi)發(fā)獨(dú)立組件時(shí),可以通過(guò)配置 Vue.js 版本來(lái)使 template 選項(xiàng)可用团滥,但這是在自己的環(huán)境竿屹,無(wú)法保證使用者的 Vue.js 版本,所以對(duì)于提供給他人用的組件灸姊,是需要考慮兼容 runtime 版本和 SSR 環(huán)境的拱燃。

  4. 這可能是使用 Render 函數(shù)最重要的一點(diǎn)。一個(gè) Vue.js 組件力惯,有一部分內(nèi)容需要從父級(jí)傳遞來(lái)顯示扼雏,如果是文本之類(lèi)的,直接通過(guò) props 就可以夯膀,如果這個(gè)內(nèi)容帶有樣式或復(fù)雜一點(diǎn)的 html 結(jié)構(gòu)诗充,可以使用 v-html 指令來(lái)渲染,父級(jí)傳遞的仍然是一個(gè) HTML Element 字符串诱建,不過(guò)它僅僅是能解析正常的 html 節(jié)點(diǎn)且有 XSS 風(fēng)險(xiǎn)蝴蜓。當(dāng)需要最大化程度自定義顯示內(nèi)容時(shí),就需要 Render 函數(shù)俺猿,它可以渲染一個(gè)完整的 Vue.js 組件茎匠。你可能會(huì)說(shuō),用 slot 不就好了押袍?的確诵冒,slot 的作用就是做內(nèi)容分發(fā)的,但在一些特殊組件中谊惭,可能 slot 也不行汽馋。比如一個(gè)表格組件 Table,它只接收兩個(gè) props:列配置 columns 和行數(shù)據(jù) data圈盔,不過(guò)某一列的單元格豹芯,不是只將數(shù)據(jù)顯示出來(lái)那么簡(jiǎn)單,可能帶有一些復(fù)雜的操作驱敲,這種場(chǎng)景只用 slot 是不行的铁蹈,沒(méi)辦法確定是那一列的 slot。這種場(chǎng)景有兩種解決方案众眨,其一就是 Render 函數(shù)握牧,下一節(jié)的實(shí)戰(zhàn)就是開(kāi)發(fā)這樣一個(gè) Table 組件容诬;另一種是用作用域 slot(slot-scope),后面小節(jié)也會(huì)詳細(xì)介紹沿腰。

Functional Render

Vue.js 提供了一個(gè) functional 的布爾值選項(xiàng)览徒,設(shè)置為 true 可以使組件無(wú)狀態(tài)和無(wú)實(shí)例,也就是沒(méi)有 data 和 this 上下文矫俺。這樣用 Render 函數(shù)返回虛擬節(jié)點(diǎn)可以更容易渲染,因?yàn)楹瘮?shù)化組件(Functional Render)只是一個(gè)函數(shù)掸冤,渲染開(kāi)銷(xiāo)要小很多厘托。

使用函數(shù)化組件,Render 函數(shù)提供了第二個(gè)參數(shù) context 來(lái)提供臨時(shí)上下文稿湿。組件需要的 data铅匹、props、slots饺藤、children包斑、parent 都是通過(guò)這個(gè)上下文來(lái)傳遞的,比如 this.level 要改寫(xiě)為 context.props.level涕俗,this.$slots.default 改寫(xiě)為 context.children罗丰。

您可以閱讀 Vue.js 文檔—函數(shù)式組件 來(lái)查看示例。

函數(shù)化組件在業(yè)務(wù)中并不是很常用再姑,而且也有類(lèi)似的方法來(lái)實(shí)現(xiàn)萌抵,比如某些場(chǎng)景可以用 is 特性來(lái)動(dòng)態(tài)掛載組件。函數(shù)化組件主要適用于以下兩個(gè)場(chǎng)景:

  • 程序化地在多個(gè)組件中選擇一個(gè)元镀;
  • 在將 children绍填、props、data 傳遞給子組件之前操作它們栖疑。

比如上文說(shuō)過(guò)的讨永,某個(gè)組件需要使用 Render 函數(shù)來(lái)自定義,而不是通過(guò)傳遞普通文本或 v-html 指令遇革,這時(shí)就可以用 Functional Render卿闹,來(lái)看下面的示例:

  1. 首先創(chuàng)建一個(gè)函數(shù)化組件 render.js

    // render.js
    export default {
      functional: true,
      props: {
        render: Function
      },
      render: (h, ctx) => {
        return ctx.props.render(h);
      }
    };
    
    

    它只定義了一個(gè) props:render,格式為 Function萝快,因?yàn)槭?functional比原,所以在 render 里使用了第二個(gè)參數(shù) ctx 來(lái)獲取 props。這是一個(gè)中間文件杠巡,并且可以復(fù)用量窘,其它組件需要這個(gè)功能時(shí),都可以引入它氢拥。

  2. 創(chuàng)建組件:

    <!-- my-component.vue -->
    <template>
      <div>
        <Render :render="render"></Render>
      </div>
    </template>
    <script>
      import Render form './render.js';
      
      export default {
        components: { Render },
        props: {
          render: Function
        }
      }
    </script>
    
    
  3. 使用上面的 my-compoennt 組件:

    <!-- demo.vue -->
    <template>
      <div>
        <my-component :render="render"></my-component>
      </div>
    </template>
    <script>
      import myComponent from '../components/my-component.vue';
      
      export default {
        components: { myComponent },
        data () {
          return {
            render: (h) => {
              return h('div', {
                style: {
                  color: 'red'
                }
              }, '自定義內(nèi)容');
            }
          }
        }
      }
    </script>
    
    

這里的 render.js 因?yàn)橹皇前?demo.vue 中的 Render 內(nèi)容過(guò)繼蚌铜,并無(wú)其它用處锨侯,所以用了 Functional Render。

就此例來(lái)說(shuō)冬殃,完全可以用 slot 取代 Functional Render囚痴,那是因?yàn)橹挥?render 這一個(gè) prop。如果示例中的 <Render> 是用 v-for 生成的审葬,也就是多個(gè)時(shí)深滚,用 一個(gè) slot 是實(shí)現(xiàn)不了的,那時(shí)用 Render 函數(shù)就很方便了涣觉,后面章節(jié)會(huì)專(zhuān)門(mén)介紹痴荐。

結(jié)語(yǔ)

如果想換一種思路寫(xiě) Vue.js,就試試 Render 函數(shù)吧官册,它會(huì)讓你“又愛(ài)又恨”生兆!

注:本節(jié)部分內(nèi)容參考了《Vue.js 實(shí)戰(zhàn)》(清華大學(xué)出版社),部分代碼參考 iView膝宁。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鸦难,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子员淫,更是在濱河造成了極大的恐慌合蔽,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件介返,死亡現(xiàn)場(chǎng)離奇詭異辈末,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)映皆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)挤聘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人捅彻,你說(shuō)我怎么就攤上這事组去。” “怎么了步淹?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵从隆,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我缭裆,道長(zhǎng)键闺,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任澈驼,我火速辦了婚禮辛燥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己挎塌,他們只是感情好徘六,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著榴都,像睡著了一般待锈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘴高,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天竿音,我揣著相機(jī)與錄音,去河邊找鬼拴驮。 笑死春瞬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的莹汤。 我是一名探鬼主播快鱼,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼颠印,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼纲岭!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起线罕,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤止潮,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后钞楼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體喇闸,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年询件,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了燃乍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宛琅,死狀恐怖刻蟹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嘿辟,我是刑警寧澤舆瘪,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站红伦,受9級(jí)特大地震影響英古,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜昙读,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一召调、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦某残、人聲如沸国撵。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)介牙。三九已至,卻和暖如春澳厢,著一層夾襖步出監(jiān)牢的瞬間环础,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工剩拢, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留线得,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓徐伐,卻偏偏與公主長(zhǎng)得像贯钩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子办素,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 探索Vue高階組件 高階組件(HOC)是 React 生態(tài)系統(tǒng)的常用詞匯角雷,React 中代碼復(fù)用的主要方式就是使用...
    君惜丶閱讀 963評(píng)論 0 2
  • 探索Vue高階組件高階組件(HOC)是 React 生態(tài)系統(tǒng)的常用詞匯,React 中代碼復(fù)用的主要方式就是使用高...
    videring閱讀 10,616評(píng)論 5 30
  • 前幾天想學(xué)學(xué)Vue中怎么編寫(xiě)可復(fù)用的組件性穿,提到要對(duì)Vue的render函數(shù)有所了解勺三。可仔細(xì)一想需曾,對(duì)于Vue的ren...
    kangaroo_v閱讀 116,012評(píng)論 13 171
  • 實(shí)戰(zhàn) 6:可用 slot-scope 自定義列的表格組件——Table 上一節(jié)吗坚,我們基于 Render 函數(shù)實(shí)現(xiàn)了...
    中午吃啥_f330閱讀 3,017評(píng)論 0 2
  • Vue 實(shí)例 屬性和方法 每個(gè) Vue 實(shí)例都會(huì)代理其 data 對(duì)象里所有的屬性:var data = { a:...
    云之外閱讀 2,202評(píng)論 0 6