如何使用Vue中的嵌套插槽(包括做用域插槽)

做者:Michael Thiessen
译者:前端小智
来源:medium
点赞再看,养成习惯

本文 GitHub https://github.com/qq44924588... 上已经收录,更多往期高赞文章的分类,也整理了不少个人文档,和教程资料。欢迎Star和完善,你们面试能够参照考点复习,但愿咱们一块儿有点东西。前端

最近我弄清楚了如何递归地实现嵌套插槽,包括如何使用做用域插槽来实现。原由是我想看看是否能够构建一个复制v-for指令但仅使用template组件。vue

它还支持插槽和做用域插槽,也能够支持命名插槽,咱们能够这样使用它:git

<template>
  <div>
    <!-- Regular list -->
    <v-for :list="list" />
    
    <!-- List with bolded items -->
    <v-for :list="list">
      <template v-slot="{ item }">
        <strong>{{ item }}</strong>
      </template>
    </v-for>
  </div>
</template>

第一个将正常打印列表,而第二个将每一个项包装在<strong>标记中。github

这不是一个很是有用的组件,但能够从中学到的最多,咱们来看看。面试

无循环实现循环

一般,当咱们要渲染元素或组件的列表时,可使用v-for指令,但此次咱们但愿彻底摆脱它。编程

那么,咱们如何在不使用循环的状况下渲染项目列表呢?就是使用 递归数组

咱们可使用递归来渲染项目列表。过程并不会复杂,咱们来看看怎么作。微信

递归表示一个列表

我在大学里最喜欢的课程之一是“编程语言概念”编程语言

对我来讲,最有趣的部分是探索函数式编程和逻辑编程,并了解与命令式编程的区别(Javascript 和最流行的语言是命令式编程)。函数式编程

这门课让我真正了解如何使用递归,由于在纯函数语言中,一切都是递归。无论怎样,从那门课我学到了可使用递归地表示一个列表。

与使用数组不一样,每一个列表是一个值(头)和另外一个列表(尾)。

[head, tail]

例如要表示列表[一、二、3],则能够递归方式表示为:

[1, [2, [3, null]]]

咱们必须以某种方式结束列表,所以咱们使用null而不是另外一个数组(也可使用空数组)。

看到这里,你或许就能够明白了,咱们可使用此概念并将其应用于咱们的组件。 相反,咱们将递归嵌套组件以表示列表。

咱们最终将渲染出这样的内容。 注意咱们“list”的嵌套结构:

<div>
  1
  <div>
    2
    <div>
      3
    </div>
  </div>
</div>

诚然,这与v-for渲染的效果并不彻底相同,但这也不是本练习的重点。

构建组件

首先,咱们将解决递归渲染项目列表的问题。

使用递归来渲染列表

此次咱们使用一个普通数组,而不是使用前面介绍的递归列表:

[1, 2, 3]

这里要讨论两种状况:

  • 基本情形-渲染列表中的第一项
  • 递归情形-渲染项目,而后沉浸下一个列表

咱们把[1,2,3]传给v-for

<template>
  <v-for :list="[1, 2, 3]" />
</template>

咱们但愿获取列表中的第一项,即1,并显示它

<template>
  <div>
    {{ list[0] }}
  </div>
</template>

如今,该组件将渲染1,就像咱们指望的那样。

可是咱们不能只渲染第一个值并中止。 咱们须要渲染值,而后还渲染列表的其他部分:

<template>
  <div>
    {{ list[0] }}
    <v-for :list="list.slice(1)" />
  </div>
</template>

咱们不传递整个list数组,而是删除第一项并传递新数组。第一个项目咱们已经打印出来了,因此没有必要保留它。

顺序是这样的:

  1. 咱们将[1,2,3]传递到v-for中进行渲染
  2. 咱们的v-for组件渲染1,而后将[2,3]传递到下一个v-for进行渲染
  3. [2,3]并渲染2,而后将[3]传递到下一个v-for
  4. 最后一个v-for组件渲染出3,咱们已经打印出列表!

