vue3作用域插槽的理解与使用

2,118 阅读1分钟

作者接触前端时间较短,对于很多技术的见解还较为浅显。发表文章的初衷也是为了存放一些自己的学习笔记,内容有误的地方希望大家可以批评指正

1.什么是渲染作用域

在讲解作用域插槽之前,需要先引入渲染作用域的概念。例如在如下应用场景,子组件中存在一个变量title,在子组件内部是可以直接访问title的内容的。然而父组件调用子组件时,是无法直接访问子组件中的title的值。因为父级模板里的所有内容都是在父级作用域中编译的,而子组件所有内容都是在子作用域中编译的。

2.作用域插槽的基本理解与使用

上面提到了渲染作用域的问题,然而在很多应用场景下,需要在插槽中访问子组件作用域内的数据。因此作用域插槽的意义在于让插槽可以访问到子组件中的内容

通过一个简单的例子说明:ShowName组件接受父组件传入的参数names,随后通过插槽的出口向父组件传递参数。 该子组件的slot向父组件向上传递item与index属性。随后父组件中通过slotProps进行属性的调用。

通过注意:v-slot="xxxx",xxxx的名字并非一定是slotProps,可以自己定义

App.vue

<template>
  <div>
    <!-- 默认写法 -->
    <ShowNames :names="names">
      <template v-slot="slotProps">
        <span>{{ slotProps.item }} - {{ slotProps.index }}</span>
      </template>
    </ShowNames>
    <ShowNames :names="names">
      <template v-slot="showData">
        <span>{{ showData.item }} - {{ showData.index }}</span>
      </template>
    </ShowNames>
  </div>
</template>

<script>
import ShowNames from './ShowNames.vue'
export default {
  components: {
    ShowNames
  },
  setup () {
    const names = ["why", "kobe", "james", "curry"]
    return {
      names
    }
  }
}
</script>

<style lang="scss" scoped>

</style>

ShowName.vue

<template>
  <div>
    <template v-for="(item, index) in names" :key="item">
      <slot :item="item" :index="index"></slot>
    </template>
  </div>
</template>

<script>
  export default {
    props: {
      names: {
        type: Array,
        default: () => []
      }
    }
  }
</script>

<style scoped>

</style>

3.具名作用域插槽

可以为插槽指定具体的名字。

<template>
  <div>
    <!-- 具名作用域插槽 -->
    <ShowNames :names="names">
      <template v-slot:addition="addProps">
        <button>{{ addProps.item }}</button>
      </template>
    </ShowNames>
    <!-- 语法糖写法 -->
    <ShowNames :names="names">
      <template #addition="addProps2">
        <strong>{{ addProps2.item }}</strong>
      </template>
    </ShowNames>
  </div>
</template>

<script>
import ShowNames from './ShowNames.vue'
export default {
  components: {
    ShowNames
  },
  setup () {
    const names = ["why", "kobe", "james", "curry"]
    return {
      names
    }
  }
}
</script>

<style lang="scss" scoped>

</style>
<template>
  <div>
    <template v-for="(item, index) in names" :key="item">
      <slot name="addition" :item="item"></slot>
    </template>
  </div>
</template>

<script>
  export default {
    props: {
      names: {
        type: Array,
        default: () => []
      }
    }
  }
</script>

<style scoped>

</style>