Vue CLI 系列之(十八)插槽

插槽

结构在哪【结构的代码在哪个组件】,样式就写在哪【样式就写在哪个组件中】

这里的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. 总结

  1. 作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信【这里传递的数据是html结构】的方式,适用于 父组件 ===> 子组件

  2. 分类:默认插槽、具名插槽、作用域插槽

  3. 使用方式:

    1. 默认插槽:

      父组件中:
              <Category>
                 <div>html结构1</div>
              </Category>
      子组件中:
              <template>
                  <div>
                     <!-- 定义插槽 -->
                     <slot>插槽默认内容...</slot>
                  </div>
              </template>
      
    2. 具名插槽:

      父组件中:
              <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>
      
    3. 作用域插槽:作用域插槽可以和具名插槽、默认插槽一起用

      1. 理解:数据在组件的自身【子组件】,但根据数据生成的结构需要组件的使用者【父组件】来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)

      2. 具体编码:

        父组件中:
        		<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>
        
posted @   刘二水  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示