Vue的slot-scope(v-slot)的场景的个人理解

Vue的插槽slot,分为3种

1. 匿名插槽(< slot > 作为我们想要插入内容的占位符)

2. 具名插槽(给插槽加入name属性就是具名插槽)

3. 作用域插槽(:text=“值” 子组件可向父组件传递信息)

前两种很好理解,无论就是子组件里定义一个slot占位符,父组件调用时,在slot对应的位置填充模板就好了。重点讲第三种,作用域插槽。

作用域插槽的慨念,文档却只有一句简单的描述

有的时候你希望提供的组件带有一个可从子组件获取数据的可复用的插槽。

语言描述太抽象,我想象不到slot-scope的使用场景。

前言

介绍了写这篇文章的来由,接下来简述一下本文的脉络

  • 先结合文档上todo-list的例子,来简单说明一下slot-scope的使用方式
  • 会使用但不理解什么时候用,就没有什么意义,所以本文第二部分,谈一下个人对于其使用场景的理解

官方文档slot-scope的示例

下面是2个父子的vue组件,先解释一下2个组件做了什么事情

  • 父组件仅仅是调用了子组件
  • 子组件内部实现了一个todolist列表

我建议从数据流动的角度,理解插槽作用域的使用方式,(先学会怎么用,暂时不用理解为什么要这么用,使用场景是第二部分

  • 1.父组件传递了todos数组给子组件
  • 2.子组件通过props接受了数组数据,这里应该没有任何问题
  • 3.子组件拿到数组后v-for渲染列表,并且通过 的方式,把数组内的每一个todo对象,传递给父组件
  • 4.父组件通过slot-scope="slotProps"的方式,接受todo对象,之后就可以通过slotProps.todo.xxx的方式来使用了

所以数据的流动经历了

  • 父组件传递todos数组给子组件
  • 子组件遍历todos数组,把里面的todo对象传递给父组件
    好啦,这就是slot-scope的使用方法,就这么简单,完结撒花~

我贴出全部代码,方便大家自己研究

父组件的源码,也就是调用者

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

<script>
import todoList from './todoList'
export default {
  data () {
    return {
      todos: [
        {
          id: 0,
          text: 'ziwei0',
          isComplete: false
        },
        {
          text: 'ziwei1',
          id: 1,
          isComplete: true
        },
        {
          text: 'ziwei2',
          id: 2,
          isComplete: false
        },
        {
          text: 'ziwei3',
          id: 3,
          isComplete: false
        }
      ]
    }
  },

  components: {
    todoList
  },

}
</script>

子组件源码,也就是封装组件的人

<template>
  <ul>
    <li v-for="todo in todos" :key="todo.id">
      <slot :todo="todo">
      </slot>
    </li>
  </ul>
</template>

<script>
export default {
  props: {
    todos: {
      type: Array
    }
  }
}
</script>

slot-scope的使用场景的个人理解

想象一个场景:

当你要给同事封装一个列表组件,你就需要使用作用域插槽(注意是列表或者类似列表的组件)

你开发的这个列表组件要如何使用呢?

一般来说作为列表组件的调用者,你的同事先做ajax请求,拿到一个这样的数组

    todos: [
        {
          id: 0,
          text: 'ziwei0',
          isComplete: false
        },
        {
          text: 'ziwei1',
          id: 1,
          isComplete: true
        },
        {
          text: 'ziwei2',
          id: 2,
          isComplete: false
        },
        {
          text: 'ziwei3',
          id: 3,
          isComplete: false
        }
      ]

之后会把todso传递给列表组件吧,那么列表组件内部做什么事情呢?

列表内部肯定会v-for去帮你的同事渲染这个数组嘛。 就类似element-ui里的table组件一样

问题的关键就在这里

列表组件的循环,是发生在组件内部的,所以通过 v-for=“todo in todos” ,列表组件很容易拿到每一项todo,但列表拿到数据没用呀,列表只是一个瓜皮,列表展示的布局和使用的参数是不固定的,所以你把数据交给子组件循环渲染是不行的,你需要在父组件来定义子组件的数据的展示效果。

那么你怎样才能把每一项的todo数据给传递出去呢?

你会发现没有办法!
无论是用$emit、vuex还是localStorage,可以考虑一下,会发现没有合适的时机,能让你把todo传递出去

所以为了应对这个场景下,发明了作用域插槽,列表组件可以通过< slot :todo=“todo”>传递todo出去

你的同事可以通过 slot-scope=“slotsProps”(v-slot=“slotProps”)拿到todo。

<template>
  <todo-list :todos="todos">
    <template slot-scope="slotProps"> // 就是这段代码
      <span v-if="slotProps.todo.isComplete"></span>
      <span>{{slotProps.todo.text}}</span>
    </template>
  </todo-list>
</template>

疑问1:一般不是我们传参数来调用组件吗?为什么组件还把数据传递回来?

的确,调用ui组件时一般是我们传递配置参数给他们来进行数据的展示。

但是存在一种情况,你传递的参数是不固定的,比如elemnt-ui的table组件,你把数组传递给table后,设置prop参数对应的字段名称,来展示对应row对象中名称的值。

<el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="date"//  <---就是这里
        label="日期"
        width="180">
      </el-table-column>
      <el-table-column
        prop="name"
        label="姓名"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="地址">
      </el-table-column>
    </el-table>
  </template>

因为循环的过程发生在table组件内部,所以table组件可以方便的获取到每一项数据,但是这些数据最终不是给组件的,而是我们自己要用的业务数据。所以也需要一个方式,让调用者能拿到自己想要的数据

疑问2: 既然子组件最终还要把我给他的数据,再返还给我,那我当初还干嘛给它,能不能就自己在父组件里玩?

如果你不把数据给子组件当然可以。但是就等于抛弃掉了子组件的封装,只能你直接在父组件自己写一个列表

毕竟你不把数据给子组件,子组件还渲染个锤子?没有父子关系的话,也就不用什么插槽了。

但是咱不是为了封装后,可以复用嘛,总不能永远不用组件嘛,每个页面都得从头写。
对我来说,就是同样的事情只做一次,之后就是ctrl+c,v,提高开发效率,只为了更好的摸鱼!
在这里插入图片描述

疑问3: 父组件需要子组件的数据?那不会有$emit和vuex嘛,为什么要有slot-scope?

e m i t 和 v u e x 是数据传递的一种方法,但是你可以尝试用 emit和vuex是数据传递的一种方法,但是你可以尝试用 emitvuex是数据传递的一种方法,但是你可以尝试用emit和vuex把todo传递给父组件。

你会发现的确没有合适的钩子、时机来$emit数据

一些网上个人认为不太恰当的例子

我认为几种说法是不太恰当的,也是给我造成一些困惑的

  • slot-scope是什么?就是把子组件的数据传递给父组件的一种方式

这种说法,会让我觉得slot-scope跟emit和vuex是一类东西

  • 在一些例子中,把数据定义在写死在列表组件中,展示如何把数据传递出去 这些举例子的不恰当之处,我觉得是不应该把数据定义在子组件里。

因为真正的使用场景下,子组件的数据都是来自父组件的。作为组件内部应该保持纯净。

就像element-ui里的table组件,肯定不会定义一些数据在组件内部,然后传递给你。

table组件的数据都是来自调用者的,然后table会把每一行的row,在开发者需要时,传递出去。

这些例子虽然不是错误,但是我觉得反而不利于理解slot-scope

链接: 学习自链接

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vueslot-scope是一个用于在父组件中传递数据给子组件的特殊属性。它允许你在父组件中定义一个插槽,并将数据传递给子组件来使用。 使用slot-scope的一般步骤如下: 1. 在父组件中定义一个插槽,并使用slot-scope属性指定一个变量名。例如: ```html <template> <div> <slot :item="item"></slot> </div> </template> ``` 在这个例子中,我们使用:item="item"将变量item传递给插槽。 2. 在子组件中使用插槽,并在插槽的内容中使用slot-scope指定的变量名。例如: ```html <template> <div> <slot-scope="props"> <p>{{ props.item }}</p> </slot-scope> </div> </template> ``` 在这个例子中,我们使用slot-scope="props"将传递给插槽的变量名设置为props,并在插槽的内容中使用props.item来访问传递的数据。 3. 在父组件中使用子组件,并在子组件标签中传递数据给插槽。例如: ```html <template> <div> <child-component> <template v-slot:item="{ item }"> <p>{{ item }}</p> </template> </child-component> </div> </template> ``` 在这个例子中,我们使用v-slot:item="{ item }"将插槽中的变量名设置为item,并在插槽的内容中使用item来访问传递给子组件的数据。 通过使用slot-scope,我们可以在父组件中传递任意类型的数据给子组件,并在子组件中使用这些数据进行渲染或其他操作。这种机制为组件之间的数据交互提供了一种灵活且强大的方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值