[译] 我最终是怎么玩转了 Vue 的做用域插槽

Vue 是一个用于构建 Web 应用程序的前端框架,其设计方式使得开发人员能够很是快速地提升工做效率。该框架的各个方面都有不少资料,它的社区也天天都在不断成长。若是你读到了这篇文章,那么这些事儿你极可能已经知道咯。前端

虽然咱们能够快速直接地启动并运行它,可是框架里面那些更复杂和更强大的地方仍是须要好好动动脑子才能理解(至少对我是这样)。其中一个是插槽,还有另外一个与之相关但功能上不太相同的就是做用域插槽。我学习的时候花了好一阵才理解插槽工做的机制,因此我以为将我对插槽的理解分享出来是有价值的,由于这没准会帮助到你们。vue

插槽和具名插槽

父组件以另一种方式(不是经过常规的 Props 属性传递机制)向子组件传递信息。我发现把这种方法同常规的 HTML 元素联系起来颇有帮助。android

好比说 HTML 标签。ios

<a href=”/sometarget">This is a link</a> 复制代码

若是这是在 Vue 环境中而且<a>是你的组件,那么你须要发送“This is a link”信息到‘a’组件里面,而后它将被渲染成为一个超连接,而“This is a link”就是这个连接的文本。git

让咱们定义一个子组件来展现它的机制是怎样的:github

<template>  
  <div>  
    <slot></slot>  
  </div>  
</template>
复制代码

而后在父组件咱们这么作:后端

<template>  
  <div>  
    <child-component>This is from outside</child-component>  
  </div>  
</template>
复制代码

这时候屏幕上呈现的就应该和你预期的同样就是“This is from outside”,但这是由子组件所渲染出来的。bash

咱们还能够给子组件添加默认的信息,以避免到时候这里出现什么都没有传入的状况,就像这样子:前端框架

<template>  
  <div>  
    <slot>Some default message</slot>  
  </div>  
</template>
复制代码

而后若是咱们像这样子建立咱们的子组件:框架

<child-component>  
</child-component>
复制代码

咱们能够看到屏幕上会呈现“Some default message”。

具名插槽和常规插槽很是相似,惟一的差异就是你能够在你的目标组件多个位置传入你的文本。

咱们把子组件升级一下,让它有多个具名插槽

<template>  
  <div>  
    <slot>Some default message</slot>  
    <br/>  
    <slot name="top"></slot>  
    <br/>  
    <slot name="bottom"></slot>  
  </div>  
</template>
复制代码

这样,在咱们的子组件中就有了三个插槽。其中 top 和 bottom 插槽是具名插槽。

让咱们更新父组件以使用它。

<child-component v-slot:top>  
Hello there!  
</child-component>
复制代码

注意 —— 咱们在这里使用新的 Vue 2.6 语法来指定咱们想要定位的插槽:`v-slot:theName`。

你如今认为会在屏幕上看到什么呢?若是你说是“Hello Top!”,那么你就只说对了一部分。

由于我没有为没有具名的插槽赋予任何值,咱们所以也还会获得默认值。因此咱们真正会看到的是:

Some default message
Hello There!

其实真正意义上没有具名的插槽是被看成‘default’,因此你还能够这么作:

<child-component v-slot:default>  
Hello There!  
</child-component>
复制代码

如今咱们就只会看到:

Hello There!

由于咱们已经提供了值给默认(也就是未具名)插槽,所以具名插槽‘top’和‘bottom’也都没有默认值。

你发送的并不必定只是文本,还能够是其余组件或者 HTML。你能够发送任意你想展现的内容。

做用域插槽

我认为插槽和具名插槽相对简单,一旦你稍微玩玩就能够掌握。可另外一方面,做用域插槽虽然名字类似但又有些不一样之处。

我倾向于认为做用域插槽有点像一个放映机(或者是一个我欧洲朋友的投影仪)。如下是缘由。

子组件中的做用域插槽能够为父组件中的插槽的显示提供数据。这就像一我的带着放映机站在你的子组件里面,而后在父组件的墙上让一些图像发光。

这有一个例子。在子组件中咱们像这样设置了一个插槽:

<template>  
  <div>  
    <slot name="top" :myUser="user"></slot>  
    <br/>  
    <slot name="bottom"></slot>  
    <br/>  
  </div>  
</template>

<script>

data() {  
  return {  
    user: "Ross"  
  }  
}

</script>
复制代码

注意到咱们的具名插槽‘top’如今有了一个名为‘myUser’的属性,而后咱们绑定了一个动态的值在‘user’中。

在咱们的父组件中就像这样子设置子组件:

<div>  
   <child-component v-slot:top="slotProps">{{ slotProps }}</child-component>  
</div>
复制代码

咱们在屏幕上看到的就是这样子:

{ “myUser”: “Ross” }

仍是使用放映机的类比,咱们的子组件经过 myUser 对象将其用户字符串的值传递给父组件。它在父组件上投射到的墙就被称为‘slotProps’。

我知道这不是一个完美的类比,但当我第一次尝试理解这个机制的时候,它帮助我以这种方式思考。

Vue 的文档很是好,并且我也已经看到了一些其余关于做用域插槽工做机制的说明。但不少人采起的方法彷佛是将父组件中的全部或部分属性命名为与子组件相同,我认为这会使得数据很难被追踪。

在父组件中使用 ES6 解构,咱们这样子写还能够将特定 user 对象从插槽属性(你能够随便怎么称呼它)解脱出来:

<child-component v-slot:top="{myUser}">{{ myUser }}</child-component>
复制代码

或者甚至就只是在父组件中给它一个新的名字:

<child-component v-slot:top="{myUser: aFancyName}">{{ aFancyName }}</child-component>
复制代码

全部都是经过 ES6 解构,与 Vue 自己并无什么关系。

若是你正开始使用 Vue 和插槽,但愿这可让你起步并解决一些棘手的问题。

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索