美文网首页vue.js
Vue.js组件中的slot 内容分发详解

Vue.js组件中的slot 内容分发详解

作者: _littleTank_ | 来源:发表于2017-12-13 17:25 被阅读0次

    学习是一个过程,记录下来,方便学习。之前做vue项目,很少用到其组件的Slot,以至于无法了解他的精髓,今天项目需要组件的自定义,需要用到Slot,也就认真的看了下vue里关于solt的一些知识点,总结一下。

    1、Slot分发内容是干什么的?

    简单来说,假如父组件需要在子组件内放一些DOM,那么这些DOM是显示、不显示、在哪个地方显示、如何显示,就是Slot分发负责的活。

    2、Slot分发小实例?

    如下代码:

    <div id="app">  
        <my-component>
            <span>这个是html内容</span>  //这行代码在页面里是无法渲染出来的,因为他放在了组件里面
        </my-component>
    </div>  
    <script>  
        var vm = new Vue({  
            el: '#app',  
            components: {  
                myComponent: {  
                    template: "<div>这是个测试作用范围的文本</div>"  
                }  
            }  
        });  
    </script>
    

    上面的代码在浏览器中渲染出来是:““这是个测试作用范围的文本””这几个字,而不会显示“<span>这个是html内容</span> ”这行内容。因为默认情况下:父组件在子组件内套的内容,是不显示的。
    但是如果我们想让 “这个是html内容”这个几个字显示该怎么写呢?那就试试slot吧,如下代码:

    <div id="app">  
        <my-component>
            <span>这个是html内容</span>  //这行代码在页面里是无法渲染出来的,因为他放在了组件里面
        </my-component>
    </div>  
    <script>  
        var vm = new Vue({  
            el: '#app',  
            components: {  
                myComponent: {  
                    template: "<div><slot></slot>这是个测试作用范围的文本</div>"  
                }  
            }  
        });  
    </script>
    

    上面的代码在浏览器中渲染的结果是:“这个是html内容这是个测试作用范围的文本”。当然了,我们slot写在哪里,其对应的内容显示在哪里。

    如果上边的 template:写成 "<div>这是个测试作用范围的文本<slot></slot></div>"  
    

    那么渲染的结果是:“这是个测试作用范围的文本这个是html内容”。

    3、具名slot

    slot元素可以用一个特殊的属性name 来配置如何分发内容,多个slot可以有不用的名字,根据具名slot的name来进行匹配,显示内容。如下代码:

        <div id="app">  
            <my-component>
                <span slot="first">111</span>  
                <span slot="second">222</span> 
           </my-component>
        </div>  
        <script>  
            var vm = new Vue({  
                el: '#app',  
                components: {  
                    myComponent: {   
                        template: "<div><slot name='first'></slot>为了明确作用范围<slot name='second'></slot></div>"  
                    }  
                }  
            });  
        </script>  
    

    上面的代码渲染的结果是:“111为了明确作用范围222”。

    4、需要注意:分发内容的作用域

        <div id="app">  
            <my-component>
                <span slot="first" @click="getText">111</span>  
                <span slot="second">222</span> 
           </my-component>
        </div>  
        <script>  
            var vm = new Vue({  
                el: '#app',  
                methods:{
                      getText:function(){
                           alert("111")
                      } 
                },
                components: {  
                    myComponent: {   
                        template: "<button><slot name='first'></slot>为了明确作用范围<slot name='second'></slot></button>"  
                    }  
                }  
            });  
        </script>  
    

    上面代码,如果我点击111(而不是按钮button全部),会触发父层的函数getText,弹出“111”。如果点击其他部分则不会有反应。为什么呢? 官方教程是这么说的:父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。

    5、需要注意:当没有分发内容时的提示

    假如父组件没有在子组件中放置有标签,或者是父组件在子组件中放置标签,但有slot属性,而子组件中没有该slot属性的标签。那么,子组件的slot标签,将不会起到任何作用,除非,该slot标签内有内容,那么在无分发内容的时候,会显示该slot标签内的内容。
    上面这句话怎么理解呢?看下边代码。

        <div id="app">  
            <my-component>
                <h1 slot="first">111</h1>  
           </my-component>
        </div>  
        <script>  
            var vm = new Vue({  
                el: '#app',  
                methods:{
                      getText:function(){
                           alert("111")
                      } 
                },
                components: {  
                    myComponent: {   
                        template: "<div><slot name='first'>3333</slot>为了明确作用范围<slot name='second'></slot></div>"  
                    }  
                }  
            });  
        </script>  
    

    上面的代码渲染结果:“111为了明确作用范围”。为啥会是这样呢?
    子组件里<slot name='first'>3333</slot>这个的name属性first可以在父组件里找到对应的值,所以会显示父组件的值111,而忽略自身内部的3333。
    而<slot name='second'></slot>没有在父组件里找到slot="second"的标签内容,所以会被忽略,不显示任何内容(这种情况下,如果是 template: "<div><slot name='first'>3333</slot>为了明确作用范围<slot name='second'>444</slot></div>" ,那么就会渲染出 “111为了明确作用范围444”)。

    6、slot的应用场景举例

    (1、)
    比如你自己做了个一个button组件,在根组件里注册为vButton,从而复用。
    那么各个button上的文字肯定是不同的,但是这些文字大部分情况下也是不需要动态更新的,那么就不必用props之类的方法从根组件向子组件传递文字,直接用slot即可。

    <template>
      <button>
        <slot></slot>
      </button>
    </template>
    

    根组件就可以这样用它:
    <v-button>我是按钮111</v-button>,<v-button>我是按钮222</v-button>这样就会显示2个不同的按钮
    这是最简单的一个用法示例。是不是觉得很方便,,,,哈哈哈。

    再说一句吧:通常情况下,子组件的内容只能在子组件中定义。但是通过 slot,父组件定的内容可以传到子组件中去。总之慢慢摸索其中的精髓吧,开着小坦克,突突突.....

    相关文章

      网友评论

        本文标题:Vue.js组件中的slot 内容分发详解

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