插槽slot

插槽

插槽是组件内预留的槽口,通过这个槽口可以插入代码,但是组件必须使用双标签

插槽的分类

  • 匿名插槽 <slot></slot>

  • 具名插槽 <slot name='插槽名'></slot>

  • 作用域插槽

                <slot name='插槽名'></slot>

                <template v-slot:'插槽名'=scope></template>或

                <template #:'插槽名'=scope></template>或

                <template slot='插槽名' slot-scope='scope'></template>

匿名插槽(默认插槽)

<first>

        <template v-slot:default>

                匿名插槽的数据

       </template>

</first>

或<first>这里是匿名插槽的数据</first>

<slot></slot>

    <div id="app">
        <!-- 使用slot插槽必须使用双标签 -->
        <first>这里是匿名插槽的数据</first>
    </div>
    <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script>
    <script>
        let first = {
            //slot不能作为对外暴露标签
            template: `
                <div>
                    匿名插槽:
                    <slot></slot>
                </div>`
        }
        new Vue({
            el: "#app",
            data: {

            },
            components: {
                first
            }
        })
    </script>

具名插槽

  • v-slot:插槽名(vue2.6版本及以上支持)简写:#插槽名
  • slot="插槽名"

可以使用template标签包裹,也可以使用其他标签包裹,使用template包裹的插槽不会创建标签,而其他标签包裹的会创建对应的标签,建议使用template包裹因为更高效

    <div id="app">
        <first>
            <!-- 可以使用v-slot:插槽名 -->
            <template v-slot:tom>
                template包裹《v-slot:插槽名绑定》的数据
            </template>
            <!-- 使用template不会创建标签更高效,建议使用template包裹-->
            <template slot="jack">
                template包裹《slot="插槽名"绑定》的数据
            </template>
            <!-- 还可以使用#插槽名 -->
            <template #marray>
                template包裹《#插槽名绑定》的数据
            </template>
            <!-- 使用div会创建div标签-->
            <div slot="tonny">
                div包裹tonny插槽的数据
            </div>
            <template v-slot:default>
                template包裹匿名插槽的数据
            </template>
        </first>
    </div>
    <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script>
    <script>
        let first = {
         // 具名插槽通过name属性来设置
            template: `
                <div>
                    具名插槽:<slot name="tom"></slot><br>
                    具名插槽:<slot name="jack"></slot><br>
                    具名插槽:<slot name="marray"></slot><br>
                    具名插槽:<slot name="tonny"></slot><br>
                    默认插槽:<slot></slot>
                </div>`
        }
        new Vue({
            el: "#app",
            data: { },
            components: {
                first
            }
        })
    </script>

作用域插槽

  • 扩大了对应变量的作用域,可以在对应的父组件内容使用子组件的数据。
  • 作用域插槽本身一般是一个具名插槽。
  • 该插槽的不同点是在子组件渲染作用域插槽时,可以将子组件内部的数据传递给父组件,让父组件根据子组件的传递过来的数据决定如何渲染该插槽。

方法一:  <template slot="插槽名" slot-scope="scope">(vue2.6版本之前)

    <div id="app">
        <!-- 父组件调用 -->
        <first>
            <template slot="mySlot" slot-scope="scope">
                <div>
                    {{scope.a}}<br>{{scope.b}}<br>
                    <button @click="scope.c.username='tonny'">改变user的username</button><br>
                    <button @click="scope.d()">调用方法</button>
                    <br>
                    <button @click="scope.f(message)">更改父组件数据</button>
                </div>
            </template>
        </first>
    </div>
    <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script>
    <script>
        let first = {
            template: `
                <div>{{user.username}}
                    <slot name="mySlot" :a="msg" b='你好' :c="user" :d="sayWhat" :f="tips"></slot>
                </div>
            `,
            data() {
                return {
                    msg: "吃饭了么",
                    user: {
                        username: 'tom'
                    }
                }
            },
            methods: {
                sayWhat() {
                    console.log("说啥呢");
                },
                tips(arg) {
                    console.log(arg);
                }
            },
        }
        new Vue({
            el: "#app",
            data: {
                message: "父组件"
            },
            components: {
                first
            }
        })
    </script>

