(三十八)Vue之插槽Slots

文章目录

上一篇:(三十七)vue 项目中常用的2个Ajax库

插槽介绍

在之前的文章中,我们已经了解到组件能够接收任意类型的值作为 props,在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段,由此就有了插槽。

作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件

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

插槽分类

默认插槽

在外部没有提供任何内容的情况下,可以为插槽指定默认内容。

使用方式:当父组件没有传递内容的时候就会显示子组件slot的内容,有传递内容时则显示<html结构>的内容。

复制代码
       父组件中:
               <MyComponent >
                  <html结构>
               </MyComponent >
       子组件中:
               <template>
                      <!-- 定义插槽 -->
                      <slot>插槽默认内容...</slot>
               </template>

demo:做一个简单的分类显示

父组件

复制代码
<div class="container">
	<Category title="美食">
      <img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg">
    </Category>
    <Category title="游戏">
      <ul>
        <li v-for="(item,index) in games" :key="index">{{item}}</li>
      </ul>
    </Category>
    <Category title="电影"> </Category>
 </div>

export default {
  name: "App",
  components: {Category},
  data() {
    return {
      foods:['火锅','烧烤','小龙虾','牛排'],
      games:['QQ飞车','穿越火线','王者荣耀','英雄联盟'],
      films:['《教父》','《拆弹专家》','《你好,李焕英》','《泰坦尼克号》']
    }
  },
}

子组件

复制代码
<div class="category">
	<h3>{{title}}分类</h3>
	<slot>没有具体结构,我就会出现</slot>
</div>

效果:

具名插槽

具名插槽,顾名思义,就是带有名字的插槽,具有 name 属性,实际上默认插槽也是一个不带 name 的具名插槽, 会带有默认的名字 default 。

使用方式:父组件使用slot或v-slot给插槽命名,子组件使用slot标签的name方法定义某个名字插槽,v-slot 有对应的简写 #,因此可以简写为 #name。其意思就是将这部分模板片段传入子组件的 name名的插槽中。

复制代码
		父组件中:
               <MyComponent >
                   <template slot="name1">
                     <div>html结构1</div>
                   </template>
       
                   <template v-slot:name2>
                      <div>html结构2</div>
                   </template>

                   <template #name3>
                   	  <div>html结构3</div>
                   </template>
               </MyComponent >
       子组件中:
               <template>
                      <!-- 定义插槽 -->
                      <slot name="name1">插槽默认内容...</slot>
                      <slot name="name2">插槽默认内容...</slot>
                      <slot name="name3">插槽默认内容...</slot>
               </template>

demo:

父组件:

复制代码
<template>
  <div class="container">
    <Category title="美食">
      <img slot="center" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg">
      <a slot="footer" href="http://www.baidu.com">更多美食</a>
    </Category>

    <Category title="游戏">
      <ul slot="center">
        <li v-for="(item,index) in games" :key="index">{{item}}</li>
      </ul>
    </Category>

    <Category title="电影">
      <template v-slot:footer>
        <div class="foot">
          <a href="http://www.baidu.com">经典</a>
          <a href="http://www.baidu.com">热门</a>
          <a href="http://www.baidu.com">推荐</a>
        </div>
        <h4 slot="footer">欢迎前来观影</h4>
      </template>
    </Category>
  </div>
</template>

子组件:

下面展示一些 内联代码片

复制代码
<template>
<div class="category">
  <h3>{{title}}分类</h3>
  <slot name="center">没有具体结构,我就会出现1</slot>
  <slot name="footer">没有具体结构,我就会出现2</slot>
</div>
</template>

效果:

条件插槽

有时需要根据插槽是否存在来渲染某些内容。可以结合使用 $slots 属性与 v-if 来实现。

使用方式:在子组件中使用

复制代码
<template>
    <div v-if="$slots.name1">
      <slot name="name1" />
    </div>
    
    <div v-if="$slots.default">
      <slot />
    </div>
    
    <div v-if="$slots.name2">
      <slot name="name2" />
    </div>
</template>

动态插槽名

在vue2.6.0引入的动态指令参数,在 v-slot 上也是有效的,即可以定义下面这样的动态插槽名:

复制代码
<base-layout>
  <template v-slot:[name1]>
    ...
  </template>

  <!-- 缩写为 -->
  <template #[name2]>
    ...
  </template>
</base-layout>

作用域插槽

由于插槽的内容无法访问到子组件的状态,然而在某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点,我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽。

