[TOC]
# **slot插槽**
slot定義在子組件中,相當于留出一個位置。當父組件引用這個子組件時,可以向這個位置插入內容。
## **1. 匿名插槽(預設插**槽)
在子組件中,由slot標簽定義,具有以下特點:
**1. 當父組件中,沒有特殊指定位置的內容默認放到匿名插槽當中
2. 匿名插槽可以有多個,都會渲染父組件傳來的默認內容
3. 當父組件沒有傳入默認內容時,顯示自己的內容**
### 1.1 顯示父組件的內容
**1. helloworld.vue**
~~~
<template>
<div>
<slot>這是子組件的一個預設插槽</slot>
</div>
</template>
<script>
export default {
name: "HelloWorld",
};
</script>
~~~
**2. home.vue** 父組件
~~~
<template>
<div class="home">
<hello-world> 這是父組件傳來的內容 </hello-world>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";
export default {
name: "Home",
components: {
HelloWorld
}
};
</script>
~~~
但是,父組件中建議用`<template>`標簽傳入內容
~~~
<template>
<div class="home">
<hello-world> <template>這是父組件傳來的內容</template> </hello-world>
</div>
</template>
~~~

### 1.2 多個匿名插槽
**1. helloworld.vue**
~~~
<template>
<div>
<slot>這是子組件的一個預設插槽</slot>
<slot>這是子組件的一個預設插槽</slot>
<slot>這是子組件的一個預設插槽</slot>
</div>
</template>
<script>
export default {
name: "HelloWorld",
};
</script>
~~~
**2. home.vue** 父組件
~~~
<template>
<div class="home">
<hello-world> <template>這是父組件傳來的內容 <br></template> </hello-world>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";
export default {
name: "Home",
components: {
HelloWorld
}
};
</script>
~~~
如下圖,多個匿名插槽都被父組件傳來的一個內容所替代了

html渲染如下:

### 1.3 父組件不傳內容時,顯示自己
**1. helloworld.vue**同1.2
**2. home.vue**不傳內容
~~~
<template>
<div class="home">
<hello-world> </hello-world>
</div>
</template>
~~~

## **2. 具名插槽**
相對于匿名插槽,具名插槽有一個名稱,用來標識自己,具有以下特點:
1. 可以出現多次,和不同地方
2. 父組件只要匹配了name,就可以渲染
### **2.1 vue 2.6以前的寫法**
**1.hellowold.vue**
子組件在slot標簽中用name屬性聲明插槽名稱
~~~
<template>
<div>
<slot>這是子組件的一個預設插槽</slot>
<slot name="header"> 這是具名插槽 </slot>
</div>
</template>
~~~
**2. home.vue**
**在父組件中,使用slot指令指定插槽,slot="插槽名"**
父組件中,在teamplate標簽中用`slot="header"`(vue 2.6以前的寫法)屬性,指定插槽
~~~
<template>
<div class="home">
<hello-world>
<template>這是父組件傳來的內容 <br></template>
<template slot="header">這是父組件傳給子組件具名插槽 <br></template>
</hello-world>
</div>
</template>
~~~

home.vue中去掉slot="header",就會都插入匿名插槽中!
### **2.2 vue 2.6后的寫法**
**在父組件中,使用v-slot 指定插槽**
`v-slot="插槽名"` 或者簡寫 `#插槽名`
**1. hellowold.vue**
~~~
<template>
<div>
<slot>這是子組件的一個預設插槽</slot>
<slot name="header"> 這是具名插槽 </slot>
</div>
</template>
~~~
**2. home.vue**
~~~
<template>
<div class="home">
<hello-world>
<template>這是父組件傳來的內容 <br></template>
<!-- vue 2.6以前 -->
<!--<template slot="header">這是父組件傳給子組件具名插槽 <br></template>-->
<!-- vue 2.6以后寫法 -->
<template v-slot:header>這是父組件傳給子組件具名插槽1 <br></template>
</hello-world>
</div>
</template>
~~~

**v-slot指令和v-on等指令一樣,也有簡寫形式**
`v-slot:header = #header`
## **3. 作用域插槽**
將slot插槽的所有屬性,封裝成一個對象(x),父組件在使用子組件時,可以調用這些屬性數據-父組件向子組件中的插槽傳值(可是是數據或者函數)
### **3.1 使用插槽的屬性值**
#### **3.1.1 vue 2.6以前的寫法**
父組件通過slot-scope或者scope屬性(**在vue 2.5.0+ 中slot-scope替代了 scope**)
**1.helloworld.vue**
~~~
<template>
<div>
<slot>這是子組件的一個預設插槽</slot>
<slot name="header" data="hello slot" id="110"> 這是具名插槽 </slot>
</div>
</template>
~~~
**2. home.vue**
* slot="header" : 指定name=header的插槽
* slot-scope="slotValue" :對于header插槽,給其屬性數據起一個”別名“,這個slotValue是一個對象,包含了slot的所有屬性數據:`{ "data": "hello slot", "id": "110" }`
~~~
<template>
<div class="home">
<hello-world>
<template>這是父組件傳來的內容 <br></template>
<template slot="header" slot-scope="slotValue">
{{slotValue}} <br>
id:{{slotValue.id}} <br>
</template>
</hello-world>
</div>
</template>
~~~

