插槽及组件的获取
插槽概述
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"> <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"> <first> <template v-slot:default> vue的版本需要2.6及以上 </template> <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> <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>
|

总结
- 使用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 获取调用的作用域插槽