浅谈Vue.js组件(二)


Posted in Javascript onApril 09, 2019

插槽(Slot)

定义一个名child子组件,为该子组件添加内容应该在子组件的template中定义,直接在父组件的<child>标签中定义的内容不会被渲染。

在子组件中通过加入<slot>元素占位,便能够渲染父组件中子组件标签中的内容了。

插槽内容

  1. 任何模版代码
  2. HTML代码
  3. 其他组件

插槽可以有默认内容,当在父组件中没有提供内容的时候,来进行显示。

<!-- submit-button -->
<button type="submit">
 <slot>Submit</slot>
</button>


1.
<submit-button></submit-button>
⬇️ 
<button type="submit">
 Submit
</button>

2.
<submit-button>
 Save
</submit-button>
⬇️
<button type="submit">
 Save
</button>

作用域

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

具名插槽

试想,我们有一个带有如下模版的<base-layout>组件

<div class="container">
 <header>
 <!-- 我们希望把页头放这里 -->
 </header>
 <main>
 <!-- 我们希望把主要内容放这里 -->
 </main>
 <footer>
 <!-- 我们希望把页脚放这里 -->
 </footer>
</div>

可以看到,在组件中显示的内容是划分不同的部位的,这个时候就需要使用到<slot>元素的一个特有的属性:name来实现了。这个特性可以用来定义额外的插槽。

<div class="container">
 <header>
 <slot name="header"></slot>
 </header>
 <main>
 <slot></slot>
 </main>
 <footer>
 <slot name="footer"></slot>
 </footer>
</div>

 一个不带 name 的 <slot> 出口会带有隐含的名字“default”。

在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:

<base-layout>
 <template v-slot:header>
 <h1>Here might be a page title</h1>
 </template>

 <p>A paragraph for the main content.</p>
 <p>And another one.</p>

 <template v-slot:footer>
 <p>Here's some contact info</p>
 </template>
</base-layout>

现在 <template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。

当然,也可以将默认插槽的内容通过v-slot:default包裹起来。

v-slot 只能添加在一个 <template> 上

作用域插槽

当我们希望能够让插槽内容能够访问子组件中才有的数据时,我们可以将数据作为一个<slot>元素的特性绑定上去

<span>
 <slot v-bind:user="user">
 {{ user.name }}
 </slot>
</span>

绑定在<slot>元素上的特性被称为插槽prop。此时我们在父组件中通过给v-slot带一个值来定义我们提供的插槽prop的名字。

<current-user>
 <template v-slot:default="slotProps">
 {{ slotProps.user.age }}
 </template>
</current-user>

 独占默认插槽的缩写语法

当被提供的内容只有默认插槽时,上面的写法可以被简化来写

<!-- 简化版 -->
<current-user v-slot:default="slotProps">
 {{ slotProps.user.firstName }}
</current-user>

<!-- 终极简化版 -->
<current-user v-slot="slotProps">
 {{ slotProps.user.firstName }}
</current-user>

需要注意两点:

  1. 简化写法不能和具名插槽混用,作用域不明确
  2. 出现多个插槽时,所有插槽都使用完整的基于<template>语法

解构插槽Prop

作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里:

function (slotProps) {
 // 插槽内容
}

这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。所以在支持的环境下 (单文件组件或现代浏览器),你也可以使用 ES2015 解构来传入具体的插槽 prop,如下:

<current-user v-slot:default="slotProps">
 {{ slotProps.user.firstName }}
</current-user>
⬇️
<current-user v-slot="{ user }">
 {{ user.firstName }}
</current-user>

使用场景举例

插槽 prop 允许我们将插槽转换为可复用的模板,这些模板可以基于输入的 prop 渲染出不同的内容。

这在设计封装数据逻辑同时允许父级组件自定义部分布局的可复用组件时是最有用的。

动态插槽名

动态指令参数也可以用在 v-slot 上,来定义动态的插槽名

<base-layout>
 <template v-slot:[dynamicSlotName]>
 ...
 </template>
</base-layout>

具名插槽缩写

v-slot可以缩写为#。

缩写方式只有在有参数的时候才可以使用

<!-- 这样会触发一个警告 -->
<current-user #="{ user }">
 {{ user.firstName }}
</current-user>

<!-- 这样是正确的 -->
<current-user #default="{ user }">
 {{ user.firstName }}
</current-user>

动态组件&keep-alive

当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题。为了解决这个问题,我们可以用一个<keep-alive>元素将动态组件包裹起来

<!-- 失活的组件将会被缓存!-->
<keep-alive>
 <component v-bind:is="currentTabComponent"></component>
</keep-alive>

注意这个 <keep-alive> 要求被切换到的组件都有自己的名字,不论是通过组件的 name 选项还是局部/全局注册。

更加详细的说明在我们之后的实战过程中遇到的话,再进行专门解说。

异步组件

在实际的项目过程中,我们往往会将一系列的功能分割成一个个小的代码块,希望只有在需要的时候才去加载。为了达成这个目的,Vue允许我们以一个工厂函数的方式定义我们的组件,这个工厂函数会异步解析组件的定义。

Vue只有在这个组件需要渲染的时候才会触发这个工厂函数,而且会把结果缓存起来供之后使用。

Vue.component('async-example', function (resolve, reject) {
 setTimeout(function () {
 // 向 `resolve` 回调传递组件定义
 resolve({
  template: '<div>I am async!</div>'
 })
 }, 1000)
})

其实,这个过程有些类似于我们设计一个异步函数,这个工厂函数会收到一个resolve回调,这个回调在我们从服务器获取到组件定义的时候被调用,当加载失败的时候我们也可以调用reject(reason)。

