詳解Vue中的插槽
阿新 • • 發佈:2020-12-29
> 作者: 小土豆
> 部落格園:[https://www.cnblogs.com/HouJiao/](https://www.cnblogs.com/HouJiao/)
> 掘金:[https://juejin.im/user/2436173500265335](https://juejin.im/user/2436173500265335)
## 什麼是插槽
在日常的專案開發中,當我們在編寫一個完整的元件時,不可避免的會引用一些`外部元件`或者`自定義元件`。
![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fb28fd810b6d46bfae327048b5353d96~tplv-k3u1fbpfcp-watermark.image)
有了這種`引用關係`之後,我們就可以把它們稱為`父元件`或者`子元件`,同時`父子元件`之間有很多的通訊方式,比如可以通過`props`向`子元件`傳遞資料,或者通過`$emit`、`$parent`呼叫`父元件`中的方法。
下面就是一個非常簡單的`父元件`引用`子元件`的例子。
```html
Badge 標記
評論
進度條
````
接著我們在`App`元件中引用`Child`元件。
```html
```
最後執行專案,`子元件`的內容成功被引用並展示在頁面上。
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/605e364310034df2969841331912e1e7~tplv-k3u1fbpfcp-watermark.image)
那假如我們現在有這樣一個需求:在引用`Child`元件的同時,希望在`Child`元件的`指定位置`插入一段內容:` `。
如果我們直接將內容寫入` `內部,是不會生效的。
```html
```
可以看到並未達到預期效果:
![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/955ca4fee17c47e89e38e022fba2833b~tplv-k3u1fbpfcp-watermark.image)
那為了解決類似這樣的問題,`Vue`就設計出來了`slot`這個東西。`slot`翻譯過來叫做`插槽`,也可稱其為`Vue`的內容分發機制,它的主要作用就是向`子元件`的`指定位置`插入一段內容,這個內容可以是`HTML`或者`其他的元件`。
## 預設插槽
在前面一節內容裡,我們提出了一個需求:在引用`Child`元件的同時,希望在`Child`元件的`指定位置`插入一段內容:` `。
那這個需求如何使用`插槽`來實現呢?我們來實踐一下。
首先我們需要在`子元件`中寫入` `,同時這個在``標籤內部可以有預設的內容,比如`我是這個slot裡面本來的內容 `
```html
Badge 標記
評論
進度條
我是這個slot裡面本來的內容
```
接著就是在`父元件`中傳入我們希望插入到`子元件`中的內容。
```html
```
此時在執行專案,就能看到` `定義一個`name`屬性。
```html
```
給`插槽`起了名稱以後,我們在`父元件`中就可以使用`v-slot:name`或者`#name`往指定的`插槽`填充內容。
> `#name` 是`v-slot:name`的簡寫形式
下面我們就來實踐一下`具名插槽`。
首先是在`子元件(Child.vue)`中定義`具名插槽`。
```html
Badge 標記
評論
進度條
```
接著在`父元件(App.vue)`中使用。
```html
```
執行專案就能看到對應的內容被插入到對應的插槽內:
![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3a13e6f4c87f4deeb653fccf7a764c1d~tplv-k3u1fbpfcp-watermark.image)
### 補充內容——預設插槽的`name`屬性
其實關於前面的`預設插槽`它也是有`name`屬性的,其值為`default`,所以在`父元件`中也可以這樣寫:
```html
```
### 補充內容——`` 元素上使用 `v-slot` 指令
在演示`具名插槽`的時候,我們的`v-slot`是寫在``元素上的,這個是比較推薦的寫法,因為``在處理的過程中不會渲染成真實的`DOM`節點。
```html
`上使用`v-bind`繫結對應的資料。
```html
{{heading}}
```
可以看到我們在``上使用`v-bind`綁定了`vue data`中定義的`heading`資料。
接著我們就可以在`父元件`中定義一個`變數`來接收`子元件`中傳遞的資料。
> 父元件中接收資料的`變數名`可以隨意起,這裡我起的變數名為`slotValue`
```html
```
執行專案後檢視頁面的結果:
![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/204853827fbd48238edd129a1e503052~tplv-k3u1fbpfcp-watermark.image)
可以看到`slotValue`是一個物件,儲存了一組資料,其`鍵`就是我們在`子元件`的``上使用`v-bind`繫結的屬性名`headingValue`,其`值`是`v-bind`繫結的`heading`值。
![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f7604c3ecb7d4c7aaae29b1b52ea3f71~tplv-k3u1fbpfcp-watermark.image)
### 作用域插槽的應用場景
前面我們瞭解了`作用域插槽`的用法,也得知其主要目的是為了能在`父元件`中訪問`子元件`的資料。那什麼時候`父元件`需要訪問`子元件`的資料呢。
我們來舉個簡單的栗子。
假設我們有下面這樣一個`Card`元件:
```html
```
執行專案檢視頁面:
![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5f12bb6d7dc24ec89f7797fe990bb73e~tplv-k3u1fbpfcp-watermark.image)
`Card`元件本身並不複雜,就是展示`title`和`list`裡面的資料。但凡是有相同需求的都可以通過複用`Card`元件來實現。
但是仔細去想,我們的`Card`元件其實並沒有那麼靈活:如果有些頁面需要`複用`該元件,但是希望在`title`處增加一個`圖示`;或者有些頁面需要在展示內容時候不顯示編號`1、2、3`。
那這樣的需求使用`插槽`就可以輕鬆實現。
```html
{{slotTitle.titleValue}}
```
頁面效果:
![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7ea92c8f4545403e91167ca9b6656e62~tplv-k3u1fbpfcp-watermark.image)
亦或者有些頁面需要在展示內容時候不顯示編號`1、2、3`:
```html
{{slotItem.itemValue.text}}
```
頁面效果:
![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dd592c8a73514ee8bf4d9fd998aceefd~tplv-k3u1fbpfcp-watermark.image)
> 這裡應該能想起來`element table`元件的實現方式,是不是也有點這樣的意思呢
到這裡或許有人會說這樣的需求不用插槽也能實現,直接在`Card`元件中增加一些邏輯即可。這樣的說法固然是可以實現功能,但是顯然不是一個好辦法。
因為元件的設計本身是希望拿來複用的,如果這個元件本身大部分實現是符合我們的需求的,只有一小部分不符合,我們首先應該想要的是去`擴充套件該元件`,而不是`修改元件`,這也是軟體設計的思想:`開放擴充套件,關閉修改`。所以`插槽`的出現正是對元件的一種擴充套件,讓我們可以更加靈活的複用元件。
## 廢棄的插槽語法
關於以上所描述的`插槽`語法,均是`vue 2.6.0`以後的語法。在這之前,插槽的語法為`slot(預設插槽或者具名插槽)`和`slot-scope(作用域插槽)`。
### 預設插槽
```html
```
頁面效果:
![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7484a961b81446b698149bd71570eef1~tplv-k3u1fbpfcp-watermark.image)
### 具名插槽
```html
```
頁面效果:
![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0e7cf4b8bfb047f9990086321653e9c2~tplv-k3u1fbpfcp-watermark.image)
### 作用域插槽
```html
{{heading}}
```
頁面效果:
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9b0ea0f9606b46c09c7221da7ffcb6b6~tplv-k3u1fbpfcp-watermark.image)
## 總結
到這裡本篇文章就結束了,內容非常簡單易懂,可以是茶餘飯後的一篇知識回顧。
最後我們在來做一個小小的總結:
![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/aceb582988664281ad14ff201a5de331~tplv-k3u1fbpfcp-watermark.image)
## 近期文章
[記一次真實的Webpack優化經歷](https://www.cnblogs.com/HouJiao/p/14171588.html)
[JavaScript的執行上下文,真沒你想的那麼難](https://www.cnblogs.com/HouJiao/p/14066663.html)
[骨架屏(page-skeleton-webpack-plugin)初探](https://www.cnblogs.com/HouJiao/p/13845693.html)
[Vue結合Django-Rest-Frameword實現登入認證(二)](https://www.cnblogs.com/HouJiao/p/13801675.html)
[Vue結合Django-Rest-Frameword實現登入認證(一)](https://www.cnblogs.com/HouJiao/p/13706920.html)
## 寫在最後
如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者
文章`公眾號`首發,關注 [`不知名寶藏程式媛`](https://mmbiz.qpic.cn/mmbiz_gif/I4j8PCMjMMhl5J9MoqaIsAAeJVfMqYibiaJWpspxGicRiczx0xib35DLPlXvOd6amGPoLxLfnbERpC5TIPDgFBwc8gQ/640?wx_fmt=gif&tp=webp&wxfrom=5&wx_lazy=1) 第一時間獲取最新的文章
筆芯
歡迎大家關注小土豆
歡迎大家關注小土豆
歡迎大家關注小土豆
歡迎大家關注小土豆
歡迎大家關注小土豆
`這段內容已經成功的顯示在頁面上。 ![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/985bbee3c6344d71bd36bcaf17b65e7e~tplv-k3u1fbpfcp-watermark.image) ## 具名插槽 `具名插槽`就是給我們的`插槽`起一個名字,即給`element-ui元件
這裡是element-ui的部分元件介紹
出品@小土豆
歡迎大家關注小土豆
歡迎關注小土豆
``` 處理之後的`DOM`節點: ```html歡迎關注小土豆
``` 當然我們也可以將`v-slot`應用在其他的`HTML`元素上,這樣最終插入到子元件中的內容就會有一層真實的`DOM`節點包裹。 ```html歡迎關注小土豆
``` 處理之後的`DOM`節點: ```html歡迎關注小土豆
``` ## 作用域插槽 關於`作用域插槽`的相關概念和示例看了很多,但相對於前面兩種型別的插槽來說,確實有些難以理解。如果需要用一句話去總結`作用域插槽`,那就是`在父元件中訪問子元件的資料`,或者從`資料流向`的角度來講就是`將子元件的資料傳遞到父元件`。 一個新概念或者一個新技術的出現總是有原因的,那`作用域插槽`的出現又是為了解決什麼樣的問題呢?一起來研究一下吧。 ### 作用域插槽的使用 我們先來看看如何利用`作用域插槽`實現`在父元件中訪問子元件的資料`。 首先我們需要在`子元件`的插槽`element-ui元件
slotValue = {{slotValue}}{{title}}
{{item.id}}.{{item.text}}
``` 其中`Card`元件中展示的`title`和`list`資料由`父元件`傳入。 接著在`App`元件中複用`Card`元件,並且傳入`title`和`list`資料。 ```html
{{title}}
歡迎關注小土豆
或者
歡迎關注小土豆
element-ui元件
這裡是element-ui的部分元件介紹
出品@小土豆