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

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

插槽和具名插槽

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

比如说 HTML 标签。

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

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

让我们定义一个子组件来展示它的机制是怎样的:

  1. <template>
  2. <div>
  3. <slot></slot>
  4. </div>
  5. </template>
  6. 复制代码

然后在父组件我们这么做:

  1. <template>
  2. <div>
  3. <child-component>This is from outside</child-component>
  4. </div>
  5. </template>
  6. 复制代码

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

我们还可以给子组件添加默认的信息,以免到时候这里出现什么都没有传入的情况,就像这样子:

  1. <template>
  2. <div>
  3. <slot>Some default message</slot>
  4. </div>
  5. </template>
  6. 复制代码

然后如果我们像这样子创建我们的子组件:

  1. <child-component>
  2. </child-component>
  3. 复制代码

我们可以看到屏幕上会呈现“Some default message”。

具名插槽和常规插槽非常类似,唯一的差别就是你可以在你的目标组件多个位置传入你的文本。

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

  1. <template>
  2. <div>
  3. <slot>Some default message</slot>
  4. <br/>
  5. <slot name="top"></slot>
  6. <br/>
  7. <slot name="bottom"></slot>
  8. </div>
  9. </template>
  10. 复制代码

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

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

  1. <child-component v-slot:top>
  2. Hello there!
  3. </child-component>
  4. 复制代码

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

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

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

Some default message
Hello There!

其实真正意义上没有具名的插槽是被当作‘default’,所以你还可以这么做:

  1. <child-component v-slot:default>
  2. Hello There!
  3. </child-component>
  4. 复制代码

现在我们就只会看到:

Hello There!

因为我们已经提供了值给默认(也就是未具名)插槽,因此具名插槽‘top’和‘bottom’也都没有默认值。

你发送的并不一定只是文本,还可以是其他组件或者 HTML。你可以发送任意你想展示的内容。

作用域插槽

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

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

子组件中的作用域插槽可以为父组件中的插槽的显示提供数据。这就像一个人带着放映机站在你的子组件里面,然后在父组件的墙上让一些图像发光。

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

  1. <template>
  2. <div>
  3. <slot name="top" :myUser="user"></slot>
  4. <br/>
  5. <slot name="bottom"></slot>
  6. <br/>
  7. </div>
  8. </template>
  9. <script>
  10. data() {
  11. return {
  12. user: "Ross"
  13. }
  14. }
  15. </script>
  16. 复制代码

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

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

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

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

{ “myUser”: “Ross” }

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

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

Vue 的文档非常好,而且我也已经看到了一些其他关于作用域插槽工作机制的说明。但很多人采取的方法似乎是将父组件中的所有或部分属性命名为与子组件相同,我认为这会使得数据很难被追踪。

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

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

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

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

所有都是通过 ES6 解构,与 Vue 本身并没有什么关系。

如果你正开始使用 Vue 和插槽,希望这可以让你起步并解决一些棘手的问题。

[译] 我最终是怎么玩转了 Vue 的作用域插槽的更多相关文章

  1. 每日一译系列-模块化css怎么玩(译文)

    原文链接:How Css Modules Work 原文作者是Preact的作者 这是一篇关于如何使用Css Modules的快速介绍,使用到的工具是Webpack吊炸的css-loader 首先,我 ...

  2. [译] 2017 年比较 Angular、React、Vue 三剑客

    原文地址:Angular vs. React vs. Vue: A 2017 comparison 原文作者:Jens Neuhaus 译文出自:掘金翻译计划 本文永久链接:github.com/xi ...

  3. 【半译】在ASP.NET Core中创建内部使用作用域服务的Quartz.NET宿主服务

    在我的上一篇文章中,我展示了如何使用ASP.NET Core创建Quartz.NET托管服务并使用它来按计划运行后台任务.不幸的是,由于Quartz.NET API的工作方式,在Quartz作业中使用 ...

  4. vue邪道玩法 : 把vue实例存在别的地方,以及可能会遇到的问题

    一般来说,VUE项目中,this指向VUE实例. 但有的时候,某些代码会改变this的指向. 这时,可以用一个临时变量存储VUE实例. test1(){ var _this = this // 把vu ...

  5. 一起学习vue源码 - Vue2.x的生命周期(初始化阶段)

    作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...

  6. 你还不知道Vue的生命周期吗?带你从Vue源码了解Vue2.x的生命周期(初始化阶段)

    作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...

  7. 适合码农工作时玩的游戏:Scrum

    适合码农工作时玩的游戏:Scrum 昨天遇到一个来自微软的面试者,在面试的最后,我简单介绍了一下我们团队使用一周一次的 Scrum 来做项目管理.他回答说:” 我在微软也用 Scrum,不过我们一周两 ...

  8. [Vue 牛刀小试]:第十七章 - 优化 Vue CLI 3 构建的前端项目模板(1)- 基础项目模板介绍

    一.前言 在上一章中,我们开始通过 Vue CLI 去搭建属于自己的前端 Vue 项目模板,就像我们 .NET 程序员在使用 asp.net core 时一样,我们更多的会在框架基础上按照自己的开发习 ...

  9. Vue基础项目模板

    https://github.com/wanglong/vue-element-admin.git 优化 Vue CLI 3 构建的前端项目模板(1)- 基础项目模板介绍 一站式开源运维平台,分享给大 ...

随机推荐

  1. [JZOJ 5888] [NOIP2018模拟9.29] GCD生成树 解题报告 (最大生成树+公约数)

    题目链接: http://172.16.0.132/senior/#main/show/5888 题目: 题解: 思路是这样的:两个数的最大公约数一定不会比这两个数的任意一个数大.因此我们把权值相等的 ...

  2. keepalived+双主架构部署

    在高可用集群环境中,keepalived使用的是VIP,利用keepalived自带的服务监控功能和自定义脚本来实现MYSQL故障时自带切换. Keepalived基于VRRP协议,虚拟冗余路由协议, ...

  3. 创建ios界面的三步骤

    1.加载数据 (包括懒加载和字典转模型等) 2.搭建界面 (常见的有九宫格算法和for循环的嵌套等) 3.实现用户交互 (通常用按钮实现)

  4. sql中计算百分比

    sql中计算百分比:(转成字符串然后拼接%) ),) AS CHAR),'%') as aa from act_canal; 效果:

  5. HD-ACM算法专攻系列(4)——A == B ?

    题目描述: 源码: /**/ #include"iostream" #include"string" using namespace std; string S ...

  6. (转载) Android开发mac /dev/kvm is not found

    Android开发mac /dev/kvm is not found 标签: KVMAndroid开发KVM is not found芒果Android芒果iOS 2016-10-29 16:31 2 ...

  7. Codeforces 986B. Petr and Permutations(没想到这道2250分的题这么简单,早知道就先做了)

    这题真的只能靠直觉了,我没法给出详细证明. 解题思路: 1.交换3n次或者7n+1次,一定会出现一个为奇数,另一个为偶数. 2.用最朴素的方法,将n个数字归位,计算交换次数. 3.判断交换次数是否与3 ...

  8. String值传递剖析

    转载自 http://www.iteye.com/topic/412531 提要:本文从实现原理的角度上阐述和剖析了:在Java语言中,以String作为类型的变量在作为方法参数时所表现出的“非对象” ...

  9. 洛谷1345 [Usaco5.4]奶牛的电信

    题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相 ...

  10. linux SVN服务器创建版本库

    1.安装svn服务 # yuminstall subversion 2.新建一个目录用于存储SVN所有文件    # mkdir /home/svn 3.在上面创建的文件夹中为项目 project_1 ...