Vuejs 组件化开发中插槽的使用说明

2020-03-05 0 By admin

在生活中很多地方都有插槽,电脑的USB插槽,插板当中的电源插槽。插槽的目的是让我们原来的设备具备更多的扩展性。
组件的插槽也是为了让我们封装的组件更加具有扩展性;让使用者可以决定组件内部的一些内容到底展示什么。

一、移动网站中的导航栏

移动开发中,几乎每个页面都有导航栏,并且不同的页面,导航栏中的内容是不同的。导航栏我们必然会封装成一个插件,比如nav-bar组件。
一旦有了这个组件,我们就可以在多个页面中复用了。而为了解决不同页面导航内容不同的问题,我们就需要使用到插槽SLOT了。

二、如何设计组件和插槽合适呢?

抽取共性,保留不同。
最好的封装方式就是将共性抽取到组件中,将不同的地方保留为插槽。一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。
是搜索框,还是文字,还是菜单。由调用者自己来决定。这就是为什么我们要学习组件中的插槽slot的原因。

三、slot 基本使用

了解了为什么用slot,我们再来谈谈如何使用slot?
在子组件中,使用特殊的元素slot就可以为子组件开启一个插槽。
在父组件中,引用子组件时,设置要替换成的内容,就可以了。

四、对插槽进行命名

当子组件的功能复杂时,子组件的插槽可能并非是一个。
比如我们封装一个导航栏的子组件,可能就需要三个插槽,分别代表左边、中间、右边。那么父组件在给插槽插入内容时,如何区分插入的是哪一个呢?
这个时候,我们就需要给插槽起一个名字;在子组件中中的slot元素中使用name关键词对插槽设置名称。在父组件使用子组件的插槽时,通过slot来指定对哪个插槽生效。

<div id="app">
    <cpn>
        <button slot="center">提代组件中的插件内容</button>
    </cpn>
    <cpn></cpn>
    <cpn>
        <button>提代组件中的插件内容</button>
    </cpn>
</div>
<template id="cpn">
    <div>
        <h2>组件内容</h2>
        <slot name="left">组件中slot元素left</slot><br/>
        <slot name="center">组件中slot元素center</slot><br/>
        <slot name="right">组件中的slot元素right</slot><br />
        <slot>组件中的插槽</slot>
        <h4>组件中插件后内容</h4>
    </div>
</template>

<script src="../js/vue.js"></script>
<script>
const cpn = Vue.extend({
      template: '#cpn',
  })

const app = new Vue({
    el: "#app",
    components:{
         cpn
      }
    })
</script>

五、作用域插槽

作用域插槽是slot一个比较难理解的点,而且官方文档说的又有点不清晰。可以理解为父组件替换插槽的标签,但是内容由子组件来提供。
假设需求是这样的:
子组件中包括一组数据,比如:Languages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++']
需要在多个界面进行展示:某些界面是以水平方向展示的,某些界面是以列表形式展示的,某些界面直接展示一个数组。内容在子组件,希望父组件告诉我们如何展示;利用作用域插槽就可以了。

5.1、作用域插槽编写过程

1、在子组件中;通过data函数属性(languages),定义好数据。
2、在子组件的模板中,通过v-bind 将数据绑定到模板的一个变量(data123)中。
3、在父组件中,通过 template 或者其他的元素,设置slot-scope=”slotProps”属性;将子组件的Props对象赋值给slotProps属性。
4、在父组件的作用范围,就可以通过slotProps属性,展示子组件中的数据了。

<div id="app">
    <cpn>
        <template slot-scope="slotProps">
            <ul>
                <li v-for="item in slotProps.data">{{item}}</li>
            </ul>
        </template>
    </cpn>
    <cpn>
        <span slot-scope="slotProps">
            <h4>{{slotProps.data123.join('-')}}</h4>
        </span>
    </cpn>
</div>

<template id="cpn">
    <div>
        <slot :data123="languages"></slot>
    </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const cpn = Vue.extend({
        template: "#cpn",
        data(){
            return{
                languages:['java','php','ruby','html','css','c#']
            }
        }
    })
    const app = new Vue({
        el: "#app",
        components:{
            cpn
        }
    })
</script>