方法二:v-slot:插槽名=“接收的属性对象名”(一般为scope)(vue2.6版本及之后)

(v-slot:插槽名)可以缩写为(#:插槽名)

    <div id="app">
        <first>
            <!-- v-slot:插槽名=“接收的属性对象名(一般为scope)” -->
            <template v-slot:mySlot>
                <div>
                    {{scope.message}}
                    <button @click="scope.a.username='tom'">更改user的username</button>
                </div>
            </template>
        </first>
    </div>
    <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script>
    <script>
        let first = {
            template: `
                <div>{{msg}}{{user.username}}
                    <slot name='mySlot' :message="msg" :a="user"></slot>
                </div>`,
            data() {
                return {
                    msg: "子组件",
                    user: {
                        username: "tonny"
                    }
                }
            }
        }
        new Vue({
            el: "#app",
            data: {},
            components: {
                first
            }
        })
    </script>

【总结】

  • 使用slot来定义插槽
  • 一个组件中只能有一个匿名插槽。
  • 匿名插槽又称为默认插槽,内容默认传递给对应的具名插槽
  • slot标签中通过name属性来指定对应的插槽名字
  • 访问的时候通过slot属性来指定需要插入到的插槽名字
  • 具名插槽建议使用template标签包起来调用
  • 作用域插槽是扩大了对应的组件作用域,通过对应的插槽中数据的绑定来传递数据给对应的父组件
  • v-slot不要和slot的写法混用(区分版本来使用,不要一起使用)

组件的获取

相关属性

  • $root 获取根组件
  • $children 获取所有的子组件
  • $parent 获取父组件
  • $refs 获取对应的ref标记的组件

获取插槽相关属性

  • $slots 获取调用的所有插槽 (不包含作用域插槽)
  • $scopedSlots 获取调用的作用域插槽
    <div id="app">
        <father>
            <template slot="father">
                <div>
                    
                </div>
            </template>
        </father>
    </div>
    <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script>
    <script>
        let son = {
            template: `
                <div>{{msg}}
                    <button @click="handler">获取组件</button>
                    <button @click="handler1">获取插槽</button>
                    <slot></slot>
                    <slot name="son"></slot>
                </div> `,
            data() {
                return {
                    msg: "儿子"
                }
            },
            methods: {
                handler() {
                    console.log(this.$parent); //获取的是father组件
                    console.log(this.$root); //获取的是vue实例的组件
                },
                handler1() {
                    console.log(this.$slots); //
                    console.log(this.$scopedSlots); //获取的是自己的具名插槽
                }
            },
        }
        let father = {
            template: `
                <div>{{msg}}
                    <son>
                        <template slot="son" slot-scope="scope">
                            <div>
                                {{scope.msg}}
                            </div>
                        </template>
                    </son>
                    <button @click="handler2">获取组件</button>
                    <button @click="handler3">获取插槽</button>
                    <slot></slot>
                    <slot name="father"></slot>
                </div>`,
            data() {
                return {
                    msg: '父亲'
                }
            },
            components: {
                son
            },
            methods: {
                handler2() {
                    console.log(this.$parent); //获取的是vue实例的组件
                    console.log(this.$root); //获取的是vue实例的组件
                    console.log(this.$children); //获取的是son组件
                },
                handler3() {
                    console.log(this.$slots); //获取插槽名为father的插槽,不包含scope作用域插槽
                    console.log(this.$scopedSlots); // 获取调用的作用域插槽
                }
            }
        }
        new Vue({
            el: "#app",
            data: {
                msg: "爷爷"
            },
            components: {
                father
            }
        })
    </script>

【理解】props和slot比较

  • props 用来传递数据,它不是响应式的,所以是单向数据传输
  • slot 用来传递结构
  • 作用域插槽用来传递结构+数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值