【vue(2)插槽】

插槽 --适用于父组件访问子组件

一、概念

1.概念

  • Slot 通俗的理解就是"占坑",在组件模板中占好了位置,当使用该组件标签的时候,组件标签里面的内容就会自动填坑(替换组件模板中slot位置)
  • 并且可以作为承载分发内容的出口

2.作用

允许你在使用组件时向组件内部插入内容(HTML、组件、甚至是函数),让组件可以根据这些内容进行渲染。

3.本质

  • 插槽是 Vue 提供的一个"内容占位符"。
  • 父组件可以向这个"占位符"中插入任意内容
  • 子组件可以决定这些内容在哪里显示

二、插槽的基本使用

  • 插槽就是"占一个位置",等别人来填内容
  • 就像写了一个组件,里面留了一个空位,别人用这个组件的时候,可以自己决定空位放什么内容

举例来说,这里有一个 <FancyButton> 组件

js 复制代码
<FancyButton>
  Click me! <!-- 插槽内容 -->
</FancyButton>

<FancyButton> 的模板是这样的

js 复制代码
<button class="fancy-btn">
  <slot></slot> <!-- 插槽出口 -->
</button>

<slot> 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。

最终渲染出的 DOM 是这样:

js 复制代码
<button class="fancy-btn">Click me!</button>

三、插槽的分类

名称 说明
默认插槽 插入内容,不指定名字
具名插槽 插入内容,指定名字
作用域插槽 插槽内容可以访问子组件的数据

1.默认插槽

我们要在页面显示三个类别,每个类别下面有不同的文字,本来是我们把数据传给子组件然后使用v-for遍历生成的文字信息,但是产品经理突然让你把美食类的下面换成图片,电影类下面换成视频,怎么搞?

子组件:

js 复制代码
<template>
    <div class="category">
        <h3>{{ title }}类</h3>
        <ul>
            <slot>我是一个插槽,当使用者没有传递具体结构时,我会出现</slot>
        </ul>
    </div>
</template>

父组件App.vue:

js 复制代码
<template>
    <div class="container">
        <Category title="美食">
        <!--往slot插入东西-->
            <img src="http://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
        </Category>
        <Category title="游戏">
         <!--往slot插入东西-->
            <li v-for="(game, index) in games" :key="index">
                {{ game }}
            </li>
        </Category>
        <Category title="电影">
         <!--往slot插入东西-->
            <video controls src="http://clips.vorwaerts-gmbh.de/big_buck.bunny.mp4"></video>
        </Category>
    </div>
</template>

<script>
import Category from './components/Category.vue';

export default {
    name: "App",
    components: { Category },
    data() {
        return {
            //foods: ['火锅', '烧烤', '小龙虾', '牛排'],
            games: ['战神4', '极品飞车', '鬼泣', '超级玛丽'],
           // films: ['《教父》', '《复仇者联盟》', '《绿皮书》', '《阿甘》']
        }
    },
}
</script>

2.具名插槽

子组件使用name属性起个名,父组件里面使用slot="名字"找到对应的坑位

html 复制代码
  父组件中:
	  <template>
	  	<div>
	          <Category>
	              <div slot="center">中间的结构</div>
	              <a slot="center" href="http://www.zzy.com">中间的结构</a>
	  
	              <template v-slot:footer>  最新写法,要配合template使用
	                 <div>底部的结构</div>
	                 <h4>欢迎你</h4>
	              </template>
	          </Category>
	    </div>
	 </template>
 
  子组件中:
        <template>
            <div>
               <!-- 定义插槽 -->
               <slot name="center">插槽默认内容...</slot>
               <slot name="footer">插槽默认内容...</slot>
            </div>
        </template>

3.作用域插槽

有一天,产品经理让你把每个部分的数据换个形式,换成下边这样,咋整?

这里就用到了作用域插槽,如果数据不在App中了,而在Category.vue中,然后App.vue要用到数据,这时我们就可以在Category.vue中使用slot标签给父组件App传值,写法很像当时父给子传值的props写法,在标签里搞个:games="games",然后用到插槽的地方必须使用template标签包裹,并且配置scope属性来接收数据,接过来的是一个对象

其实这个功能使用默认插槽完全可以实现,但是默认插槽是指数据在使用插槽的文件里的,那么如果数据在别的地方(比如本案例的Category.vue文件),就得用作用域插槽

html 复制代码
Category.vue文件
<template>
    <div class="category">
        <h3>{{ title }}类</h3>
        <slot :games="games">默认内容</slot>
    </div>
</template>

<script>
export default {
    name: 'Category',
    props: ['title'],
    data() {
        return {
            games: ['战神4', '极品飞车', '鬼泣', '超级玛丽']
        }
    },
};
</script>
html 复制代码
App.vue文件
<template>
    <div class="container">
        <Category title="游戏">
            <template scope="youxis">
                <!-- {{ youxis.games }} -->
                <!-- { "games": [ "战神4", "极品飞车", "鬼泣", "超级玛丽" ] } -->
                <ul>
                    <li v-for="(game, index) in youxis.games" :key="index">
                        {{ game }}
                    </li>
                </ul>
            </template>
        </Category>

        <Category title="游戏">
            <template scope="{games}">
                <ol>
                    <li v-for="(game, index) in games" :key="index">
                        {{ game }}
                    </li>
                </ol>
            </template>

        </Category>
        <Category title="游戏">
            <template slot-scope="{games: youxis}">
                <h4 v-for="(game, index) in youxis" :key="index">
                    {{ game }}
                </h4>
            </template>
        </Category>
    </div>
</template>

<script>
import Category from './components/Category.vue';
export default {
    name: "App",
    components: { Category },
}
</script>
相关推荐
mCell4 小时前
React 如何处理高频的实时数据?
前端·javascript·react.js
随笔记4 小时前
HbuilderX载入项目,运行后唤起微信开发者工具,提示:Error: Fail to open IDE,唤醒不起来怎么办
javascript·微信小程序·uni-app
百***35514 小时前
TypeScript 与后端开发Node.js
javascript·typescript·node.js
启山智软5 小时前
使用 Spring Boot + Vue.js 组合开发多商户商城(B2B2C平台)是一种高效的全栈技术方案
vue.js·spring boot·后端
hongliangsam5 小时前
Vue 3 defineModel 完全指南
vue.js
少卿5 小时前
PerformanceObserver 性能条目类型(Entry Types)
前端·javascript
进击的野人5 小时前
防抖与节流:优化前端性能的两种关键技术
前端·javascript
小高0075 小时前
别再滥用 Base64 了——Blob 才是前端减负的正确姿势
前端·javascript·面试
黑羽同学5 小时前
Fix: 修复AI聊天输入框Safari回车发送bug
前端·javascript·dom
进击的野人5 小时前
JavaScript原型与原型链:深入理解面向对象编程的基石
前端·javascript·面试