浅谈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 相关文章推荐
让您的菜单不离网站
Oct 03 Javascript
javascript下查找父节点的简单方法
Aug 13 Javascript
JS实现两个大数(整数)相乘
Apr 28 Javascript
微信小程序  生命周期详解
Oct 27 Javascript
最细致的vue.js基础语法 值得收藏!
Nov 03 Javascript
Bootstrap组件之下拉菜单,多级菜单及按钮布局方法实例
May 25 Javascript
详解有关easyUI的拖动操作中droppable,draggable用法例子
Jun 03 Javascript
AnglarJs中的上拉加载实现代码
Feb 08 Javascript
Swiper 4.x 使用方法(移动端网站的内容触摸滑动)
May 17 Javascript
JS正则表达式常见用法实例详解
Jun 19 Javascript
小程序云开发实现数据库异步操作同步化
May 18 Javascript
微信小程序自定义底部弹出框动画
Nov 18 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
php版微信公众平台接口参数调试实现判断用户行为的方法
2016/09/23 PHP
php操作access数据库的方法详解
2017/02/22 PHP
php 判断IP为有效IP地址的方法
2018/01/28 PHP
laravel实现一个上传图片的接口,并建立软链接,访问图片的方法
2019/10/12 PHP
WordPress 照片lightbox效果的运用几点
2009/06/22 Javascript
javascript的console.log()用法小结
2012/05/31 Javascript
给文字加上着重号的JS代码
2013/11/12 Javascript
JS,Jquery获取select,dropdownlist,checkbox下拉列表框的值(示例代码)
2014/01/11 Javascript
js设置文本框中焦点位置在最后的示例代码(简单实用)
2014/03/04 Javascript
jquery实现初次打开有动画效果的网页TAB切换代码
2015/09/06 Javascript
layui表格实现代码
2017/05/20 Javascript
React Native基础入门之调试React Native应用的一小步
2018/07/02 Javascript
Mint UI实现A-Z字母排序的城市选择列表
2018/12/28 Javascript
jQuery利用cookie 实现本地收藏功能(不重复无需多次命名)
2019/11/07 jQuery
JS Array.from()将伪数组转换成数组的方法示例
2020/03/23 Javascript
Python中字典和JSON互转操作实例
2015/01/19 Python
python实现反转部分单向链表
2018/09/27 Python
python opencv实现图像边缘检测
2019/04/29 Python
python之拟合的实现
2019/07/19 Python
python3.5 cv2 获取视频特定帧生成jpg图片
2019/08/28 Python
Ubuntu下Python+Flask分分钟搭建自己的服务器教程
2019/11/19 Python
python实现指定ip端口扫描方式
2019/12/17 Python
python json load json 数据后出现乱序的解决方案
2020/02/27 Python
5分钟快速掌握Python定时任务框架的实现
2021/01/26 Python
.NET程序员的数据库面试题
2012/10/10 面试题
办护照工作证明范本
2014/01/14 职场文书
大学毕业感言200字
2014/03/09 职场文书
旅游与酒店管理专业求职信
2014/07/21 职场文书
庆六一文艺汇演活动方案
2014/08/26 职场文书
庆元旦演讲稿
2014/09/15 职场文书
计划生育证明书写要求
2014/09/17 职场文书
运动会5000米加油稿
2015/07/21 职场文书
导游词之山西关帝庙
2019/11/01 职场文书
一文弄懂MySQL中redo log与binlog的区别
2022/02/15 MySQL
【D4DJ】美少女DJ企划 动画将于明年冬季开播第2季
2022/04/11 日漫
Linux中各个目录的作用与内容
2022/06/28 Servers