浅谈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 相关文章推荐
动态改变textbox的宽高的js
Oct 26 Javascript
用最通俗易懂的代码帮助新手理解javascript闭包 推荐
Mar 01 Javascript
Jquery 表单验证类介绍与实例
Jun 09 Javascript
JavaScript继承基础讲解(原型链、借用构造函数、混合模式、原型式继承、寄生式继承、寄生组合式继承)
Aug 16 Javascript
JavaScript获取服务器端时间的方法
Nov 29 Javascript
jquery Form轻松实现文件上传
May 24 jQuery
微信小程序实现获取自己所处位置的经纬度坐标功能示例
Nov 30 Javascript
vue实现底部菜单功能
Jul 24 Javascript
在Layui 的表格模板中,实现layer父页面和子页面传值交互的方法
Sep 10 Javascript
使用JS location实现搜索框历史记录功能
Dec 23 Javascript
jquery.validate自定义验证用法实例分析【成功提示与择要提示】
Jun 06 jQuery
JavaScript实现前端网页版倒计时
Mar 24 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版(3)
2006/10/09 PHP
laravel5.1 ajax post 传值_token示例
2019/10/24 PHP
JS 页面内容搜索,类似于 Ctrl+F功能的实现代码
2007/08/13 Javascript
Tips 带三角可关闭的文字提示
2010/10/06 Javascript
js绑定事件this指向发生改变的问题解决方法
2013/04/23 Javascript
javascript预加载图片、css、js的方法示例介绍
2013/10/14 Javascript
js实现文字滚动效果
2016/03/03 Javascript
jQuery Ajax 加载数据时异步显示加载动画
2016/08/01 Javascript
原生js编写基于面向对象的分页组件
2016/12/05 Javascript
jQuery网页定位导航特效实现方法
2016/12/19 Javascript
微信小程序 网络请求(post请求,get请求)
2017/01/17 Javascript
angular 基于ng-messages的表单验证实例
2017/05/04 Javascript
echarts学习笔记之图表自适应问题详解
2017/11/22 Javascript
vue :src 文件路径错误问题的解决方法
2018/05/15 Javascript
antd vue 刷新保留当前页面路由,保留选中菜单,保留menu选中操作
2020/08/06 Javascript
[02:58]献给西雅图的情书_高清
2014/05/29 DOTA
Python实现查找系统盘中需要找的字符
2015/07/14 Python
python环形单链表的约瑟夫问题详解
2018/09/27 Python
pandas每次多Sheet写入文件的方法
2018/12/10 Python
使用python opencv对目录下图片进行去重的方法
2019/01/12 Python
Python3中函数参数传递方式实例详解
2019/05/05 Python
pycharm不能运行.py文件的解决方法
2020/02/12 Python
Python ckeditor富文本编辑器代码实例解析
2020/06/22 Python
浅析Python 责任链设计模式
2020/09/11 Python
深深扎根运动世界的生活品牌:Tillys
2017/10/30 全球购物
企业趣味活动方案
2014/08/21 职场文书
2014旅游局党组书记党建工作汇报材料
2014/11/02 职场文书
写给医生的感谢信
2015/01/22 职场文书
2015年清明节演讲稿范文
2015/03/17 职场文书
2015年电工工作总结
2015/04/10 职场文书
Pycharm连接远程服务器并远程调试的全过程
2021/06/24 Python
MybatisPlus EntityWrapper如何自定义SQL
2022/03/22 Java/Android
讲解MySQL增删改操作
2022/05/06 MySQL
python数据分析之单因素分析线性拟合及地理编码
2022/06/25 Python
python数字图像处理实现图像的形变与缩放
2022/06/28 Python
Sentry的安装、配置、使用教程(Sentry日志手机系统)
2022/07/23 Python