一个推荐的做法是异步组件和webpack的code-splitting功能结合使用

Vue.component('async-webpack-example', function (resolve) {
 // 这个特殊的 `require` 语法将会告诉 webpack
 // 自动将你的构建代码切割成多个包,这些包
 // 会通过 Ajax 请求加载
 require(['./my-async-component'], resolve)
})

同样,也可以在工厂函数中返回一个Promise

Vue.component(
 'async-webpack-example',
 // 这个 `import` 函数会返回一个 `Promise` 对象。
 () => import('./my-async-component')
)

处理加载状态

上面的工厂函数可以返回一个下面格式的对象

const AsyncComponent = () => ({
 // 需要加载的组件 (应该是一个 `Promise` 对象)
 component: import('./MyComponent.vue'),
 // 异步组件加载时使用的组件
 loading: LoadingComponent,
 // 加载失败时使用的组件
 error: ErrorComponent,
 // 展示加载时组件的延时时间。默认值是 200 (毫秒)
 delay: 200,
 // 如果提供了超时时间且组件加载也超时了,
 // 则使用加载失败时使用的组件。默认值是:`Infinity`
 timeout: 3000
})

小结
本篇我们主要围绕着Vue组件中的插槽和相关动态组件、异步组件的内容进行了梳理。通过这两篇的整理,我们对于Vue组件有了一个比较整体的了解。后续我们会在实战过程中针对具体的点再进行详细的说明。

以上所述是小编给大家介绍的Vue.js组件详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript 密码强弱度检测万能插件
Feb 25 Javascript
Struts2的s:radio标签使用及用jquery添加change事件
Apr 08 Javascript
如何获取select下拉框的值(option没有及有value属性)
Nov 08 Javascript
js实现div闪烁原理及实现代码
Jun 24 Javascript
异步加载JS、CSS代码(推荐)
Jun 15 Javascript
用原生js统计文本行数的简单示例
Aug 19 Javascript
微信小程序 icon组件详细及实例代码
Oct 25 Javascript
express默认日志组件morgan的方法
Apr 05 Javascript
基于jQuery.i18n实现web前端的国际化
May 04 jQuery
JavaScript实现构造json数组的方法分析
Aug 17 Javascript
koa socket即时通讯的示例代码
Sep 07 Javascript
javascript实现放大镜功能
Dec 09 Javascript
4 种滚动吸顶实现方式的比较
Apr 09 #Javascript
vue响应式系统之observe、watcher、dep的源码解析
Apr 09 #Javascript
浅谈发布订阅模式与观察者模式
Apr 09 #Javascript
vue使用keep-alive保持滚动条位置的实现方法
Apr 09 #Javascript
浅谈JavaScript闭包
Apr 09 #Javascript
使用Three.js实现太阳系八大行星的自转公转示例代码
Apr 09 #Javascript
webpack4实现不同的导出类型
Apr 09 #Javascript
You might like
高分R级DC动画剧《哈莉·奎茵》第二季正式预告首发
2020/04/09 欧美动漫
PHP获取网站域名和地址的代码
2008/08/17 PHP
PHP的邮件群发系统phplist配置方法详细总结
2016/03/30 PHP
php中foreach结合curl实现多线程的方法分析
2016/09/22 PHP
php7 错误处理机制修改实例分析
2020/05/25 PHP
JS替换文本域内的回车示例
2014/02/18 Javascript
Javascript添加监听与删除监听用法详解
2014/12/19 Javascript
JavaScript实现横向滑出的多级菜单效果
2015/10/09 Javascript
js实现正则匹配中文标点符号的方法
2015/12/23 Javascript
jQuery调用Webservice传递json数组的方法
2016/08/06 Javascript
JS实现六位字符密码输入器功能
2016/08/19 Javascript
Javascript中的prototype与继承
2017/02/06 Javascript
canvas实现图片根据滑块放大缩小效果
2017/02/24 Javascript
微信小程序手机号码验证功能的实例代码
2018/08/28 Javascript
每周一练 之 数据结构与算法(Stack)
2019/04/16 Javascript
vue实现随机验证码功能的实例代码
2019/04/30 Javascript
vue flex 布局实现div均分自动换行的示例代码
2020/08/05 Javascript
[01:16]DOTA2小知识课堂 Ep.03 芒果树无伤肉山
2019/12/05 DOTA
python使用os模块的os.walk遍历文件夹示例
2014/01/27 Python
python中pass语句用法实例分析
2015/04/30 Python
详解Python中最难理解的点-装饰器
2017/04/03 Python
解决python3 网络请求路径包含中文的问题
2018/05/10 Python
Python Multiprocessing多进程 使用tqdm显示进度条的实现
2019/08/13 Python
详解Python IO编程
2020/07/24 Python
澳大利亚儿童和婴儿产品在线商店:Lime Tree Kids
2017/10/05 全球购物
单位提档介绍信
2014/01/17 职场文书
2014年党务公开实施方案
2014/02/27 职场文书
新手上路标语
2014/06/20 职场文书
九寨沟导游词
2015/02/02 职场文书
初中教师个人工作总结
2015/02/10 职场文书
幼儿园教师节活动总结
2015/03/23 职场文书
公司中层管理培训心得体会
2016/01/11 职场文书
经典法律座右铭(50句)
2019/08/15 职场文书
晶体管单管来复再生式收音机
2021/04/22 无线电
springboot+VUE实现登录注册
2021/05/27 Vue.js
Redis sentinel哨兵集群的实现步骤
2022/07/15 Redis