函數化組件

函數化組件

Vue提供了一個functional的布爾值選項,設置爲true可使組件無狀態和無實例,也就是沒有datathis上下文。這樣用render函數返回虛擬節點能夠更容易渲染,由於函數化組件只是一個函數,渲染開銷要小不少。html

使用函數化組件時,Render函數提供了第二個參數context來提供臨時上下文。組件須要的datapropslotschildrenparent都是經過這個上下文來傳遞。好比this.level要改寫爲context.props.levelthis.$slots.default改變爲context.childrenvue

用函數化組件展現一個根據數據智能選擇不一樣組件的場景:數組

<p data-height="365" data-theme-id="0" data-slug-hash="mKRKGm" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="Vue-函數化組件-根據數據選擇組件" class="codepen">See the Pen Vue-函數化組件-根據數據選擇組件 by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>瀏覽器

函數化組件主要適用於如下兩個場景:babel

  1. 程序化地在多個組件中選擇一個。
  2. 在將childrenpropsdata傳遞給子組件以前操做它們。

JSX

爲了讓Render函數更好地書寫和閱讀,Vue提供了插件babel-plugin-transform-vue-jsx來支持JSX語法。app

使用createElement時,經常使用配置:async

<p data-height="365" data-theme-id="0" data-slug-hash="Vdpwpz" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="Vue-createElement" class="codepen">See the Pen Vue-createElement by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>函數

JSX寫法:this

<p data-height="300" data-theme-id="0" data-slug-hash="eKvYvm" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="Vue-JSX" class="codepen">See the Pen Vue-JSX by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>插件

實戰:使用Render函數開發可排序的表格組件

表格組件的全部的內容(表頭和行數據)由兩個prop構成:columnsdata。二者都是數組,columns用來描述每列的信息,並渲染在表頭<head>內,能夠指定某一列是否須要排序;data時每一行的數據,由columns決定每一行裏各列的順序。

爲了讓排序後的columnsdata不影響原始數據,給v-table組件的data選項添加兩個對應的數據,組件全部的操做將在這兩個數據上完成,不對原始數據作任何處理。

columns的每一項是一個對象,其中titlekey字段是必填的,用來標識這列的表頭標題,key的對應data中列內容的字段名。sortable是選填字段,若是值爲true,說明該列須要排序。

v-talbe組件的prop:columnsdata的數據已經從父級傳遞過來,v-table不直接使用它們,而是使用data選項的currentColumnscurrentData。因此在v-table初始化時,須要把columnsdata賦值給currentColumnscurrentData。在v-tablemethods選項裏定義兩個方法用來複制,並在mounted鉤子內調用。

map()是JavaScript數組的一個方法,根據傳入的函數從新構造一個新數組。

排序分升序(asc)和降序(desc)兩種,並且同時只能對一列數據進行排序,與其餘列互斥,爲了標識當前列的排序狀態,在map列添加數據時,默認給每列都添加一個_sortType的字段,而且賦值爲normal,表示默認排序(也就是不排序)。

在排序後,currentData每項的順序可能都會發生變化,因此給currentColumnscurrentData的每一個數據都添加_index字段,表明當前數據在原始數據中的索引。

render(h) {
    var ths = [],
        trs = [];
    return h('table', [
        h('thead', [
            h('tr', ths)
        ]),
        h('tbody', trs)
    ])
}

這裏的h就是createElement,只是換了個名稱。

表格主題trs是一個二維數組,數據由currentColumnscurrentData組成。

先遍歷全部的行,而後再每一行內再遍歷各列,最終組合出主題內容節點trs

若是col.sortable沒有定義,或值爲false,就直接把col.title渲染出來,不然除了渲染title,還加了兩個<a>元素來實現升序和降序的操做。

排序使用了JavaScript數組的sort()方法,這裏之因此返回1-1,而不直接返回a[key]<b[key],也就是truefalse,是由於在部分瀏覽器對sort()的處理不一樣,而1-1能夠作到兼容。

排序前,先將全部列的排序狀態都重置爲normal,而後設置當前列的排序狀態(ascdesc),對用到render的<a>元素的class名稱on,後面經過CSS來高亮顯示當前列的排序狀態。

當渲染完表格後,父級修改了data數據,好比增長或刪除,v-tablecurrentData也應該更新,若是某列已經存在排序狀態,更新後應該直接處理一次排序。

經過遍歷currentColumns來找出是否按某一列進行過排序,若是有,就按照當前排序狀態對更新後的數據作一次排序操做。

<p data-height="365" data-theme-id="0" data-slug-hash="XYMmJr" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="Vue-可排序表格組件" class="codepen">See the Pen Vue-可排序表格組件 by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>

實戰:留言列表

發佈一條留言,須要的數據有暱稱和留言內容,發佈操做應該在根實例app內完成。留言列表的數據也是從app獲取。

數組list存儲了全部的留言內容,經過函數handleSendlist添加一項留言數據,添加成後把texrarea文本框置空。

Render函數內的節點使用v-model:動態綁定value,而且監聽input事件,把輸入的內容經過$emit('input')派發給父組件。

列表數據list爲空時,渲染一個「列表爲空」的信息提示節點;不爲空時,每一個list-item贏包含暱稱、留言內容和回覆按鈕3個子節點。

this.list.forEach至關於template裏的v-for指令,遍歷出每條留言。句柄handleReply直接向父組件派發一個事件reply,父組件(app)接收後,將當前list-item的暱稱提取,並設置到v-textarea內。

<p data-height="365" data-theme-id="0" data-slug-hash="ZRKGrR" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="Vue-留言列表" class="codepen">See the Pen Vue-留言列表 by whjin (@whjin) on CodePen.</p>
<script async src="https://static.codepen.io/ass...;></script>

相關文章
相關標籤/搜索