天下无坑

天下无坑


slot之作用域插槽 理解

> 作用域插槽主要应用场景是循环结构 作用域插槽: 子组件内数据可以被父页面拿到(解决了数据只能从父页面传递给子组件) 在父页面使用template标签对子组件的slot插槽进行重写 slot标签template标签用于传递/接收插槽的nameprops,不影响最终的html元素输出

  • 理解图一
start
:**子组件中寻找作用域slot**
<slot name="插槽名" :age="[1,2,3]" :sex="[0,1]"></slot>;
:**父页面中寻找slot的template**
<template #插槽名="{age,sex}"></template>;
if (是否找到?) then (找到)
:获取子组件所有prop的数据集合;
:用父页面中的template渲染;
else (没找到)
:用子组件slot内的html作为template渲染(如有);
note right
  Vue.component("datagrid",{
    props:{
        data:null
    },
    template:`
     <table>
        <thead>
          <slot name="headslot"></slot>
        </thead>
        <tbody>
          <tr v-for="itemV in data">
            <slot name="bodyslot" :item="itemV">
            <!- - 子组件中如果slot带有默认内容,且有渲染数据 - ->
            <!- - 需要使用itemV, 而不是props名item - ->
            {{itemV.text}}
            </slot>
          </tr>
       </tbody>
     </table>
   `
  });
end note

endif
stop
  • 理解图二
parent<-child.vue:检查获取子组件的slot
parent->child.vue:用template标签重写slot模板
parent<-child.vue:从slot中取出所有props数据,整合为一个对象
parent->child.vue:用得到的props对象渲染template

父页面

  • slotProps 可以随意命名
  • slotProps 接收的是子组件slot标签上props的集合,即所有v-bind:user="user"指令的集合
<todo-list>
  <template v-slot:todo="slotProps"> 
      {{slotProps.user.firstName}}
  </template> 
</todo-list> 

//多个props可用对象解构或改名,如写成:
v-slot:todo="{user,name}"
v-slot:todo="{user:uid,name}"

子组件

 <slot name="todo" :user="userV" :test="testV">
        {{ userV.lastName }}
  </slot> 
data() {
        return {
            userV:{
                lastName:"Zhang",
                firstName:"yue"
            },
            testV:[1,2,3,4]
        }
    },

    // {{ userV.lastName }}是默认数据 v-slot:todo 
    // 当父页面没有(="slotProps") 时显示 Zhang

// 显示yue

完整实例及注释

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <title>vue slot-scope</title>
 </head>
 <body>
  <div id="app">
    <datagrid :data="todos">
      <template #headslot>
       <tr>
        <td>id</td>
         <td>text</td>
         <td>isTrue</td>
       </tr>
      </template>
      <template #bodyslot="slotProps">
        <!--slotProps是slot上的props的数据集合-->
        <td>{{slotProps.item.id}}</td>
        <td>{{slotProps.item.text}}</td>
        <td>{{slotProps.item.isTrue}}</td>
      </template>

      <!-- 另一种写法,加花括号,列出props名-->
      <!--<template #bodyslot="{item}">
        <td>{{item.id}}</td>
        <td>{{item.text}}</td>
        <td>{{item.isTrue}}</td>
      </template> 
      -->
    </datagrid>
  </div>

  <script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
  <!-- <script src=../static/vue.js></script> --> 
  <script>
  Vue.component("datagrid",{
    props:{
        data:null
    },
    template:`
     <table>
        <thead>
          <slot name="headslot"></slot>
        </thead>
        <tbody>
          <tr v-for="itemV in data">
            <slot name="bodyslot" :item="itemV">
            <!-- 如果slot带有默认内容,且有渲染数据 -->
            <!-- 需要使用itemV, 而不是props名item -->
            {{itemV.text}}
            </slot>
          </tr>
       </tbody>
     </table>
   `
  });

  var vm = new Vue({
    el:"#app",
    data:{
      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},
      ]
    }
  });     
  </script>
 </body>
</html>

页面列表

ITEM_HTML