Vue之slot插槽

当需要让组件组合使用,混合父组件的内容子组件的模板时,就会用到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 实战》
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值