浅谈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方法和技巧大全
Dec 27 Javascript
jQuery中prevAll()方法用法实例
Jan 08 Javascript
node.js插件nodeclipse安装图文教程
Oct 19 Javascript
全面解析Node.js 8 重要功能和修复
Jun 02 Javascript
Angular.js中$resource高大上的数据交互详解
Jul 30 Javascript
vue 挂载路由到头部导航的方法
Nov 13 Javascript
Vue CLI3 如何支持less的方法示例
Aug 29 Javascript
使用Vue做一个简单的todo应用的三种方式的示例代码
Oct 20 Javascript
angular6 利用 ngContentOutlet 实现组件位置交换(重排)
Nov 02 Javascript
移动端自适应flexible.js的使用方法(不用三大框架,仅写一个单html页面使用)推荐
Apr 02 Javascript
JavaScript实现美化滑块效果
May 17 Javascript
JS实现字体背景跑马灯
Jan 06 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初始化对象和析构函数的简单实例
2014/03/11 PHP
php实现天干地支计算器示例
2014/03/14 PHP
PHP判断远程图片是否存在的几种方法
2014/05/04 PHP
php用ini_get获取php.ini里变量值的方法
2015/03/04 PHP
php中array_column函数简单实现方法
2016/07/11 PHP
Laravel5.0+框架邮件发送功能实现方法图文与实例详解
2019/04/23 PHP
php实现推荐功能的简单实例
2019/09/29 PHP
javascript object array方法使用详解
2012/12/03 Javascript
高性能JavaScript 重排与重绘(2)
2015/08/11 Javascript
JavaScript实现显示函数调用堆栈的方法
2016/04/21 Javascript
Bootstrap中的Panel和Table全面解析
2016/06/13 Javascript
Jquery UI实现一次拖拽多个选中的元素操作
2020/12/01 Javascript
深入浅析Vue不同场景下组件间的数据交流
2017/08/15 Javascript
Jquery遍历筛选数组的几种方法和遍历解析json对象,Map()方法详解以及数组中查询某值是否存在
2019/01/18 jQuery
解析JS在获取当前月的最后一天遇到的坑
2019/08/30 Javascript
keep-alive不能缓存多层级路由菜单问题解决
2020/03/10 Javascript
浅谈javascript如何获取文件后缀名
2020/08/07 Javascript
Node.js利用Express实现用户注册登陆功能(推荐)
2020/10/26 Javascript
在antd Table中插入可编辑的单元格实例
2020/10/28 Javascript
vue如何使用rem适配
2021/02/06 Vue.js
python实现绘制树枝简单示例
2014/07/24 Python
Python标准库之sqlite3使用实例
2014/11/25 Python
pytorch中tensor的合并与截取方法
2018/07/26 Python
Python CVXOPT模块安装及使用解析
2019/08/01 Python
python 已知一个字符,在一个list中找出近似值或相似值实现模糊匹配
2020/02/29 Python
总结30个CSS3选择器
2017/04/13 HTML / CSS
英国儿童家具专卖店:GLTC
2016/09/24 全球购物
简单介绍Object类的功能、常用方法
2013/10/02 面试题
五年级学生评语
2014/04/22 职场文书
我的中国梦演讲稿高中篇
2014/08/19 职场文书
公司向个人借款协议书范本
2014/10/09 职场文书
2015年医院创卫工作总结
2015/04/22 职场文书
怎样评估创业计划书是否有可行性?
2019/08/07 职场文书
创业计划书之熟食店
2019/10/16 职场文书
WCG2010 星际争霸决赛 Flash vs Goojila 1 星际经典比赛回顾
2022/04/01 星际争霸
Python各协议下socket黏包问题原理
2022/04/12 Python