插槽及组件的获取

插槽概述

​ Vue插槽是Vue中常见的一种组件间的相互通信方式,作用是让父组件可以向子组件指定位置插入html结构,适用于父组件===>子组件,在要接收数据的组件页面通过<slot>标签来表示,简单来说,就是通过此标签来起到占位的作用,而要插入的内容也会对应到标签所在的位置。

​ 简单来讲就是组件预留的一个入口,帮助你将内容放到组件中

分类

  • 匿名插槽
  • 具名插槽
  • 作用域插槽

匿名插槽

没有具体名字,默认名为default

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<div id="app">
<first>world</first>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.config.productionTip = false

let first = {
// 匿名插槽的定义
template:`
<div>
hello
<slot></slot>
</div>
`
}
const vm = new Vue({
el: '#app',
data: {
},
components:{
first
}
})
</script>

具名插槽

通过name属性,指定插槽的名字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<div id="app">
<!-- 具名插槽的使用一般使用template标签来包裹传入的内容 -->
<first>
<template slot="footer">
传入的数据
</template>
</first>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.config.productionTip = false

let first = {
// 具名插槽的定义
template:`
<div>
具名插槽<br>
header插槽:<slot name="header"></slot><br>
footer插槽:<slot name="footer"></slot>
</div>
`
}
const vm = new Vue({
el: '#app',
data: {
},
components:{
first
}
})
</script>

v-slot指令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<div id="app">
<!-- 具名插槽的使用一般使用template标签来包裹传入的内容 -->
<first>
<template v-slot:default>
vue的版本需要2.6及以上
</template>
<!-- 通过v-slot属性来指定插入的插槽 -->
<template v-slot:footer>
传入的数据
</template>
<template #footer>
传入的数据,简写了v-slot为#
</template>
</first>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.config.productionTip = false

let first = {
// 具名插槽的定义
template:`
<div>
匿名插槽<br>
<slot></slot><br>
具名插槽<br>
<slot name="footer"></slot>
</div>
`
}
const vm = new Vue({
el: '#app',
data: {
},
components:{
first
}
})
</script>

作用域插槽

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<div id="app">
<first>
<!-- 可简写为#header="scope" -->
<template v-slot:header="scope" >
<div>
你好世界{{scope}}<br>
<button @click="scope.user.username='tom'">改为tom</button>
<button @click="scope.sayHelloFn('父组件调用了')">调用sayhello</button>
</div>
</template>
</first>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.config.productionTip = false
let first = {
template:`
<div>
作用域插槽:{{msg}}<br>
<slot name="header" :msg="msg" :user="user" :sayHelloFn="sayHello" ></slot><br>
</div>
`,
data() {
return {
msg:'插槽里的数据',
user:{
username:'jerry',
age:22
}
}
},
methods: {
sayHello(arg){
console.log(arg);
}
},
}
const vm = new Vue({
el: '#app',
data: {
msg: '袁同学!',
},
components:{
first
}
})
</script>

image-20230330174020762

总结

  • 使用slot来定义插槽
  • 匿名插槽又称默认插槽,内容默认传递给对应的具名插槽
  • slot标签通过name属性来指定插槽名
  • 需要插入的内容建议用template标签包裹
  • 作用域插槽是扩大了对应的组件作用域,通过对应的插槽数据中的属性来传递数据
  • 父组件使用对应的slot-scope属性来接收对应的传递的属性对象(2.6之前的写法)
  • v-slot(2.6及以上版本才支持)(v-slot:name)可简写为(#name)
  • v-slot和slot的写法不要混用,容易造成兼容问题

组件获取

  • $root获取根组件
  • $children获取子组件
  • $parent获取父组件
  • $refs获取ref标记的组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<div id="app">
<last></last>
<button @click="logMsg">btn</button>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.config.productionTip = false
let first = {
template: `<div>
第一个组件
<button @click="handler">第一个组件button</button>
<slot name="firstSlot" :hdfn="handler"> </slot>
<slot name="firstSlot2"> </slot>
</div>
`,
methods: {
handler() {
console.log(this.$scopedSlots)
}
},
}
let last = {
template: `<div>第二个组件<br>
<button @click="hdl">last-btn</button>
<first>
<template #firstSlot="scope">放入插件的内容
{{scope.hdfn()}}
<button @click="hdl(scope)">hdl(scope)</button>
</template>
</first>
</div>`,
data() {
return {
msg: '父组件'
}
},
methods: {
hdl(arg) {
console.log(arg)
console.log(this.$children)
}
},
components: {
first
}
}
const vm = new Vue({
el: '#app',
data: {
names: ' !',
},
components: {
last
},
methods: {
logMsg() {
console.log(this.$slot)
}
}
})
</script>

插槽的获取

  • $slots 获取调用的插槽(不包括作用域插槽)

  • $scopedSlots 获取调用的作用域插槽