Vue.js組件詳解之使用slot分發內容

有一個網站是由一級導航、二級導航、左側列表、正文以及底部版權5個模塊組成,如果要將它們都組件化,這個結構可能是:

Vue.js組件詳解之使用slot分發內容

當需要讓組件組合使用,混合父組件的內容與子組件的模板時,就會用到slot,這個過程叫做內容分發。以為例,它有兩個特點:

  1. 組件不知道它的掛載點會有什麼內容。掛載點的內容是由父組件決定的
  2. 組件很可能有它自己的模板

props傳遞數據、events觸發事件和slot內容分發就構成了Vue組件的3個API來源,再複雜的組件也是由這3部分構成的。

作用域

正式介紹slot前,需要先知道一個概念:編譯的作用域。比如父組件中有如下的模板:

Vue.js組件詳解之使用slot分發內容

這裡的message就是一個slot,但是它綁定的是父組件的數據,而不是組件的數據。

父組件模板的內容是在父組件作用域內編譯,子組件模板的內容是在子組件作用域內編譯,例如下面的代碼實例:

Vue.js組件詳解之使用slot分發內容

這裡的狀態showChild綁定的是父組件的數據,如果想在子組件上綁定,那應該是:

Vue.js組件詳解之使用slot分發內容

因此,slot分發的內容,作用域是在父組件上的。

slot用法

單個slot

在子組件內使用特殊的元素就可以為這個子組件開啟一個slot,在父組件模板裡,插入在子組件標籤內的所有內容將替代子組件的標籤及它的內容。示例代碼如下:

Vue.js組件詳解之使用slot分發內容

子組件child-component的模板內定義了一個元素,並且用一個

作為默認的內容,在父組件沒有使用slot時,會渲染這段默認的文本;如果寫入了slot,那就會替換整個。所以上例渲染後的結果是:

Vue.js組件詳解之使用slot分發內容

注意:子組件內的備用內容,它的作用域是子組件本身。

具名Slot

元素指定一個name後可以分發多個內容,具名slot可以與單個slot共存,例如下面的示例:

Vue.js組件詳解之使用slot分發內容

子組件內聲明瞭3個

元素,其中在
內的沒有使用name特性,它將作為默認slot出現,父組件沒有使用slot特性的元素與內容都出現在這裡。

上例最終渲染後的結果為:

Vue.js組件詳解之使用slot分發內容

在組合使用組件時,內容分發API至關重要。

作用域插槽

作用域插槽是一種特殊的slot,使用一個可以複用的模板替換已渲染元素。概念比較難理解,我們先看一個簡單的示例來了解它的基本用法。示例代碼如下:

Vue.js組件詳解之使用slot分發內容

觀察子組件的模板,在元素上有一個類似props傳遞數據給組件的寫法msg=”XXX”,將數據傳遞到了插槽。父組件中使用了

將上面的示例渲染後的最終結果為:

Vue.js組件詳解之使用slot分發內容

作用域插槽更具代表性的用例是列表組件,允許組件自定義應該如何渲染列表每一項。示例代碼如下:

Vue.js組件詳解之使用slot分發內容

子組件my-list接收一個來自父級的prop數組books,並且將它在name為book的slot上使用v-for指令循環同時暴露一個變量bookName。

如果你仔細揣摩上面的用法,你可能會產生這樣的疑問:我直接在父組件使用v-for不就好了嗎,為什麼還繞一步,在子組件裡面循環呢?的確,如果只是針對上面的示例,這樣寫是多此一舉的。此例的用意主要是介紹作用域插槽的用法,並沒有加入使用場景,而作用於插槽的使用場景就是既可以複用子組件的slot,又可以使slot內容不一致。如果上例還在其它組件內使用,

  • 的內容渲染權是由使用者掌握的,而數據卻可以通過臨時變量(比如:props)從子組件內獲取。

    訪問slot

    在Vue.js 1.x中,想要獲取某個slot是比較麻煩的。需要用v-el間接獲取,而Vue.js 2.x提供了用來訪問被slot分發的內容的方法$slots,請看下例:

    Vue.js組件詳解之使用slot分發內容

    通過$slots可以訪問某個具名slot,this.$slots.default包括了所有沒有被包含在具名slot中的節點。

    $slots在業務中幾乎用不到,在用render函數創建組件時會比較有用,但主要還是用於獨立組件開發中。


  • 分享到:


    相關文章: