21.Vue中的插槽slot
】父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
一个不带 name 的
会带有隐含的名字name=“default”
。
问题:插槽(slot)是什么?兄弟们也可以点这里去看这位兄弟的博客,写的比我详细!!!
- 【理解1】:插槽就是子组件中的提供给父组件使用的一个占位符,用
表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的
标签。简单理解就是子组件中留下个“坑”,父组件可以使用指定内容来补“坑”。
- 【理解2】:插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。插槽显不显示、怎样显示是由父组件来控制的;而插槽在哪里显示就由子组件来进行控制。
问题:三种插槽(slot):
1、默认插槽
<slot>slot>
2、具名插槽
<slot name="名称">slot>
3、作用域插槽
<slot :自定义 name = data 中的属性对象>slot>
<template>
<div class="about">
<h1>这里是子组件Categoryh1>
<slot>slot>
div>
template>
--这里东西放入子组件的插槽中--
。<template>
<div class="container">
<h1>这里是父组件h1>
<category title="美食">
<img src="http://rwt9uxba6.hd-bkt.clouddn.com/9999.png" />
category>
div>
template>
那么,就会把要放入插槽中的东西复制几份【比如:两个默认插槽就复制两份】
<template>
<div class="about">
<h1>这里是子组件Categoryh1>
<slot>slot>
<slot>slot>
div>
template>
我们看一下:不是动态的数据,即静态的数据,怎么从父组件传递给子组件的【依旧可以使用props
】
子组件:category.vue
<template>
<div class="category">
<h3>{{ title }}分类h3>
<slot>我是一些默认值,当使用者没有传递具体结构时,我会出现slot>
div>
template>
<script>
export default {
name: 'Category',
// 父组件给子组件传递数据:props
props: ['title'],
};
script>
父组件:app.vue
//静态的数据 title不是变量,是个常量
<category title="美食">
<img src="http://rwt9uxba6.hd-bkt.clouddn.com/9999.png" />
category>
//动态的数据 data是变量,不是常量
<category :data="data">
<img src="http://rwt9uxba6.hd-bkt.clouddn.com/9999.png" />
category>
上面案例完整代码:
main.js
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入vue-resource插件
// import vueResource from 'vue-resource';
//关闭Vue的生产提示
Vue.config.productionTip = false
//使用插件
// Vue.use(vueResource)
//创建vm
new Vue({
el:'#app',
render: h => h(App),
// 生命周期钩子beforeCreate中模板未解析,且this是vm
beforeCreate() {
// this:指的是vm
Vue.prototype.$bus = this //安装全局事件总线$bus
}
})
App.vue
<template>
<div class="container">
<category title="美食">
<img src="http://rwt9uxba6.hd-bkt.clouddn.com/9999.png" />
category>
<category title="游戏">
<ul>
<li v-for="(g, index) in games" :key="index">{{ g }}li>
ul>
category>
<category title="电影">
<video
src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
>video>
category>
div>
template>
<script>
import Category from './components/Category';
export default {
name: 'App',
components: { Category },
data() {
return {
foods: ['火锅', '烧烤', '小龙虾', '牛排'],
games: ['红色警戒', '穿越火线', '劲舞团', '超级玛丽'],
films: [
'《教父》',
'《拆弹专家》',
'《你好,李焕英》',
'《尚硅谷》',
],
};
},
};
script>
<style scoped>
.container {
/* 弹性布局 */
display: flex;
/* 弹性项目平均分布在该行上,两边留有一半的间隔空间。 */
justify-content: space-around;
}
style>
Category.vue
<template>
<div class="category">
<h3>{{ title }}分类h3>
<slot>我是一些默认值,当使用者没有传递具体结构时,我会出现slot>
div>
template>
<script>
export default {
name: 'Category',
// 父组件给子组件传递数据:props
props: ['title'],
};
script>
<style scoped>
.category {
background-color: aquamarine;
width: 200px;
height: 300px;
}
h3{
background-color: orange;
/* 为文本或img标签等一些内联对象(或与之类似的元素)的居中。 */
text-align: center;
}
img {
/* 占父元素的比例 */
width: 100%;
}
video {
/* 占父元素的比例 */
width: 100%;
}
style>
其实就是在子组件中定义插槽时,给对应的插槽分别起个名字,方便后边插入父组件将根据name来填充对应的内容。
<slot name="one">slot> <slot name="two">slot>
【父组件:App;子组件:Category】
在子组件:Category中定义两个具名插槽。
<template>
<div class="about">
<h1>T这里是子组件Categoryh1>
<slot name="one">slot>
<slot name="two">slot>
div>
template>
【这里东西放入子组件的插槽中,有插槽名的一一对应放入】
。<category title="美食">
<template slot="one">
<p>one插槽p>
template>
<template slot="two">
two插槽
template>
category>
包裹起来,好处是:
不渲染真实DOM,结构少了一层,并且还可以用这种写法【v-slot:插槽名】:
。具名插槽案例效果展示:
具名插槽案例的完整代码:
:video标签里面的controls属性是控制视频播放的按钮 。父组件App.vue
<template>
<div class="container">
<category title="美食">
<img slot="center" src="http://rwt9uxba6.hd-bkt.clouddn.com/9999.png" />
<a slot="footer" href="http://www.atguigu.com">更多美食a>
category>
<category title="游戏">
<ul slot="center">
<li v-for="(g, index) in games" :key="index">{{ g }}li>
ul>
<div class="footer" slot="footer">
<a href="http://www.atguigu.com">单机游戏a>
<a href="http://www.atguigu.com">网络游戏a>
div>
category>
<category title="电影">
<video
controls
slot="center"
src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
>
video>
<template slot="footer">
<div class="footer">
<a href="http://www.atguigu.com">经典a>
<a href="http://www.atguigu.com">热门a>
<a href="http://www.atguigu.com">推荐a>
div>
<h4>欢迎前来观影h4>
template>
category>
div>
template>
<script>
import Category from './components/Category';
export default {
name: 'App',
components: { Category },
data() {
return {
foods: ['火锅', '烧烤', '小龙虾', '牛排'],
games: ['红色警戒', '穿越火线', '劲舞团', '超级玛丽'],
films: [
'《教父》',
'《拆弹专家》',
'《你好,李焕英》',
'《尚硅谷》',
],
};
},
};
script>
<style scoped>
.container ,.footer{
/* 弹性布局 */
display: flex;
/* 弹性项目平均分布在该行上,两边留有一半的间隔空间。 */
justify-content: space-around;
}
h4{
/* 为文本或img标签等一些内联对象(或与之类似的元素)的居中。 */
text-align: center;
}
style>
子组件Category.vue
<template>
<div class="category">
<h3>{{ title }}分类h3>
<slot name="center">我是一些默认值,当使用者没有传递具体结构时,我会出现1slot>
<slot name="footer">我是一些默认值,当使用者没有传递具体结构时,我会出现2slot>
div>
template>
<script>
export default {
name: 'Category',
// 父组件给子组件传递数据:props
props: ['title'],
};
script>
<style scoped>
.category {
background-color: aquamarine;
width: 200px;
height: 300px;
}
h3{
background-color: orange;
/* 为文本或img标签等一些内联对象(或与之类似的元素)的居中。 */
text-align: center;
}
img {
/* 占父元素的比例 */
width: 100%;
}
video {
/* 占父元素的比例 */
width: 100%;
}
style>
作用域插槽的主要作用是在父组件中书写插槽内容时可以获取到 { 插槽作用域的值 }【指的是:子组件的data】。
描述:作用域插槽其实就是带数据的插槽,即带参数的插槽,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容。
作用域插槽就是实现在子组件自行决定自己要显示什么内容。 并且,能够让要放入插槽的内容能够访问子组件中才有的数据。【一种子给父通信的方法】
可以让要放入模板中的数据一样,但是HTML结构不一样:如下面的案例中的三个小卡片放入的data一样,但是样式不一样。【一个无序、一个有序且字体有颜色、还有一个应用了h4字体样式】
要放入插槽的内容指的是:
父组件中
里面的包裹的东西 <category title="美食"> <template v-slot="childrenDate"> <p>one插槽p> template> <div scope="childrenDate"> <p>one插槽p> div> category>
- 此处的
v-slot指令
可以替换成scope
和slot-scope
- 【注意 】
v-slot
只能添加在上
- 【模板】子组件Category要传给父组件的data:
<slot :自定义的name=子组件data中的属性或对象>slot>
元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有
v-slot
的 中的内容都会被视为默认插槽的内容。
【例子:Category.vue】子组件Category要传给父组件的data:【childrenDate=games - - ->整个都传递过去- - ->childrenDate= [‘红色警戒’, ‘穿越火线’, ‘劲舞团’, ‘超级玛丽’]】
<slot :childrenDate=games>slot>
data() {
return {
games: ['红色警戒', '穿越火线', '劲舞团', '超级玛丽'],
};
},
或者
,使用的话,xxx.childrenDate[index]<category title="游戏">
<template scope="haha">
<ul>
<li v-for="(g,index) in haha.childrenDate" :key="index">{{g}}li>
ul>
template>
category>
<slot :dataOfCategory="games" :Msg="nihao">slot>
data() { return { games: ['红色警戒', '穿越火线', '劲舞团', '超级玛丽'], nihao:'我是伍六七,我喜欢梅小姐!', }; },
haha
,我们看一下它的到底是个什么玩意???<category title="游戏"> <template scope="haha"> <ul> <li v-for="(g, index) in haha.dataOfCategory" :key="index"> {{ g }} li> ul> <button @click="CategoryDate(haha)"> <h2>点击查看子组件传过来的数据h2> button> template> category>
methods: { CategoryDate(haha) { console.log(haha); }, },
结果展示:
有点看不清,那就月下观鸟:
具名插槽案例效果展示:
完整代码:
App.vue组件
<template>
<div class="container">
<category title="游戏">
<template scope="haha">
<ul>
<li v-for="(g, index) in haha.dataOfCategory" :key="index">
{{ g }}
li>
ul>
<button @click="CategoryDate(haha)">
<h2>点击查看子组件传过来的数据h2>
button>
template>
category>
<category title="游戏">
<template slot-scope="{ dataOfCategory }">
<ol>
<li
style="color: orange"
v-for="(g, index) in dataOfCategory"
:key="index"
>
{{ g }}
li>
ol>
template>
category>
<category title="游戏">
<template v-slot="hello">
<h4 v-for="(g, index) in hello.dataOfCategory" :key="index">
{{ g }}
h4>
template>
category>
div>
template>
<script>
import Category from './components/Category';
export default {
name: 'App',
components: { Category },
methods: {
CategoryDate(haha) {
console.log(haha);
},
},
};
script>
<style scoped>
.container,
.footer {
/* 弹性布局 */
display: flex;
/* 弹性项目平均分布在该行上,两边留有一半的间隔空间。 */
justify-content: space-around;
}
h4 {
/* 为文本或img标签等一些内联对象(或与之类似的元素)的居中。 */
text-align: center;
}
button{
/* 为文本或img标签等一些内联对象(或与之类似的元素)的居中。 */
text-align: center;
background-color: blueviolet;
}
style>
Category.vue组件
<template>
<div class="category">
<h3>{{ title }}分类h3>
<slot :dataOfCategory="games" :Msg="nihao">我是一些默认值,当使用者没有传递具体结构时,我会出现1slot>
div>
template>
<script>
export default {
name: 'Category',
// 父组件给子组件传递数据:props
props: ['title'],
data() {
return {
games: ['红色警戒', '穿越火线', '劲舞团', '超级玛丽'],
nihao:'我是伍六七,我喜欢梅小姐!',
};
},
};
script>
<style scoped>
.category {
background-color: aquamarine;
width: 200px;
height: 300px;
}
h3{
background-color: orange;
/* 为文本或img标签等一些内联对象(或与之类似的元素)的居中。 */
text-align: center;
}
img {
/* 占父元素的比例 */
width: 100%;
}
video {
/* 占父元素的比例 */
width: 100%;
}
style>
作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件 。
分类:默认插槽、具名插槽、作用域插槽
使用方式:
默认插槽:
父组件中:
html结构1
子组件中:
插槽默认内容...
具名插槽:
父组件中:
html结构1
html结构2
子组件中:
插槽默认内容...
插槽默认内容...
作用域插槽:
理解:作用域插槽其实就是带数据的插槽,即带参数的插槽,简单的来说就是子组件提供给父组件的参数,该参数仅限于插槽中使用,父组件可根据子组件传过来的插槽数据来进行不同的方式展现和填充插槽内容。
具体编码:【见上面的案例的代码】