Vue之插槽slot

2020-02-06  本文已影响0人  wenmingxing

当需要让组件组合使用,混合父组件的内容子组件的模板时,就会用到slot。这个过程叫做内容分发

其主要特点为:

1. 作用域

首先需要了解一个概念: 编译的作用域

父组件模板的内容是在父组件作用域内编译,子组件模板的内容是在子组件作用域内编译。

slot分发的内容,作用域是在父组件上的

2. slot用法

在子组件内使用<slot>元素就可以为这个子组件开启一个slot插槽,在父组件模板中,插入在子组件标签内的所有内容将代替子组件的<slot>标签及它的内容:

单个slot

<!-- 单个slot -->
<body>
    <div id="app">
        <child-component>
            <p>分发的内容</p>
            <p>更多分发的内容</p>
        </child-component>
    </div>

    <script src = "https://unpkg.com/vue/dist/vue.min.js"></script>
    <script>
        Vue.component('child-component',{
            template: '\
            <div>\
                <slot>\
                    <p>如果父组件没有插入内容,我将默认出现</p>\
                </slot>\
            </div>'
        });

        var app = new Vue({
            el: '#app',
        })
    </script>
</body>
执行结果

如果将上述代码中的这部分注释:

<child-component>
    <!-- <p>分发的内容</p>
    <p>更多分发的内容</p> -->
</child-component>  

则执行结果如下:

执行结果

可见,在父组件没有使用slot时,会渲染子组件的默认文本;如果写入了slot将会替换整个<slot>

具名slot

<slot>元素指定一个name后可以分发多个内容,剧名Slot可以与单个Slot共存:

<!-- 具名slot -->
<body>
    <div id="app">
        <child-component>
            <h2 slot="header">覆盖标题</h2>
            
            <div slot="footer">覆盖底部</div>
        </child-component>
    </div>

    <script src = "https://unpkg.com/vue/dist/vue.min.js"></script>
    <script>
        Vue.component('child-component',{
            template: '\
            <div class="container">\
                <div class="header">\
                    <slot name="header">默认标题</slot>\
                </div>\
                <div class="main">\
                    <slot>默认正文</slot>\
                </div>\
                <div class="footer">\
                    <slot name="footer">默认底部</slot>\
                </div>\
            </div>'
        });

        var app = new Vue({
            el: '#app',
        })
    </script>
</body>
执行结果

子组件中声明了三个<slot>,其中<div class="main">中的<slot>没有使用name属性,即为默认slot,如果父组件包含没有使用slot特性的元素都将出现在这里。

3. 作用域插槽

作用域插槽是一种特殊的slot,其使用一个可以复用的模板替换已渲染元素

<!-- 作用域插槽 -->
<body>
    <div id="app">
        <child-component>
            <template scope="props">
                <p>来自父组件的内容</p>
                <p>{{props.msg}}</p>
            </template>
        </child-component>
    </div>

    <script src = "https://unpkg.com/vue/dist/vue.min.js"></script>
    <script>
        Vue.component('child-component',{
            template: '\
            <div class="container">\
                <slot msg="来自子组件的内容"></slot>\
            </div>'
        });

        var app = new Vue({
            el: '#app',
        })
    </script>
</body>
执行结果

上述代码在子组件的模板上,<slot>元素中有一个类似props传递数据给组件的写法msg="xxx",将数据传到了插槽。父组件中使用<template>模板,并且拥有一个scope="props"的特性,这里的props只是一个临时变量,template内可以通过这个临时变量访问来自子组件插槽中的数据msg

4.访问slot

Vue 2.x提供了用来访问被slot分发的内容的方法$slots:

<!-- 访问slot -->
<body>
    <div id="app">
        <child-component>
            <h2 slot="header">覆盖标题</h2>
            <p>覆盖正文</p>
            <p>更多覆盖正文</p>
            <div slot="footer">覆盖底部</div>
        </child-component>
    </div>

    <script src = "https://unpkg.com/vue/dist/vue.min.js"></script>
    <script>
        Vue.component('child-component',{
            template: '\
            <div class="container">\
                <div class="header">\
                    <slot name="header">默认标题</slot>\
                </div>\
                <div class="main">\
                    <slot>默认正文</slot>\
                </div>\
                <div class="footer">\
                    <slot name="footer">默认底部</slot>\
                </div>\
            </div>',

            mounted: function() {
                var header = this.$slots.header;
                var main = this.$slots.default; //所有没有包含在具名slot中的节点
                var footer = this.$slots.footer;

                console.log(footer);
                console.log(footer[0].elm.innerHTML);
            }
        });

        var app = new Vue({
            el: '#app',
        })
    </script>
</body>  
执行结果

通过$slots可以访问某个具名slot,this.$slots.default包括了所有没有包含在具名slot中的节点。

参考

  1. 《Vue.js 实战》
上一篇 下一篇

猜你喜欢

热点阅读