美文网首页
Vue之插槽slot

Vue之插槽slot

作者: wenmingxing | 来源:发表于2020-02-06 12:01 被阅读0次

    当需要让组件组合使用,混合父组件的内容子组件的模板时,就会用到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 实战》

    相关文章

      网友评论

          本文标题:Vue之插槽slot

          本文链接:https://www.haomeiwen.com/subject/eysyxhtx.html