VUE——组件(三)使用slot分发内容

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

props传递数据,events触发事件,sloat分发内容,就构成了vue组件的3个API来源。

一、slot的用法

单个slot

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

    <div id="app">
        <child-component>
            <p>这是分发内容</p>
            <p>更多的分发内容</p>
        </child-component>
    </div>
    <script type="text/javascript">
        Vue.component('child-component',{
            props:{},
            template:'<div>\
                <slot>\
                    <p>如果父组件没有插入内容,我将作为默认出现</p>\
                </slot>\
                </div>'
        })
        var app = new Vue({
            el: '#app',
            data: { },
            methods:{}
        })
    </script>

子组件child-component 模板内定义了一个<slot>元素,并且用一个<p>作为默认的内容,在父组件没有使用<slot>时,会渲染这段默认的文本,如果父组件写入了<slot>,那父组件的slot会替换整个子组件的<slot>

最终渲染结果为:

<div id="app">
        <div>
            <p>这是分发内容</p>
             <p>更多的分发内容</p>
        </div>
    </div>

  注意:子组件内的备用内容,它的作用域是子组件本身

具名slot

给<slot>指定一个name后可以分发多个内容,具名<slot>可以和单个<slot>共存

 
    <div id="app">
        <child-component>
            <h2 slot="header">标题</h2>
            <p>正文内容</p>
            <p>更多正文内容</p>
            <div slot="footer">底部信息</div>
        </child-component>
    </div>
    <script type="text/javascript">
        Vue.component('child-component',{
            props:{},
            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',
            data: { },
            methods:{}
        })
    </script>

   子组件内声明了多个<slot>元素,其中<div class="min">内的<slot>没有使用name特性,它将作为默认的<slot>出现,父组件没有使用<slot>特性的元素与内容将出现在这里

作用域插槽

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

    <div id="app">
        <child-component>
            <template scope="props"><!--props将数据传到插槽 临时变量--><!--通过临时变量props访问来自子组件插槽的数据msg-->
                <p>来自父组件的内容</p>
                <p>{{props.msg}}</p>
            </template>
        </child-component>
    </div>
    <script type="text/javascript">
        Vue.component('child-component',{
            props:{},
            template:'<div class="container">\
                <slot msg="来自子组件的内容"></slot>\
                </div>'
        })
        var app = new Vue({
            el: '#app',
            data: { },
            methods:{}
        })
    </script>

  最终渲染结果为

    <div id="app">
        <div class="container">
            <p>来自父组件的内容</p>
            <p>来自子组件的内容</p>
        </div>
    </div>

作用域插槽更具代表性的是列表组件,允许组件自定义列表每一项如何渲染

    <div id="app">
        <my-list :books="books">
            <template slot="book" scope="props"><!--作用域插槽也可以是具名slot-->
                <li>{{props.bookName}}</li>
            </template>
        </my-list>
    </div>
    <script type="text/javascript">
        Vue.component('my-list', {
            props: {
                books:{
                    type:Array,
                    default:function(){
                        return []
                    }
                }
            },
            template: '<ul>\
                <slot name="book"\
                v-for="item in books"\
                :book-name="item.name"\
                ></slot>\
                </ul'
        })
        var app = new Vue({
            el: '#app',
            data: {
                books:[
                    {name:'《我爸爸》'},
                    {name:'《我妈妈》'},
                    {name:'《我最爱我自己》'}
                ]
            },
            methods: {}
        })
    </script>

  作用域插槽的使用场景就是既可以复用子组件的slot有可以使slot内容不一致。

访问slot

Vue2中提供了$slots来访问分发内容

<div id="app">
        <child-component>
            <h2 slot="header">标题</h2>
            <p>正文内容</p>
            <p>更多正文内容</p>
            <div slot="footer">底部信息</div>
        </child-component>
    </div>
    <script type="text/javascript">
        Vue.component('child-component',{
            props:{},
            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(){//el挂载到实例上时调用,一般我们的第一个业务逻辑会写在这里
                var header= this.$slots.header,
                    main=this.$slots.default,
                    footer=this.$slots.footer;
                    console.log(header,main,footer)
            }
        })
        var app = new Vue({
            el: '#app',
            data: { },
            
            methods:{}
        })
</script>

通过slots可以访问某个具名的slot,this.$slots.default包括来所有没有具名的slot 

 

上一篇:上海办上海证书


下一篇:Vue-slot插槽