0.什么是插槽
插槽(slot)的出现主要是为了父组件向子组件中加入内容。类似一个占位符,我们常说的“一个萝卜一个坑”,slot就是那个坑,在子组件中给你挖好了坑,然后在通过父组件来填坑。
1.默认插槽
我们创建一个vue项目。App.vue作为父组件参考如下:
<template> <div id="app"> <div>我是父组件APP</div> <HelloWorld msg="Welcome to Your Vue.js App"/> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld } } </script>
子组件HelloWorld组件,一开始没有引入插槽,参考如下:
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String } } </script>
效果图如下:
我们在子组件中加入slot标签:
<template> <div class="hello"> <h1>{{ msg }}</h1> <!-- 引入插槽 --> <slot></slot> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String } } </script>
此时刷新页面发现没有效果,因为我们只是挖好了坑,还没有填充内容。我们在父组件中引入子组件时填充内容:
<template> <div id="app"> <div>我是父组件APP</div> <HelloWorld msg="Welcome to Your Vue.js App"> <h5>我是在父组件,填充子组件内容</h5> </HelloWorld> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld } } </script>
效果如下:
这就是基础用法。
2.具名插槽
什么是具名插槽,其实就是给slot起个名字,在父组件调用时,根据名字对应插入信息。
我们在子组件中定义两个具名插槽。
<template> <div class="hello"> <h1>{{ msg }}</h1> <!-- 引入插槽 --> <slot name="type1"></slot> <slot name="type2"></slot> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String } } </script>
然后在父组件中分别使用具名插槽:
<template> <div id="app"> <div>我是父组件APP</div> <HelloWorld msg="Welcome to Your Vue.js App"> <template slot="type1"> <p>type1</p> </template> <template slot="type2"> <p>type2</p> </template> </HelloWorld> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld } } </script>
效果如下:
上面也可以写成下面这种形式:
<template v-slot:type1>
<p>type1</p>
</template>
3.作用域插槽
作用域插槽就是在父组件调用子组件时,由父组件决定显示的具体内容。
我们修改子组件内容:
<template> <div class="hello"> <h1>{{ msg }}</h1> <slot :obj="info">{{info}}</slot> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String }, data() { return { info: "默认信息" } } } </script>
然后父组件直接使用插槽的话就会显示子组件的默认内容:
<template> <div id="app"> <div>我是父组件APP</div> <HelloWorld msg="Welcome to Your Vue.js App"> </HelloWorld> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld } } </script>
效果:
我们修改子组件:
<template> <div class="hello"> <h1>{{ msg }}</h1> <slot name='type1' :value1="info1">{{info1}}</slot> <br> <slot :value2="info2">{{info2}}</slot> </div> </template> <script> export default { name: 'HelloWorld', props: { msg: String }, data() { return { info1: "默认信息1", info2: "默认信息2" } } } </script>
第一个插槽我们起名了,叫type1,第二个插槽没有没名字,这样就站好了两个坑。
然后我们在父组件里直接填充数据:
<template> <div id="app"> <div>我是父组件APP</div> <HelloWorld msg="Welcome to Your Vue.js App"> <!-- 有名字的 --> <template v-slot:type1> 修改信息1 </template> <!-- 没有名字默认 --> <template> 修改信息2 </template> </HelloWorld> </div> </template> <script> import HelloWorld from './components/HelloWorld.vue' export default { name: 'App', components: { HelloWorld } } </script>
效果:
可以看到,填充了数据。
4.简单总结
作用域插槽实际开发用的可能多一些,一般都是初始加载时显示子组件一个默认页面,等待后台数据返回后再填充数据到子组件中。