vue slot scope使用_20、slot插槽的用法
重點:
單個插槽、具名插槽、作用域插槽的用法;訪問插槽的方法。
其實本小白對插槽理解的還不深,哪些場景會經常用到插槽也不了解。
但是本著“大膽猜測”的理念,我的猜測如下:
- 假設有 父組件A,有 子組件B、子組件C、子組件D;
- 三個子組件要顯示不同的內容,于是可以在三個子組件中各自寫不同的內容;
- 但是如果子組件中有重復的部分,那就會產生冗余的代碼,而且修改起來也不方便;
- 于是可是將這些重復的部分,放到他們的 父組件A 中,由 父組件 統一管理;
- 哪個子組件要用到這些內容, 父組件就把內容發給誰,也就是“內容分發”;
- 由父組件統一管理,還有一個好處就是,只需要修改父組件中的內容,子組件就會隨之改變;
- “內容分發”的過程,又仿佛與組件通信的過程類似;
- 比如:父組件要怎么“發內容”呢?子組件要怎么“收內容”呢?
- 于是“插槽(slot)”就登場了;
- 只需要在子組件中使用 slot 元素,就可以將內容顯示出來。
接下來,就主要介紹“單個插槽”、“具名插槽”、“作用域插槽”的用法。
一、單個插槽
首先請看:
<div id="app"> <child-component> <p>來自父組件的問候</p> // 這看似是在子組件中寫的內容,但其實這是屬于父組件的作用域</child-component> // 也就是說,其實這個 p元素 ,是父組件中的內容 </div> Vue.component('child-component', {template: `<div></div>` })var app = new Vue({el: '#app',data: {} })如果像上面這樣,直接在 <child-component></child-component>中寫東西,是不會被渲染的,因為子組件還沒接收你寫的東西。子組件里只有一個空的 div 元素,所以頁面只渲染一個空的 div ,如圖:
那么子組件要如何接收父組件傳來的內容呢?答案是,在子組件中使用 slot 元素就好了:
Vue.component('child-component', {template: `<div><slot></slot> // 在子組件中使用 slot 元素</div>` })看,現在頁面就渲染出了父組件中寫的 p 元素:
總結:
在子組件中使用 slot 做一個插槽,父組件中的內容就可以插到這個插槽里邊。
二、具名插槽
顧名思義,具名插槽,就是有名字的插槽。
如果父組件中有很多內容都要放到子組件中,如果子組件中只有一個 slot(插槽)的話,那所有內容都擠到一起,顯然是不合理的。所以我們需要多個 slot(插槽),并給每個 slot(插槽)起個名字,那么就能很方便的講指定內容放到指定 slot(插槽)中。
比如父組件中有一首詩:
<div id="app"><child-component><p>離離原上草,</p> // 注意,這里的作用域還是父組件的作用域<p>一歲一枯榮。</p><p>野火燒不盡,</p><p>春風吹又生。</p><address>白居易</address><h2>賦得古原草送別</h2></child-component> </div>Vue.component('child-component', {template: `<div><slot></slot> // 子組件中只有一個 slot(插槽),那么所有內容都將按順序被插到這個 slot 中</div>` })var app = new Vue({el: '#app',data: {} })渲染:
顯然這樣是不合適的,如果有更多的內容,那么更多的內容都將被插到這一個 slot 中。
于是我們在子組件中多寫幾個 slot,并給他們名字:
Vue.component('child-component', {template: `<div><slot name="header"></slot> // 有 name<slot></slot> // 沒有 name ?這個先放著,后面再說<slot name="footer"></slot> // 有 name</div>` })那么相應的,也要給父組件中的內容起個名字,不然怎么知道哪個插到哪里呢??但是要注意的是,給父組件中的內容起名字,要用到 slot,而不是 name:
<div id="app"><child-component><p>離離原上草,</p><p>一歲一枯榮。</p><p>野火燒不盡,</p><p>春風吹又生。</p> // 上面的四個 p 元素沒名字?<address slot="footer">白居易</address> // 用 slot 起名字<h2 slot="header">賦得古原草送別</h2> // 用 slot 起名字</child-component> </div>先看看頁面是怎么渲染的:
這里需要注意幾點:
- 頁面渲染的順序,是子組件中 slot 的順序;
- 子組件中有名字的 slot,顯示父組件中有對應名字的內容;沒有名字的 slot,顯示父組件中沒有名字的內容;
三、作用域插槽
上面說的單個插槽和具名插槽,都是父組件向子組件傳遞數據。那么,父組件要從子組件中獲取數據,怎么辦呢?同樣,使用 slot 就可以辦到。
<div id="app"><child-component><template slot="text1" slot-scope="data"> // 這里用的 template{{ data.text }}</template><p slot="text2" slot-scope="data"> // 這里用的 p{{ data.text }}</p></child-component> </div>Vue.component('child-component', {template: `<div><slot name="text1" text="我多想再見你,哪怕匆匆一眼就別離"></slot><slot name="text2" text="路燈下昏黃的剪影,越走越漫長的林徑"></slot></div>` })var app = new Vue({el: '#app',data: {} })以上代碼中,子組件中使用了兩個 slot 并且都有 name 屬性,對應了父組件中的 template 元素 和 p 元素。
為什么要用兩個不同的元素呢?原因是,在 Vue 2.5.0 版本之前,要想使用作用域插槽獲取子組件數據,必須使用 template 元素;而在 Vue 2.5.0 版本之后,就可以使用其他元素了。所以上面代碼中,使用了 p 元素做了一個測試,你也可以嘗試其他元素。
接著看上面代碼,子組件中的 text,就是子組件中的數據。看看父組件是怎么獲取的?它分別在 template 和 p 上寫了 slot-scope 屬性,scope 有“范圍”的意思,也就是 slot 的范圍,也就是“作用域插槽”了。同時我們還看到:
slot-scope="data"data 其實就是一個變量名,你也可以換成其他的名字,比如 prop,如果換成 prop,你就要這么寫:
<template slot="text1" slot-scope="prop"> {{ prop.text }} </template>四、訪問插槽
還記得上篇文章的子鏈嗎?父鏈 和 子鏈
如果有多個子鏈,我們訪問子鏈的時候,就要用到 this.$refs。
同樣的,如果有多個插槽,我們訪問插槽的時候,就要用到 this.$slots。
<div id="app"><child-component><p>離離原上草</p><p>一歲一枯榮</p><p>野火燒不盡</p><p>春風吹又生</p><address slot="footer">白居易</address><h2 slot="header">賦得古原草送別</h2></child-component> </div>Vue.component('child-component', {template: `<div><slot name="header"></slot><slot name="footer"></slot><slot></slot></div>`,mounted: function () {let header = this.$slots.header // 訪問名字為 header 的插槽let footer = this.$slots.footer // 訪問名字為 footer 的插槽let headerText = header[0].elm.innerText // header 中的元素的文本let footerText = footer[0].elm.innerText // footer 中的元素的文本console.log(headerText)console.log(footerText)} })var app = new Vue({el: '#app',data: {} })控制臺打印:
如果你覺得插槽不好理解的話,你就想象小時候玩的“小霸王”。是不是得插個卡到那個卡槽里,才能開始玩游戲?那個卡槽,就相當于子組件中的 slot,游戲卡就相當于父組件中的內容。你得把內容插到 slot 里,子組件才能正確被渲染。
總結
以上是生活随笔為你收集整理的vue slot scope使用_20、slot插槽的用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 尘封往事
- 下一篇: python工作目录_如何使用pytho