Vue中slot插槽的使用

为什么使用slot

  • slot翻译为插槽:
    • 在生活中很多地方都有插槽,电脑的USB插槽,插板当中的电源插槽
    • 插槽的目的是让我们原来的设备具备更多的扩展性
    • 比如电脑的USB我们可以插入U盘、硬盘、手机、音响、键盘、鼠标等等
  • 组件的插槽:
    • 组件的插槽也是为了让我们封装的组件更加具有扩展性
    • 让使用者可以决定组件内部的一些内容到底展示什么
  • 举例:移动网站中的导航栏
    • 移动开发中,几乎每个页面都有导航栏。
    • 导航栏我们必然会封装成一个插件,比如nav-bar组件。
    • 一旦有了这个组件,我们就可以在多个页面中复用了
      在这里插入图片描述
  • 如何去封装这类的组件呢?
    • 它们也很多区别,但是也有很多共性
    • 如果我们每一个单独去封装一个组件,显然不合适:比如每个页面都有返回,这部分内容我们就要重复去封装
    • 但是,如果我们封装成一个,好像也不合理:有些左侧是菜单,有些是返回,有些中间是搜索,有些是文字等等
  • 如何封装合适呢?抽取共性,保留不同
    • 最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽
    • 一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容
    • 是搜索框,还是文字,还是菜单。由调用者自己来决定。

子组件中引入插槽(以插入button为例):

  • 子组件(HelloWorld.vue):
<template>
    <div class="hello">
        hello
        <slot></slot>
    </div>
</template>

父子组件引入button:

<template>
  <div class="hello">
    <HelloWorld>
      <button>click</button><!-- 插槽中插入一个button -->
    </HelloWorld>  
  </div>
</template>
  1. 插槽的基本使用:<slot></slot>
  2. 插槽可以添加默认值:<slot><button>默认按钮</button></slot>,若插入其他元素可以替换掉默认值
  3. 如果有多个值,同时放入到组件中进行替换时,一起作为替换元素

具名插槽slot

  • 当子组件的功能复杂时,子组件的插槽可能并非是一个
    • 比如我们封装一个导航栏的子组件,可能就需要三个插槽,分别代表左边、中间、右边
    • 那么,外面在给插槽插入内容时,如何区分插入的是哪一个呢?
    • 这个时候,我们就需要给插槽起一个名字
  • 如何使用具名插槽呢?
    • 非常简单,只要给slot元素一个name属性即可
    • <slot name="center"></slot>

子组件(默认三个插槽):

<template>
    <div class="hello">
        <slot name="left"><span>左边</span></slot>
        <slot name="center"><span>中间</span></slot>
        <slot name="right"><span>右边</span></slot>
    </div>
</template>

父组件(替换掉中间中的内容为标题):

<template>
  <div class="hello">
    <HelloWorld>
        <span slot="center">标题</span>
    </HelloWorld>
  </div>
</template>

作用域插槽

  • 父组件替换插槽的标签,但是内容由子组件来提供
  • 我们先提一个需求:
    • 子组件中包括一组数据,比如:planguages:[ ‘Javascript’, ‘Python’, ‘Swift’, ‘Go’, ‘C++’]
    • 需要在多个界面进行展示:
      • 某些界面是以水平方向展示的
      • 某些界面是以列表形式展示的
      • 某些界面直接展示一个数组
    • 内容在子组件,希望父组件告诉我们如何展示,怎么办呢?
      • 利用slot作用域插槽就可以了

子组件(默认以list形式展示)

<template>
    <div class="hello">
        <slot :data_1="planguages">  <!-- 子组件插槽绑定子组件中的数据 -->
            <ul>
                <li v-for="(item,index) in planguages" :key="index">{{ item }}</li>
            </ul>
        </slot>
    </div>
</template>

<script>
export default {
    name: "HelloWorld",
    data() {
        return {
            planguages:['Javascript', 'Python', 'Swift', 'Go', 'C++']
        };
    }
};
</script>

父组件以多种方式展示子组件中数据:

<template>
  <div class="hello">
    <HelloWorld></HelloWorld><!-- 列表 -->
    <HelloWorld>
        <template slot-scope="slot_1">
            <span>{{ slot_1.data_1.join(' - ') }}</span> <!-- 水平展示 -->
        </template>
    </HelloWorld>
    <HelloWorld>
        <template slot-scope="slot_2">
            <span>{{ slot_2.data_1 }}</span> <!-- 数组展示 -->
        </template>
    </HelloWorld>
  </div>
</template>

猜你喜欢

转载自blog.csdn.net/xiecheng1995/article/details/106954694