一. 概述

项目开发中想封装一个好用的列表组件,思考到怎么在一个组件中实现不同的样式和细微差别呢,想到了vue插槽功能符合我的预想。

注意:遇到了一个问题入坑了?,按照官方文档说明写的例子,还报错,倒腾了一天,各种百度都没有解决。突然想到可能跟vue版本有关,本地项目vue版本2.5.16,看的官方文档插槽的教程是2.6.0以上新写法。血的教训还是要仔细看文档,及时升级一下项目。下面笔记基于vue版本2.6.0以上的语法

二. 注意事项
  1. 如果在子组件中不定义分发内容的出口slot,即使在使用子组件时候,里面书写内容了也会被抛弃。
// app.vue
<template>
  <section>
      <my-list>
          <h2>定制内容</h2> // 这部分内容会被抛弃
      </my-list>
  </section>
</template>

<script>
export default {
   components: {
       myList: {
           template: '<div>子组件</div>'   //这里没有定义slot出口
       }
   },
}
</script>
三. 编译作用域

使用场景:在插槽中能使用父容器里数据,但是不能使用子组件里的作用域(数据)。

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

//app.vue
<template>
   <section>
       <my-list>
           <h2>{{title}}</h2>
       </my-list>
   </section>
</template>
// app.vue
<script>
export default {
    components: {
        myList: {
            template: '<div>子组件<slot></slot></div>'
        }
    },
    data() {
        return {
            title: '父作用域的变量',
        }
    }
}
</script>
四.后备内容,俗称默认内容

使用场景:一般我们操作按钮button,会根据不同情况显示不同内容,在我们没有设置状态的希望会给出一个默认文本。

用法:想给插槽设置一个默认值,只有当没有分发内容时候被渲染。

//app.vue
<template>
   <section>
       <my-list></my-list>
   </section>
</template>

<script>
export default {
    components: {
        myList: {
            template: '<div>子组件<slot>默认文本</slot></div>'
        }
    },
    data() {
        return {
            title: '父作用域的变量',
        }
    }
}
</script>
五.具名插槽

使用场景:一个模版需要多个插槽。

用法: 元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽。一个不带 name 的 出口会带有隐含的名字“default”。

//app.vue
<template>
   <section>
       <my-list>
           <template v-slot:header>name:header具名插槽</template>
           <div>内容被放到默认插槽中</div>
       </my-list>
   </section>
</template>

<script>
export default {
    components: {
        myList: {
            template:
            `<div>
                <slot name="header"></slot>
                <slot></slot>
            </div>`
        }
    },
}
</script>
六. 作用域插槽

使用场景:想要插槽内的内容访问子组件中才有的数据。

用法:绑定在 元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字

// table.vue
<template>
    <section>
        <div class="header">
            <slot name="pageHeader" v-bind:info="title">
                默认头部
            </slot>
        </div>
        <div class="main">
            <slot name="main"></slot>
        </div>
        <div class="footer">
            <slot name="pageFooter">
                默认底部
            </slot>
        </div>
    </section>
</template>

<script>
export default {
  data () {
    return {
      title: '子组件表格头部'
    }
  }
}
</script>
<style lang="scss" scoped>
.header{
    color: #35abdd;
    text-align: center;
    padding: 10px;
}
.table{
    padding: 10px;
    border: 1px solid #c1baba;

    .table-item{
        display: flex;
        flex-direction: row;
        justify-content: space-around;
        border-bottom: 1px solid #c1baba;

        span {
            display: block;
            text-align: center;
            padding: 10px;
        }
    }
}
.footer{
    margin-top: 20px;
    text-align: center;
    padding: 10px;
    color: #a8b6bc;
}
</style>
// app.vue
<template>
    <div class="home">
        <div class="body">
            <my-table>
                <template #pageHeader="propsData">
                    ----定制头部----
                    <div>{{propsData.info}}</div>
                </template>
                <template #main>
                    <ul class="table">
                      <li
                        class="table-item"
                        v-for="(item,index) of peopleArr"
                        :key="index +'peo'">
                          <span>{{item.name}}</span>
                          <span>{{item.age}}</span>
                      </li>
                    </ul>
                </template>
            </my-table>
        </div>
    </div>
</template>

<script>
// @ is an alias to /src
import myTable from '@/components/table.vue'

export default {
  name: 'home',
  components: {
    myTable,
  },
  data () {
    return {
      peopleArr: [
        { name: '徐开心', age: 13 },
        { name: '大韩', age: 6 },
        { name: '民国', age: 6 },
        { name: '万岁', age: 6 }
      ]
    }
  },
}
</script>
七. 具名插槽的缩写

使用场景:命令只有在有参数的时候才可以用缩写语法。#=“user”这种写法非法。正确写法:#default=“user”。

用法:v-slot:替换为字符 #,v-slot:header,可以写成 #header

Logo

前往低代码交流专区

更多推荐