浅谈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 相关文章推荐
通过MSXML2自动获取QQ个人头像及在线情况(给初学者)
Jan 22 Javascript
javascript 尚未实现错误解决办法
Nov 27 Javascript
JavaScript Distilled 基础知识与函数
Apr 07 Javascript
JQuery中serialize()、serializeArray()和param()方法示例介绍
Jul 31 Javascript
sea.js常用的api简易文档
Nov 15 Javascript
Vue单页式应用(Hash模式下)实现微信分享的实例
Jul 21 Javascript
使用Vue做一个简单的todo应用的三种方式的示例代码
Oct 20 Javascript
在Express中提供静态文件的实现方法
Oct 17 Javascript
微信小程序使用 vant Dialog组件的正确方式
Feb 21 Javascript
基于openlayers实现角度测量功能
Sep 28 Javascript
vue 获取url里参数的两种方法小结
Nov 12 Javascript
JavaScript实现酷炫的鼠标拖尾特效
Feb 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程序--记数器
2006/10/09 PHP
实用函数2
2007/11/08 PHP
PHP生成UTF8文件的方法
2010/05/15 PHP
input file获得文件根目录简单实现
2013/04/26 PHP
php如何计算两坐标点之间的距离
2018/12/29 PHP
asp.net刷新本页面的六种方法总结
2014/01/07 Javascript
JavaScript函数定义的常见注意事项小结
2014/09/16 Javascript
谷歌浏览器调试JavaScript小技巧
2014/12/29 Javascript
js实现文字跟随鼠标移动而移动的方法
2015/02/28 Javascript
基于BootStrap Metronic开发框架经验小结【三】下拉列表Select2插件的使用
2016/05/12 Javascript
全面解析Bootstrap中form、navbar的使用方法
2016/05/30 Javascript
AngularJs定制样式插入到ueditor中的问题小结
2016/08/01 Javascript
BootStrap iCheck插件全选与获取value值的解决方法
2016/08/24 Javascript
jQuery Validate让普通按钮触发表单验证的方法
2016/12/15 Javascript
ionic3 懒加载
2017/08/16 Javascript
vue移动端监听滚动条高度的实现方法
2018/09/03 Javascript
小程序scroll-view组件实现滚动的示例代码
2018/09/20 Javascript
Vue+Webpack完美整合富文本编辑器TinyMce的方法
2018/11/30 Javascript
jquery-ui 进度条功能示例【测试可用】
2019/07/25 jQuery
vue基于Echarts的拖拽数据可视化功能实现
2020/12/04 Vue.js
[47:55]Ti4第二日主赛事败者组 NaVi vs EG 1
2014/07/20 DOTA
python判断windows隐藏文件的方法
2014/03/21 Python
CentOS6.5设置Django开发环境
2016/10/13 Python
Python3 模块、包调用&amp;路径详解
2017/10/25 Python
Python迭代器模块itertools使用原理解析
2019/12/11 Python
pandas中read_csv、rolling、expanding用法详解
2020/04/21 Python
欧洲最大的品牌水上运动服装和设备在线零售商:Wuituit Outlet
2018/05/05 全球购物
琳达·法罗眼镜英国官网:Linda Farrow英国
2021/01/19 全球购物
客服端调用EJB对象的几个基本步骤
2012/01/15 面试题
采购主管工作职责
2013/12/12 职场文书
房地产项目策划书
2014/02/05 职场文书
新农村建设标语
2014/06/24 职场文书
社团活动总结怎么写
2014/06/30 职场文书
小时代观后感
2015/06/10 职场文书
python实战之一步一步教你绘制小猪佩奇
2021/04/22 Python
SSM项目使用拦截器实现登录验证功能
2022/01/22 Java/Android