Vue 中的匿名插槽、具名插槽以及作用域插槽(slot-scope)的理解

百度上已经有很多的关于slot-scope的文章,但我感觉都是那些以前没学好,又回头学的人,他们都使用了.Vue文件,我觉得有点不适合初学者,所以我就写一篇适合初学者的。
先抛例程:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件之通过插槽(slot)分发内容title>
    <script src="你的vue地址,请下载最新版的">script>
    <script>
        Vue.component("test-slot",{
           // 匿名插槽
           // 插槽允许有默认内容
           template:
               `
Error!
`
, data:function () { return { name:"perry" } } }); // 具名插槽 Vue.component("slot-name",{ template: `
`
}); // 作用域插槽 Vue.component("todo-list",{ inheritAttrs:false, props:{ todos:[Array,Object] }, template: `
  • {{todo.text}}
`
});
script> <style> li{ list-style: none; display: inline-block; font-size: 25px; } style> head> <body> <div id="app"> <test-slot>Something bad happened.你是谁啊,我认识你吗test-slot> <test-slot> Something bad happened. <h3>标题{{name}}h3> <img src="img/flower.jfif" alt="图片无法显示"> test-slot> <slot-name> <h3>劝学h3> <p>少壮不努力,老大徒伤悲p> <p>光阴似箭,日月如梭p> <template slot="header"> <ul > <li>主页li> <li>关于时间li> <li>关于人生li> <li>关于未来li> ul> template> <p>你好啊p> <p slot="footer"> <p>结尾p> <p>粤ICP备6545646456415p> p> slot-name> <todo-list :todos="todos"> <template slot-scope="slotProps"> <span v-if="slotProps.data.isTrue">span> {{slotProps.data.text}} template> todo-list> <todo-list :todos="todos"> <template slot-scope="{data}"> <span v-if="data.isTrue">span> {{data.text}} template> todo-list> div> <script> new Vue({ el:"#app", data:{ name:"岔道口", todos:[ {text:"A",id:1,isTrue:true}, {text:"B",id:2,isTrue:true}, {text:"C",id:3,isTrue:false}, {text:"D",id:4,isTrue:true}, ], // slotProps:"" } }) script> body> html>

例程中也写了普通插槽和具名插槽,这个我就不说,我就说一下作用域插槽。首先从“作用域插槽“”这个名字说起,本来你父组件的模板是无法使用到子组件模板中的数据,官网中有一句特别强调的话:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。这句话其实挺难理解,举个例子就知道了,

<test-slot>
     Something bad happened.
     
     <h3>标题{{name}}h3>
     <img src="img/flower.jfif" alt="图片无法显示">
test-slot>
 这是我上面的例子,也就是说这里name必须是当前组件里的,不能是test-slot这个组件内部的数据,这是它作用域限制,name这个数据属于父组件的作用域,所以只能是父组件的数据。但是slot-scope的出现却实现了父组件调用子组件内部的数据,子组件的数据通过slot-scope属性传递到了父组件
//    作用域插槽
Vue.component("todo-list",{
    inheritAttrs:false,
    props:{
        todos:[Array,Object]
    },
    template:
    `<ul>
        <li v-for="todo in todos" :key="todo.id" style="display: block;" >
            // 这里的:data=“todo”就是讲子组件todo这个数据传给了父组件
            // todo.text是默认值,父组件会把它覆盖掉
            <slot :data="todo">{{todo.text}}slot>
        li>
     ul>
    `
});

<todo-list :todos="todos">
    <template slot-scope="slotProps">
        <span v-if="slotProps.data.isTrue">span>
        {{slotProps.data.text}}
    template>
todo-list>

使用的时候就是这样,从子组件传过来的名为data值为todo的数据将会被slot-scope接收,需要注意的是,slot-scope接收的是一个对象,这里命名为slotProps,也就是说你传过来的data将会作为slotProps的一个属性,所以需要slotProps.data才能调用到data。前面说了,data的值为todo,todo是什么呢?todo是todos遍历出来的,所以是一个对象。

new Vue({
    el:"#app",
    data:{
        name:"岔道口",
        todos:[
            {text:"A",id:1,isTrue:true},
            {text:"B",id:2,isTrue:true},
            {text:"C",id:3,isTrue:false},
            {text:"D",id:4,isTrue:true},
        ],
        // slotProps:""
    }
});

我们已经理解了slot-scope特性,那么他有什么运用场景呢?我们可以试想一下,别人写好了一个组件,该组件已经封装好了,但他觉得,数据的显示风格让用户自己定义,就像我们上面,我们希望列表的样式由用户定义,比如我就加了一个√号。一开始最初的数据是我们传进去的,但数据必须进过子组件处理后,写组件那个人肯定希望显示的是处理后的数据。这时候slot-scope就无比重要了。

本文转载自: https://blog.csdn.net/huangyilinnuli/article/details/81239077

你可能感兴趣的:(Vue,vue)