VUE学习笔记--内容分发

基础用法
标签<slot>会把组件使用上下文的内容注入到此标签所占据的位置上。组件分发的概念简单而强大,因为它意味着对一个隔离的组件除了通过属性、事件交互之外,还可以注入内容。

尽管内容分发这个概念看起来极为复杂,而实际上可以简单了解为把HTML标签传入组件的一种方法。所以归根结底,内容分发是一种为组件传递参数的方法。

<div class="" id="app">
    <my-component>
        <p>hi,slots</p>
    </my-component> 
</div>
<script>
    Vue.component('my-component', {
            template:'<div><slot></slot><div>'
    });
    new Vue({
        el: "#app"
});
</script>
编译作用域
组件作用域简单地说是:父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8"/>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
      <child-component  v-show="someChildProperty"></child-component>
</div>
<script>
    Vue.component('child-component', {
        template: '<div>这是子组件内容</div>',
        data: function () {
            return {
                someChildProperty: true
            }
        }
    })
    new Vue({
        el:'#app'
    })
</script>
</body>
</html>
这里someChildProperty绑定的是父组件的数据,所以是无效的,获取不到数据。如果想在子组件上绑定,可以是如下代码:

因此,slot分发的内容是在父作用域内编译。

<div id="app">
  <child-component ></child-component>
</div>
<script>
    Vue.component('child-component', {
        // 有效,因为是在正确的作用域内
        template: '<div  v-show="someChildProperty">这是子组件内容</div>',
        data: function () {
            return {
                someChildProperty: true
            }
        }
    })
    new Vue({
        el:'#app'
    })
</script>
默认 slot 
如果要父组件在子组件中插入内容 ,必须要在子组件中声明slot 标签  ,如果子组件模板不包含<slot>插口,父组件的内容将会被丢弃

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8"/>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <!-- 1.2 那组件innerHTML位置以后不管有任何代码,都会被放进插槽那个坑里面去 -->
    <index>
        <span>首页</span>
        <span>首页</span>
        <span>首页</span>
        <h1>手机</h1>
    </index>
</div>
<script>
    // 插槽的作用就是组件外部取代码片段放到组件内部来
    // 定义默认插槽通过slot组件定义,定义好了之后,就相当于一个坑,你可以把它理解为电脑上usb插口
    Vue.component('index', {
        template:' <div>index</div>'
    })
    var vm = new Vue({
        el: '#app',
    })
</script>
</body>
</html>
页面显示结果为:index。所有子组件中的内容都不会被显示,被丢弃。
要想父组件在 子组件中插入内容,必须要在子组件中声明 slot 标签,示例代码如下:

<script>
        vue. component ( 'index', {
            template : '<div><slot></slot>index </div>'
        })
        var vm=new vue ( {
            el : '#app ' ,
        })
    </script>
具名 slot
slot 元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 标签可以有不同的名字。
使用方法。
父组件要在分发的标签中添加属性"slot=name 名"。 
子组件在对应分发位置上的 slot 标签添加属性"name=name 名"。
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8"/>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<body>
  <div id="app">
        <child>
          <span slot="one">123456</span>
          <span slot="two">abcdef</span>
        </child>
      </div>
  <script>
    new Vue({
        el:'#app',
        components:{
            child:{
                template:"<div><slot name='two'></slot>我是子组件<slot name='one'></slot></div>"
            }
        }
    });
</script>
</body>
</body>
</html>
 作用域插槽
作用域插槽的样式由父组件决定,内容却由子组件控制。

作用域插槽更具代表性的应用是列表组件,允许组件自定义应该如何渲染列表每一项,如下面示例代码:
<div id="app">
    <child></child>
</div>
<script>
    Vue.component('child', {
        data(){
            return {
                list:[1,2,3,4]
        }
        },
        template: '<div> <ul>' +
            '<li v-for="item of list">{{item}}</li></ul></div>',
    })
    var vm = new Vue({
        el: '#app'
    })
</script>
在上面示例代码中,如果需要child组件在很多地方会被调用,我希望在不同的地方调用child的组件时,这个列表到底怎么循环,列表的样式不是child组件控制的,而是外部child模版占位符告诉我们组件的每一项该如何渲染,也就是说这里不用li标签,而是要用slot标签,示例代码如下:

<div id="app">
    <child>
        <template slot-scope="props">       <!--固定写法,属性值可以自定义-->
            <li>{{props.item}}</li>         <!--用插值表达式就可以直接使用-->
        </template>
    </child>
</div>
<script>
    Vue.component('child', {
        data(){
            return {
                list:[1,2,3,4]
        }
        },
        template: '<div> <ul>' +
            '<slot v-for="item of list" :item=item></slot> </ul></div>',
    })
    var vm = new Vue({
        el: '#app'
    })
</script>

 

上一篇:VUE实现页面缓存


下一篇:第三百三十六天 how can I 坚持