如圖,slotValue包含了header插槽的所有屬性數據
#### **3.1.2 vue 2.6以后的寫法**
v-slot指令,相當于slot和slot-scope的功能集合,slot定位和數據傳遞
v-slot:插槽名="屬性別名" 或者 #插槽名="屬性別名"
**2. home.vue**
~~~
<template>
<div class="home">
<hello-world>
<template>這是父組件傳來的內容 <br></template>
<template v-slot:header="slotValue">
v-slot: {{slotValue}} <br>
id:{{slotValue.id}} <br>
</template>
</hello-world>
</div>
</template>
~~~

```
<list :data="listData" class="img-list">
<template scope="scope">
<div class="info">
<p>數據:{{scope}}</p>
<p>索引:{{scope.$index}}</p>
<p>姓名:{{scope.row.name}}</p>
<p>性別:{{scope.row.sex}}</p>
</div>
</template>
</list>
```
? ? ? ? ? ?
## **4. 案例**
### **4.1 傳值**

? ?**1. slot-test.vue 子組件**
~~~
<template>
<div class="color-list">
<h2>{{ title }}</h2>
<div class="list">
<div class="list-item" v-for="(item, index) in items" :key="index">
<slot v-bind="item"></slot>
</div>
</div>
</div>
</template>
<script>
export default {
name: "slot-test",
props: {
title: {
type: String,
default: 'slot測試'
},
items: {
type: Array
}
}
}
</script>
<style scoped>
</style>
~~~
其中:以下產生多個匿名slot
```
<div class="list-item" v-for="(item, index) in items" :key="index">
<slot v-bind="item"></slot>
</div>
```
三個匿名slot

**2. about.vue**
~~~
<template>
<div id="app">
<slot-test :items="colors" title="slot測試">
<template v-slot:default="color">
<div :style="{background: color.hex}">{{ color.name }}</div>
</template>
</slot-test>
</div>
</template>
<script>
import SlotTest from '@/components/slot-test'
export default {
name: 'app',
components: {
SlotTest
},
data () {
return {
colors: [
{ name: 'Yellow', hex: '#F4D03F', },
{ name: 'Green', hex: '#229954' },
{ name: 'Purple', hex: '#9B59B6' }
]
}
}
}
</script>
~~~
其中,
```
<template v-slot:default="color">
<div :style="{background: color.hex}">{{ color.name }}</div>
</template>
```
v-slot:default="color" :default指定是匿名插槽,也可以不指定。父組件傳的值都會再子組件的多個匿名插槽中顯示,所有有以下三個顏色的div

### **4.2 讀取值**
子組件通過`v-bind="{ item, form, handleFieldChange, setFieldValue }"`綁定屬性數據和函數
~~~
<slot name="field" v-if="item.slots.ext" v-bind="{ item, form, handleFieldChange, setFieldValue }">
<span>customEditor</span>
</slot>
setFieldValue(name, value) {
this.$set(this.form, name, value);
this.handleFieldChange(name, value);
},
~~~
父組件不但可以使用子組件的值,還可以使用子組件的函數`setFieldValue`
~~~
<template v-slot:field="{ form, item, setFieldValue }">
<div>
<el-input :value="form.file" @input="setFieldValue(item.field.name, $event)">
<el-button slot="append" @click="uploadBtn">選擇軟件包</el-button>
</el-input>
<input @change="changeFile(form, item.field.name,setFieldValue)" type="file" style="display: none;" class="fileInput"/>
</div>
</template>
~~~
## 5. 總結
vue2.6以后使用v-slot代替slot和slot-scope(scope),例如:
~~~
v-slot:header="slotValue"
~~~
等價于
~~~
slot="header" slot-scope="slotValue">
~~~
- vue
- 為什么要學vue
- 數據雙向綁定
- vue指令
- v-bind創建HTML節點屬性
- v-on綁定事件
- v-cloak
- v-text
- v-for和key屬性
- v-if和v-show
- 案例1
- 自定義指令
- vue樣式
- vue生命周期
- vue過濾器
- 自定義鍵盤修飾符
- 跨域請求
- vue組件
- 組件基礎
- 引入vue文件組件
- 引入render函數作為組件
- 兄弟間組件通信
- 組件函數數據傳遞練習
- 路由
- 數據監聽
- webpack
- vue校驗
- vue筆記
- form表單中input前部分默認輸入,切不可修改
- mixins
- 部署到nginx
- scope
- render
- 下載文件
- vue動態組件
- axios
- Promise
- vue進階
- node-vue-webpack搭建
- vue事件
- 插槽
- vuex
- vuex基礎
- vuex命名空間
- HTML遞歸?
- this.$nextTick異步更新dom
- elementui
- table
- 修改element ui樣式
- form
- 優質博客
- vuex state數據與form元素綁定
- es6
- Promise