使用方式:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(数据在子组件中,但使用数据所遍历出来的结构由父组件决定)

默认作用域插槽

复制代码
           父组件中:
                   <MyComponent >
                       <template scope="scopeData">
                           <!-- 生成的是ul列表 -->
                           <ul>
                               <li v-for="g in scopeData.text" :key="g">{{g}}</li>
                           </ul>
                       </template>
                   </MyComponent >
           
                   <MyComponent >
                       <template slot-scope="scopeData">
                           <h4 v-for="g in scopeData.text" :key="g">{{g}}</h4>
                       </template>
                   </MyComponent >
					 <!-- v-slot用法-->
				<MyComponent v-slot="{ text, test2}">
				 	 {{ text }} {{ test2}}
				</MyComponent>
           子组件中:
                   <template>
                       <div>
                           <slot :text="text"  :test2="test2"></slot>
                       </div>
                   </template>
                   
                   <script>
                       export default {
                           name:'MyComponent ',
                           props:['title'],
                           //数据在子组件自身
                           data() {
                               return {
                                   text:['1','2','3','4'],
                                   test2: "test2"
                               }
                           },
                       }
                   </script>

具名作用域插槽

具名作用域插槽的工作方式也是类似的,插槽 props 可以作为 v-slot 指令的值被访问到:v-slot:name="slotProps"。也可以进行缩写:

复制代码
父组件:
<MyComponent>
  <template v-slot:test1="slotProps">
    {{ slotProps}}
  </template>

  <template #default="slotProps">
    {{ slotProps}}
  </template>
 
 <template #test2="slotProps">
    {{ slotProps}}
  </template>
</MyComponent>

子组件:
<slot  slotProps="hello"></slot>

注意:如果你同时使用了具名插槽与默认插槽,则需要为默认插槽使用显式的 <template>标签。尝试直接为组件添加 v-slot 指令将导致编译错误。这是为了避免因默认插槽的 props 的作用域而困惑。

例如:

复制代码
<!-- 该模板无法编译 -->
<template>
  <MyComponent v-slot="{ slotProps}">
    <p>{{ slotProps }}</p>
    <template #test>
      <!-- slotProps 属于默认插槽,此处不可用 -->
      <p>{{ slotProps }}</p>
    </template>
  </MyComponent>
</template>

为默认插槽使用显式的<template>标签有助于更清晰地指出 message 属性在其他插槽中不可用:

复制代码
<template>
  <MyComponent>
    <!-- 使用显式的默认插槽 -->
    <template #default="{ slotProps}">
      <p>{{ slotProps }}</p>
    </template>

    <template #test>
   		 xxx
    </template>
  </MyComponent>
</template>

demo:

父组件:

复制代码
	<Category title="游戏">

        <!-- 使用显式的默认插槽 -->
        <template #default="{ slotProps}">
          <p>{{ slotProps }}</p>
        </template>

      <template #test="test">
        <p>Here's some contact info</p>
        <p>{{ test }}</p>
      </template>
    </Category>

子组件:

复制代码
	<h3>{{title}}分类</h3>
  <slot :slotProps="games" test="hello">默认内容</slot>
  <slot name="test" :slotProps="games" test="hello">默认内容</slot>

效果:

相关推荐
ayqy贾杰6 分钟前
Claude Fable 5 提示词泄漏,抓紧学习下
前端·后端·面试
To_OC8 小时前
别再串行写 await 了,Promise.all 才是并行请求的正确打开方式
前端·javascript·promise
To_OC9 小时前
LC 17 电话号码的字母组合:我的回溯算法,就是从这道题开窍的
javascript·算法·leetcode
vipbic9 小时前
中后台越做越乱后,我用插件化把它救回来了
前端·vue.js
Hyyy9 小时前
Computer Use 适合做什么,不适合做什么——一次真实使用后的思考
前端
小和尚同志9 小时前
前端 AI 单元测试思考与落地
前端·人工智能·aigc
invicinble10 小时前
c端系统,其实更像一个信息展示平台
前端
你怎么知道我是队长11 小时前
JavaScript的变量和数据类型介绍
开发语言·javascript·ecmascript
李姆斯11 小时前
管理是否可以被完全量化
前端·产品经理·团队管理
名字还没想好☜12 小时前
Next.js 中间件实战:鉴权、重定向与 A/B 分流
开发语言·前端·javascript·中间件·react·next.js