九、在Vue中使用插槽

2019-03-20  本文已影响0人  李浩然_6fd1
<body>
    <div id="root">
        <child></child>
    </div>

    <script>
        Vue.component('child',{
            template:'<div><p>hello</p></div>'
        })

        var vm = new Vue({
            el:"#root"
        })
    </script>
</body>

页面显示如下:


图片.png

那么什么时候会用到插槽呢?
假设现在有一个需求:子组件除了展示P标签外,还要展示一段内容,但是这个内容不是子组件所决定的,而是父组件传递过来的。
按照以前学的内容,从父组件传递给子组件,需要通过属性的形式来传递。
修改后如下:

<body>
    <div id="root">
        <child content='<p>Dell</p>'></child>
    </div>

    <script>
        Vue.component('child',{
            props:['content'],
            template:`<div>
                         <p>hello</p>
                         <div v-html="this.content"></div>
                      </div>`
        })

        var vm = new Vue({
            el:"#root"
        })
    </script>
</body>

其中子组件中template用了es6的语法``,如果用以前的语法也可以:

template:'<div><p>hello</p><div v-html="this.content"></div></div>'

这样是可行的,但是会有一个问题,如果父组件向子组件传值传的比较少,这样做是没问题的;但是当要传的内容很多的时候,代码就会变得很难阅读。
所以当子组件有一部分内容是根据父组件传递过来的DOM进行显示的时候,这时候就可以使用—插槽slot。
改变后的语法如下:

<body>
    <div id="root">
        <child>
            <p>Dell</p>
        </child>
    </div>

    <script>
        Vue.component('child',{
            template:`<div>
                         <p>Hello</p>
                         <slot></slot>
                      </div>`             
        })

        var vm = new Vue({
            el:"#root"
        })
    </script>
</body>

这种语法就像在使用的child标签中插入了内容(p标签),故叫插槽。
往子组件中插入了内容,那么子组件就有办法用到传递过来的内容,这时就使用了Vue中的内置语法—slot。slot显示的就是父组件中往子组件插入的p标签。
当然插槽还有一些别的特性。
1、slot标签内可以定义默认值:当在slot标签内写上别的内容(比如“默认内容”),且父组件中子组件没有插入插槽,这个时候slot中的内容(“默认内容”)就会显示出来。
代码如下:

<body>
    <div id="root">
        <child>
            
        </child>
    </div>

    <script>
        Vue.component('child',{
            template:`<div>
                         <p>Hello</p>
                         <slot>默认内容</slot>
                      </div>`             
        })

        var vm = new Vue({
            el:"#root"
        })
    </script>
</body>

网页显示如下:


图片.png

2、有选择的使用slot——具名插槽
先举个例子:

<body>
    <div id="root">
        <body-content></body-content>
    </div>

    <script>
        Vue.component('body-content',{
            template:`<div>
                         <div class='content'>content</div>
                      </div>`             
        })

        var vm = new Vue({
            el:"#root"
        })
    </script>
</body>

子组件中的内容会显示在上面的div标签上,但是如果我的需求是整个数据不只是单单由子组件的内容决定的,还由其他的内容决定(比如来一个头部数据和一个尾部数据),这就可以用到了插槽。
数据如下:

<body>
    <div id="root">
        <body-content>
            <div class="header">header</div>
            <div class="footer">footer</div>
        </body-content>
    </div>

    <script>
        Vue.component('body-content',{
            template:`<div>
                           <slot></slot>
                           <div class='content'>content</div>
                           <slot></slot>
                      </div>`             
        })

        var vm = new Vue({
            el:"#root"
        })
    </script>
</body>

网页显示如下:


图片.png

这个显示并不是我想要的,因为我想要的顺序是头部-content-尾部。但是这个显示的重复了。
这时就需要来给slot取名来避免这个问题。
修改代码如下:

<body>
    <div id="root">
        <body-content>
            <div class="header" slot='header'>header</div>
            <div class="footer" slot='footer'>footer</div>
        </body-content>
    </div>

    <script>
        Vue.component('body-content',{
            template:`<div>
                           <slot name='header'></slot>
                           <div class='content'>content</div>
                           <slot name='footer'></slot>
                      </div>`             
        })

        var vm = new Vue({
            el:"#root"
        })
    </script>
</body>

这个子组件需要从外部接收两个插入的内容,一部分的内容叫header,一部分的内容叫footer,而在父组件调用子组件的时候,插入了两个插槽,一个是插槽header,另一个是插槽footer。
这种写法,可以在调用子组件的时候,一次性传入多个区域的DOM结构;在子组件中,通过具名插槽,分别使用不同的DOM结构,方便做复杂的调用。
插槽和具名插槽的区别:插槽只可以有一个,而具名插槽可以有多个
当然。具名插槽也可以有默认内容。

上一篇 下一篇

猜你喜欢

热点阅读