如今,咱们的Vue应用程序的结构以下所示:

<App>
  <v-for>
    <v-for>
      <v-for />
    </v-for>
  </v-for>
</App>

能够看到,咱们有几个v-for组件,它们彼此嵌套在一块儿。最后一件事,咱们须要中止递归

<template>
  <div>
    {{ list[0] }}
    <v-for
      v-if="list.length > 1"
      :list="list.slice(1)"
    />
  </div>
</template>

最终,渲染完全部项后,咱们须要中止递归操做。

递归嵌套的插槽

如今,组件能够正常工做,可是咱们也但愿它与做用域内插槽一块儿使用,由于这样能够自定义渲染每一个项的方式:

<template>
  <v-for :list="list">
    <template v-slot="{ item }">
      <strong>{{ item }}</strong>
    </template>
  </v-for>
</template>

嵌套插槽

一旦弄清楚了如何递归地嵌套插槽,就会对它痴迷同样的感叹:

  • 嵌套n级的插槽
  • 递归插槽
  • 包装组件将一个插槽转换为多个插槽

首先,咱们将简要介绍嵌套插槽的工做方式,而后介绍如何将它们合并到v-for组件中。

假设咱们有三个组件:ParentChildGrandchild。咱们但愿传递来自Parent组件的一些内容,并在Grandchild组件中渲染它。

Parent开始,咱们传递一些内容:

// Parent.vue
<template>
  <Child>
    <span>Never gonna give you up</span>
  </Child>
</template>

咱们在Child组件中作一些事情,将在稍后介绍。 而后咱们的Grandchild组件获取插槽并渲染内容:

// Grandchild.vue
<template>
  <div>
    <slot />
  </div>
</template>

那么,这个Child组件是什么样的?

咱们须要它从Parent组件获取内容并将其提供给Grandchild组件,所以咱们将两个不一样的插槽链接在一块儿。

// Child.vue
<template>
  <Grandchild>
    <slot />
  </Grandchild>
</template>

请记住,<slot />元素渲染出做为插槽传递到组件的内容。 所以,咱们将从“Parent”中获取该内容,而后将其渲染到“Grandchild”插槽中。

添加做用域插槽

与嵌套做用域插槽惟一不一样的是,咱们还必须传递做用域数据。将其添加到v-for中,咱们如今获得如下信息:

<template>
  <div>
    <slot v-bind:item="list[0]">
      <!-- Default -->
      {{ list[0] }}
    </slot>
    <v-for
      v-if="list.length > 1"
      :list="list.slice(1)"
    >
      <!-- Recursively pass down scoped slot -->
      <template v-slot="{ item }">
        <slot v-bind:item="item" />
      </template>
    </v-for>
  </div>
</template>

首先让咱们看一下基本状况。

若是没有提供插槽,则默认<slot>元素内部的内容,并像之前同样渲染list[0]。 可是若是咱们提供了一个slot,它会将其渲染出来,并经过slot做用域将列表项传递给父组件。

这里的递归状况相似。 若是咱们将插槽传递给v-for,它将在下一个v-for的插槽中进行渲染,所以咱们获得了嵌套。 它还从做用域槽中获取item并将其传递回链。

如今,咱们这个组件仅使用template就能实现 v-for效果。

总结

咱们作了不少事情,终于了解了如何建立一个仅使用 template 就能实现v-for的效果。

本文主要内容:

  • 递归地表示列表
  • 递归组件
  • 嵌套槽和嵌套做用域槽

原文:https://stackoverflow.com/que...

代码部署后可能存在的BUG无法实时知道,过后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给你们推荐一个好用的BUG监控工具 Fundebug


交流

文章每周持续更新,能够微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了不少个人文档,欢迎Star和完善,你们面试能够参照考点复习,另外关注公众号,后台回复福利,便可看到福利,你懂的。

相关文章
相关标签/搜索