插槽slot

插槽,也就是slot,是组件的一块HTML模板,一个slot最核心的两个问题是显示不显示和怎样显示

1、单个slot

单个插槽,别名默认插槽、匿名插槽,不用设置name属性

<div id="app">
    <children1>
        <span>12345</span>
    </children1>
</div>

<script type="text/javascript">
    var app = new Vue({
        el: '#app',
        components: {
            children1: {
                template: "<button><slot></slot>单个插槽</button>"
            }
        }
    });
</script>

2、具名slot

插槽加了name属性,就变成了具名插槽。具名插槽可以在一个组件中出现N次,出现在不同的位置

<div id="app">
    <children2>
        <span slot="first" @click="tobeknow">12345</span>
        <span slot="second">56789</span>
    </children2>
</div>

<script type="text/javascript">
    var app = new Vue({
        el: '#app',
        methods: {
            tobeknow: function () {
                console.log("It is the parent's method");
            }
        },
        components: {
            children2: {//这个无返回值,不会继续派发  
                template: "<button><slot name='first'></slot>具名插槽,<slot name='second'></slot></button>"
            }
        }
    });
</script>

3、作用域slot

vue2.5版本中slot-scope取代了scope,来实现作用域插槽,主要用在组件调用中,具体在template标签上面使用slot-scope来获取插槽slot上面的属性值,获取值的为一个对象,slot-scope=”它可以取任意字符串”,在element-ui的组件中经常看到。

<div id="app">
    <!-- 将数据传递给组件 -->
    <tb-list :data="data">
        <!-- 获取slot上面的值 -->
        <template slot-scope="scope">
            <p>索引:{{JSON.stringify(scope)}}</p>
            <p>索引:{{scope.$index}}</p>
            <p>姓名:{{scope.row.name}}</p>
            <p>年龄: {{scope.row.age}}</p>
            <p>性别: {{scope.row.sex}}</p>
        </template>
    </tb-list>
</div>

<script type="text/javascript">
    var app = new Vue({
        el: '#app',
        data: {
            data: [{
                name: 'kongzhi1',
                age: '29',
                sex: 'man'
            }]
        },
        components: {
            // 作用域slot
            'tb-list': {
                template:
                    `<ul>
                        <li v-for="(item, index) in data">
                            <slot :row="item" :$index="index"></slot>
                        </li>
                    </ul>`,
                // 获取值
                props: ['data']
            }
        }
    });
</script>

完整代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue入门之slot</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <children1>
        <span>12345</span>
    </children1>

    <children2>
        <span slot="first" @click="tobeknow">12345</span>
        <span slot="second">56789</span>
    </children2>

    <!-- 将数据传递给组件 -->
    <tb-list :data="data">
        <!-- 获取slot上面的值 -->
        <template slot-scope="scope">
            <p>索引:{{JSON.stringify(scope)}}</p>
            <p>索引:{{scope.$index}}</p>
            <p>姓名:{{scope.row.name}}</p>
            <p>年龄: {{scope.row.age}}</p>
            <p>性别: {{scope.row.sex}}</p>
        </template>
    </tb-list>
</div>

<script type="text/javascript">
    var app = new Vue({
        el: '#app',
        data: {
            data: [{
                name: 'kongzhi1',
                age: '29',
                sex: 'man'
            }]
        },
        methods: {
            tobeknow: function () {
                console.log("It is the parent's method");
            }
        },
        components: {
            // 单个slot
            children1: {
                template: "<button><slot></slot>单个插槽</button>"
            },
            // 具名slot
            children2: {
                template: "<button><slot name='first'></slot>具名插槽,<slot name='second'></slot></button>"
            },
            // 作用域slot
            'tb-list': {
                template:
                    `<ul>
                        <li v-for="(item, index) in data">
                            <slot :row="item" :$index="index"></slot>
                        </li>
                    </ul>`,
                // 获取值
                props: ['data']
            }
        }
    });
</script>
</body>
</html>