插槽
结构在哪【结构的代码在哪个组件】,样式就写在哪【样式就写在哪个组件中】
这里的App组件是Category组件的父组件
<!-- Category组件 -->
<h3>{{title}}分类</h3>
<!-- 定义一个插槽,相当于提前挖了个坑 -->
<!-- slot标签的作用相当于占位符,用于告诉Vue组件标签的标签体内容应该放的位置,slot标签在哪,标签体就放在哪 -->
<slot></slot>
<!-- App组件 -->
<Category title="食物">
<!-- 组件标签的标签体内容:用于传递动态结构-->
<!-- 组件的标签体内容就相当于往组件的坑里填土 -->
<img src="https://img1.baidu.com/it/u=3009731526,373851691&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500" >
</Category>
<Category title="游戏">
<ul>
<li v-for="(game,index) in games" :key="index">{{game}}</li>
</ul>
</Category>
注:Category组件的标签体内容是在App组件中解析完成后,传入到Category组件中的,所以标签体内容中的样式完全可以写在App组件中
Category组件的标签体内容中的样式写在App组件中和Category组件中有什么不同?
App组件中:标签体内容在App组件中解析完成后带着样式传到了Category组件中
Category组件中:App组件直接将标签体内容传到了Category组件中,然后应用的样式
插槽分为默认插槽、具名插槽、作用域插槽
1. 默认插槽
<!-- Category组件 -->
<h3>{{title}}分类</h3>
<!-- 定义插槽时可以设置默认结构 -->
<slot>我是默认结构,如果没往插槽中放东西,我就会显示,传了结构就不会显示</slot>
2. 具名插槽
具名插槽:具有名字的插槽
应用场景:一个组件中定义多个不同的插槽时
<!-- Category组件 -->
<h3>{{title}}分类</h3>
<!-- 组件中有多个坑【插槽】就要给每个坑【插槽】起个名 -->
<slot name="center"><h1>我是默认内容,如果没传结构,我就会显示,传了结构就不会显示</h1></slot>
<slot name="footer"><h1>我是默认内容,如果没传结构,我就会显示,传了结构就不会显示2</h1></slot>
<!-- App组件 -->
<Category title="食物">
<!-- slot属性:填坑的时候告诉Vue要给哪个坑【插槽】填东西,Vue会将slot属性所在的元素放到坑里 -->
<img slot="center" src="https://img1.baidu.com/it/u=3009731526,373851691&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500" >
<a slot="footer" href="http://www.baidu.com">点击跳转</a>
</Category>
<Category title="游戏">
<ul slot="center" >
<li v-for="(game,index) in games" :key="index">{{game}}</li>
</ul>
<!-- 往同一个坑里填多个东西,只会追加,不会覆盖 -->
<!-- <a slot="footer" href="http://www.baidu.com">点击跳转</a> -->
<!-- <a slot="footer" href="http://www.baidu.com">点击跳转2</a> -->
<!-- 往同一个坑里填多个东西时,如果每个东西分开写,slot属性要写多次 -->
<!-- 如果用div包裹,在最终的结构中会多出一层div结构,使用template则不会 -->
<!-- template:能够包裹元素,自身最终又不生成真实的DOM元素 -->
<!-- <template slot="footer"> -->
<!-- <a href="http://www.baidu.com">点击跳转</a> -->
<!-- <a href="http://www.baidu.com">点击跳转2</a> -->
<!-- </template> -->
<!-- 如果使用template,slot标签会有一种新的写法,v-slot:插槽名, Vue 2.6+ 才支持 -->
<template v-slot:footer>
<a href="http://www.baidu.com">点击跳转</a>
<a href="http://www.baidu.com">点击跳转2</a>
</template>
</Category>
3. 作用域插槽
js中的作用域
<!-- Category组件 -->
<h3>{{title}}分类</h3>
<!-- 通过slot标签传递的数据传给了该插槽的使用者 -->
<slot :games="games"><h1>我是默认内容,如果没传结构,我就会显示,传了结构就不会显示</h1></slot>
data(){
return {
games: ['红色警戒','cf','cs','超级玛丽'],
}
}
<!-- App组件 -->
<Category title="游戏">
<!-- 要想收到Category组件中插槽传过来的数据,必须使用template标签 -->
<!-- scope属性的属性值任意,会接收所有来自插槽的数据封装为一个对象 -->
<template scope="data">
<ul>
<li v-for="(game,index) in data.games" :key="index">{{game}}</li>
</ul>
</template>
</Category>
<Category title="游戏">
<!-- 此处的scope还可以写成slot-scope,作用相同,只不过这个是新的API写法 -->
<template slot-scope="data">
<ol>
<li v-for="(game,index) in data.games" :key="index">{{game}}</li>
</ol>
</template>
</Category>
<Category title="游戏">
<!-- 此处支持ES6中的解构赋值 -->
<template slot-scope="{games}">
<h4 v-for="(game,index) in games" :key="index">{{game}}</h4>
</template>
</Category>
App组件在使用Category组件的同时,数据也是在App组件中的
Category组件的使用者使用Category组件的同时,数据也在Category组件的使用者中
数据是相同的,但根据数据生成的结构是由使用者决定的
数据在Category组件中,但根据数据生成的结构要由Category组件的使用者App组件决定
使用子组件中的数据生成不同的结构
解构赋值
数据是在子组件【定义插槽的组件】中的,父组件【插槽的使用者】可以拿到子组件中的数据,使用数据生成不同的结构。【数据由子组件决定,结构由父组件决定】
4. 总结
-
作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信【这里传递的数据是html结构】的方式,适用于 父组件 ===> 子组件 。
-
分类:默认插槽、具名插槽、作用域插槽
-
使用方式:
-
默认插槽:
父组件中: <Category> <div>html结构1</div> </Category> 子组件中: <template> <div> <!-- 定义插槽 --> <slot>插槽默认内容...</slot> </div> </template>
-
具名插槽:
父组件中: <Category> <template slot="center"> <div>html结构1</div> </template> <template v-slot:footer> <div>html结构2</div> </template> </Category> 子组件中: <template> <div> <!-- 定义插槽 --> <slot name="center">插槽默认内容...</slot> <slot name="footer">插槽默认内容...</slot> </div> </template>
-
作用域插槽:作用域插槽可以和具名插槽、默认插槽一起用
-
理解:数据在组件的自身【子组件】,但根据数据生成的结构需要组件的使用者【父组件】来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)
-
具体编码:
父组件中: <Category> <template scope="scopeData"> <!-- 生成的是ul列表 --> <ul> <li v-for="g in scopeData.games" :key="g">{{g}}</li> </ul> </template> </Category> <Category> <template slot-scope="scopeData"> <!-- 生成的是h4标题 --> <h4 v-for="g in scopeData.games" :key="g">{{g}}</h4> </template> </Category> 子组件中: <template> <div> <slot :games="games"></slot> </div> </template> <script> export default { name:'Category', props:['title'], //数据在子组件自身 data() { return { games:['红色警戒','穿越火线','劲舞团','超级玛丽'] } }, } </script>
-
-