[vue]之插槽slot

作者: MJ 分类: vue 发布时间: 2019-06-19 16:55

最开始听到插槽,实在是有点迷惑,在深入学习之后,我自己把它用【占位】来理解,其实官网已经说的很清楚了,为啥还要写一遍呢,我感觉自己梳理一遍写出来,会让自己更加深入的理解概念和用法。

以下都是基于官网最新,不包含废弃的。

一:插槽内容

简单的理解就是:

1:在父组件中的子组件里边加入自己想要的内容,然后跟子组件里边的内容混在一起;


2:如果父组件中的子组件有内容,就展示该内容,子组件中的slot则被忽略;


3:如果父组件中的子组件没有内容,就展示子组件里边slot占位里边的内容。

好像还是不太明白,是吗?哭笑的表情,还是代码实在。

父组件:

<template>
    <div>
        <h1>solt</h1>
        <Children>
            
        </Children>
    </div>
</template>

子组件(Children):

<template>
    <div>
        <slot>我是占位内容,如果子组件(Children)里边有值我就不显示,反之,我就显示。</slot>
        <h2>我是子组件内容</h2>
    </div>
</template>

二:编译作用域

刚接触这个概念的时候,还是有点蒙的,理解之后再去看文档,很有道理,哈哈。其实就是插槽模板可以访问父组件的值,但是不可以访问子组件内部的值。

看下边的代码,其实就是父组件内的Children下的插槽可以访问父组件的数据msg,但是访问不了Children组件内的names,这就是插槽的作用域。

作为一条规则,请记住:

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

父组件:

<template>
    <div>
        <h1>solt</h1>
        <Children>
            {{ msg }}
        </Children>
    </div>
</template>

<script>
const Children = () => import('@/pages/solt/children');
export default {
    data(){
        return {
            msg:"我是内容"
        }
    },
    components: {
        Children
    }
}
</script>

子组件:

<script>
export default {
    data () {
        return {
            names:"abc"
        }
    },
    props:['url']
}
</script>

三:后备内容

其实就是最开始的这一句解释:

3:如果父组件中的子组件没有内容,就展示子组件里边slot占位里边的内容

四:具名插槽

简单的字面理解就是:具有名字的插槽。

看代码一目了然,这里有一个注意点:
一个不带 name 的 <slot> 出口会带有隐含的名字“default”。

父组件:

<template>
    <div>
        <h1>solt</h1>
        <Children>
            <template v-slot:header></template>
            //<template v-slot:default></template>
            <p>我是内容</p>
            <template v-slot:footer></template>
        </Children>
    </div>
</template>

子组件:

<template>
    <div>
        <h2>我是子组件内容</h2>
        <slot name="header">我是header</slot>
        //<slot name="default">我是内容</slot>
        <slot>我是内容</slot>
        <slot name="footer">我是footer</slot>
    </div>
</template>

五:作用域插槽

有时让插槽内容能够访问子组件中才有的数据是很有用的。

可以这么来理解作用域插槽:就是在父级组件内的子组件插槽内(<Chinlren>我这个区域就是:子组件插槽内 </Children>),可以访问子组件内的data数据。

父组件:

<template>
    <div>
        <h1>solt</h1>
        <Children v-slot:default="names">
            {{ names }}
        </Children>
    </div>
</template>

子组件:

<template>
    <div>
        <h2>我是子组件内容</h2>
        <slot v-bind:names="names">我是内容</slot>
    </div>
</template>
<script>
export default {
    data () {
        return {
            names:"abc"
        }
    }
}

#独占默认插槽的缩写语法

1:当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot 直接用在组件上 。

(v-slot可以省略template标签直接写在组件上)

2: 假定未指明的内容对应默认插槽一样,不带参数的 v-slot 被假定对应默认插槽

(v-slot:default可以缩写为v-slot)

#解构插槽 Prop

<template>
    <div>
        <h1>solt</h1>
        <Children v-slot:default="{names}">
            {{ names }}
        </Children>
    </div>
</template>

六:动态插槽名

<template v-slot:[name]>
    
</template>

七:具名插槽的缩写

v-slot:header缩写为:#header

八:其他

示例:

父组件:

<template>
    <div>
        <h1>solt</h1>
        <Children>
            <template v-slot:todo="{todo}">
                <span v-if="todo.flag">{{todo.age}}</span>
            </template>
        </Children>
    </div>
</template>

子组件:

<template>
    <div>
        <h2>我是子组件内容</h2>
        <ul>
            <li v-for="todo in arrs" :key="todo.age">
                <slot name="todo" v-bind:todo="todo">
                    {{ todo.name }}
                </slot>
            </li>
        </ul>
    </div>
</template>

<script>
export default {
    data () {
        return {
            arrs:[
                {
                    name:"zhangsan",
                    age:31,
                    flag:true
                },
                {
                    name:"wangwu",
                    age:18,
                    flag:false
                },
                {
                    name:"zhaoliu",
                    age:20,
                    flag:true
                }
            ]
        }
    }
}
</script>

参考官方 https://cn.vuejs.org/v2/guide/components-slots.html#%E5%85%B6%E5%AE%83%E7%A4%BA%E4%BE%8B

完结。

欢迎关注小程序,感谢您的支持!

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

电子邮件地址不会被公开。 必填项已用*标注