Personal understanding of Vue's slot-scope scene

This article is not simply to translate and demonstrate the documentation and api, but to talk about my personal understanding of the usage scenarios of slot-scope. If you understand it wrong, welcome to discuss!

Vue slots are divided into 3 types

  • Anonymous slot
  • Named slot
  • Scope slot

The first two are well understood, whether it is defining a slot placeholder in the child component, when the parent component is called, just fill the template in the corresponding position of the slot.

The concept of scope slot, the document only has a simple description

Sometimes you want to provide a component with a reusable slot that can get data from subcomponents.

Most articles on the Internet also translate this sentence in the same way, but with this sentence alone, I can't imagine the use of slot-scope.

Preface

Introduce the reason for writing this article, and then briefly describe the context of this article

  • First of all, I will combine the todo-list example on the document to briefly explain the use of slot-scope
  • Secondly, if you can use it but don’t understand when to use it, it doesn’t make much sense. Therefore, in the second part of this article, I will talk about my personal understanding of its usage scenarios.
  • Finally, when I read about slot-scope on the Internet, I saw some cases that I felt were not appropriate.

Example of official document slot-scope

Below are the two parent-child vue components, first explain what the two components do

  • The parent component just calls the child component
  • A todolist list is implemented inside the subcomponent

I suggest to understand the use of slot scope from the perspective of data flow. (First learn how to use it. For the time being, I don’t need to understand why it is used in this way. The usage scenario is the second part)

  • 1. The parent component passes the todos array to the child component
  • 2. The sub-component received the array data through props, there should be no problem here
  • 3. After the child component gets the array, v-for renders the list, and passes each todo object in the array to the parent component by means of <slot :todo="todo">
  • 4. The parent component accepts the todo object through slot-scope="slotProps", and then it can be used through slotProps.todo.xxx

So the flow of data has gone through

  • The parent component passes the todos array to the child component
  • The child component traverses the todos array and passes the todo object inside to the parent component

Okay, this is how to use slot-scope, it's as simple as that.

I posted all the code for your own research

The source code of the parent component, which is the caller

<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>

The sub-component source code, that is, the person who encapsulates the component

<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>

Personal understanding of slot-scope usage scenarios

Imagine a scene:

When you want to encapsulate a list component to a colleague, you need to use a scope slot (note that it is a list or a list-like component)

How to use this list component you developed?

Generally speaking, as the caller of the list component, your colleague first makes an ajax request and gets an array like this

    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
        }
      ]

Later, todso will be passed to the list component, so what does the list component do?

V-for will definitely help your colleagues render this array inside the list. Just like the table component in element-ui

The key to the problem is here

The loop of the list component occurs inside the component, so through v-for="todo in todos", the list component can easily get each todo, but it’s useless to get the data in the list. The list is just a peel. It doesn’t understand business logic

This data is your colleague's business data, so this data must be handed over to the caller of the component, that is, hand over the data to your colleague.

So how can you pass the todo data of each item?

You will find no way!

Whether you use $emit, vuex or localStorage, you can think about it, and you will find that there is no suitable time for you to pass todo.

So in order to cope with this scenario, the scope slot was invented, and the list component can pass todo out via <slot :todo="todo"></slot>

Your colleagues can get todo through slot-scope="slotsProps".

Answer a few questions. In fact, if you understand the above questions, you should be able to answer the following questions. This is also my question

Question 1: Generally, don't we pass parameters to call components? Why does the component still pass data back?

的确,调用ui组件时一般是我们传递配置参数给他们。

但是就像elemnt-ui的table组件,你把数组传递给table后,是不是有时候需要拿到某一行的row对象

并根据row对象里的字段,来判断一些内容的显示隐藏?

因为循环的过程发生在table组件内部,所以table组件可以方便的获取到每一项数据,但是这些数据最终不是给组件的,而是我们自己要用的业务数据。所以也需要一个方式,让调用者能拿到自己想要的数据
Question 2: Since the child component will eventually return the data I gave him and then return it to me, why did I give it back then, can I just play in the parent component?
如果你不把数据给子组件当然可以。但是就等于抛弃掉了子组件的封装,只能你直接在父组件自己写一个列表

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

但是咱不是为了封装后,可以复用嘛,总不能永远不用组件嘛
Question 3: Does the parent component need the data of the child component? Then there won't be $emit and vuex, why is there slot-scope?
$emit和vuex是数据传递的一种方法,但是你可以尝试用$emit和vuex把todo传递给父组件。

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

Some examples on the Internet that I personally think are inappropriate

I think several statements are inappropriate, and they also cause me some confusion

  • What is slot-scope? It is a way to pass the data of the child component to the parent component

This statement makes me think that slot-scope is the same thing as emit and vuex

  • In some examples, the data is defined in the hard-coded list component to show how to pass the data out

The inappropriateness of these examples is that I think that data should not be defined in subcomponents.

Because in the real usage scenario, the data of the child component comes from the parent component. The inside of the component should be kept pure.

Just like the table component in element-ui, certain data will not be defined inside the component and then passed to you.

The data of the table component comes from the caller, and then the table will pass the row of each row when the developer needs it.

Although these examples are not wrong, but I think it is not conducive to understanding slot-scope

Guess you like

Origin blog.csdn.net/sd19871122/article/details/108399726