组件(优化)

动态组件

keep-alive

当在这些组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题。

有时我们更希望那些标签的组件实例能够被在它们第一次被创建的时候缓存下来。为了解决这个问题,我们可以用一个 <keep-alive> 元素将其动态组件包裹起来。

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

** 切换tag时保存标签页状态

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

当组件在 <keep-alive> 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
  • max - 数字。最多可以缓存多少组件实例。
<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :exclude="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>
<keep-alive :max="10">
<component :is="view"></component>
</keep-alive>

异步组件

Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。

// 模拟异步组件
Vue.component('async-example', function (resolve, reject) {
// 向 `resolve` 回调传递组件定义
setTimeout(function () {
resolve({template: '<div>I am async!</div>'})
}, 1000)
})
// 结合webpack使用
Vue.component('async-webpack-example', function (resolve) {
// 这个特殊的 require 语法将会告诉 webpack自动将你的构建代码切割成多个包,这些包会通过 Ajax 请求加载
require(['./my-async-component'], resolve)
})
// 动态导入 --这个动态导入会返回一个 `Promise` 对象。
Vue.component('async-webpack-example',() => import('./my-async-component'))
new Vue({components: {'my-component': () => import('./my-async-component')}})

异步组件工厂函数

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

注意如果你希望在 Vue Router 的路由组件中使用上述语法的话,你必须使用 Vue Router 2.4.0+ 版本。

$root

在每个 new Vue 实例的子组件中,其根实例可以通过 $root property 进行访问。

所有的子组件都可以将这个实例作为一个全局 store 来访问或使用。

// Vue 根实例
new Vue({
data: {foo: 1},
computed: {
bar: function () { /* ... */ }
},
methods: {
baz: function () { /* ... */ }
}
})
this.$root.foo // 获取根组件的数据

$parent

$parent property 可以用来从一个子组件访问父组件的实例。

// 在层级嵌套组件里会失控。因此向任意更深层级的组件提供上下文信息时推荐依赖注入
var map = this.$parent.map || this.$parent.$parent.map

$refs

在 JavaScript 里直接访问一个子组件可以通过 ref 这个 attribute 为子组件赋予一个 ID 引用。

<base-input ref="usernameInput"></base-input>

现在在 JS 里可以通过 this.$refs.usernameInput引用这个组件

$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。

<div id="comp">
<base-input ref="usernameInput"></base-input>
</div>
<script>
Vue.component('base-input',template:`<input ref="input">`)
new Vue({
el:'#comp',
...
this.$refs.input.focus()
...
})
</script>

依赖注入 (provide & inject)

使用 $parent property 无法很好的扩展到更深层级的嵌套组件上。这也是依赖注入的用武之地,它用到了两个新的实例选项:provideinject

  • provide 选项允许我们指定我们想要提供给后代组件的数据/方法。
  • inject 选项允许接收指定的我们想要添加在这个实例上的 property。
    • from property 是在可用的注入内容中搜索用的 key
    • default property 是降级情况下使用的 value
provide: [object | ()=>object]
inject: Array<String>
// 父级组件提供 'getMap' provide: function () {
return {getMap: this.getMap}
} // 子组件注入 'getMap' inject: ['getMap']
// 用 from 来表示其源 property
const Child = {
inject: {
foo: {from: 'bar',default: () => [1, 2, 3]}
}
}

相比 $parent 来说,这个用法可以让我们在任意后代组件中访问 getMap,而不需要暴露整个 <google-map> 实例。

  • 祖先组件不需要知道哪些后代组件使用它提供的 property
  • 后代组件不需要知道被注入的 property 来自哪里

provideinject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

事件侦听器

  • 通过 $on(eventName, eventHandler) 侦听一个事件
  • 通过 $once(eventName, eventHandler) 一次性侦听一个事件
  • 通过 $off(eventName, eventHandler) 停止侦听一个事件
// 一次性将这个日期选择器附加到一个输入框上,它会被挂载到 DOM 上。
// Pikaday 是一个第三方日期选择器的库
mounted: function () {
this.picker = new Pikaday({field: this.$refs.input,format: 'YYYY-MM-DD'})
},
// 在组件被销毁之前,也销毁这个日期选择器。
beforeDestroy: function () {
this.picker.destroy()
}

上述的picker挂载到了Vue实例的data上,而实际我们 只需要在生命周期钩子函数上使用并销毁

一次侦听可以解决这样的问题,每个新的实例都程序化地在后期清理它自己。

mounted: function () {
var picker = new Pikaday({
field: this.$refs.input,
format: 'YYYY-MM-DD'
})
this.$once('hook:beforeDestroy', function () {
picker.destroy()
})
}
// 封装picker,每个picker在实例销毁之前销毁自身
mounted: function () {
this.attachDatepicker('startDateInput');
this.attachDatepicker('endDateInput')},
methods: {attachDatepicker: function (refName) {
var picker = new Pikaday({
field: this.$refs[refName],
format: 'YYYY-MM-DD'
})
this.$once('hook:beforeDestroy', function () {picker.destroy()})
}
}

递归组件

组件是可以在它们自己的模板中调用自身的。不过它们只能通过 name 选项来做这件事

// 使用一个最终会得到 false 的 v-if
Vue.component('stack', {
template: '<div><stack v-if="done"></stack></div>'
})

组件间的循环引用

如果你使用一个模块系统依赖/导入组件,例如通过 webpack 或 Browserify,你会遇到一个错误

<!-- <tree-folder> 组件 -->
<p>
<span>{{ folder.name }}</span>
<tree-folder-contents :children="folder.children"/>
</p>
<!-- <tree-folder-contents> 组件 -->
<ul>
<li v-for="child in children"><tree-folder v-if="child.children" :folder="child"/>
<span v-else>{{ child.name }}</span>
</li>
</ul>
  • Vue.component 全局注册组件的时候,这些组件在渲染树中互为对方的后代和祖先。
  • 等到生命周期钩子 beforeCreate 时去注册它
    beforeCreate: function () {
    this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue').default}
  • 使用 webpack 的异步 import
    components: {TreeFolderContents: () => import('./tree-folder-contents.vue')}

内联模板

当 inline-template 这个特殊的 attribute 出现在一个子组件上时,这个组件将会使用其里面的内容作为模板,而不是将其作为被分发的内容。

<my-component inline-template>
<div>
<p>These are compiled as the component's own template.</p>
</div>
</my-component>

内联模板需要定义在 Vue 所属的 DOM 元素内。

X-Template

在一个 <script> 元素中,并为其带上 text/x-template 的类型,然后通过一个 id 将模板引用过去。

<script type="text/x-template" id="hello-world-template">
<p>Hello world</p>
</script>
<script>
Vue.component('hello-world', {template: '#hello-world-template'})
</script>

x-template 需要定义在 Vue 所属的 DOM 元素外。

强制更新

$forceUpdate :迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

v-once

有的时候你可能有一个组件,这个组件包含了大量静态内容。在这种情况下,你可以在根元素上添加 v-once attribute 以确保这些内容只计算一次然后缓存起来。

Vue.component('terms-of-service', {
template: `<div v-once><h1>Terms of Service</h1>... a lot of static content ...</div>`
})

可能导致无法正确更新。

VUE学习-优化组件的更多相关文章

  1. vue学习之组件

    组件从注册方式分为全局组件和局部组件. 从功能类型又可以分为偏视图表现的(presentational)和偏逻辑的(动态生成dom),推荐在前者中使用模板,在后者中使用 JSX 或渲染函数动态生成组件 ...

  2. vue学习之四组件系统

    vue.js既然是框架,那就不能只是简单的完成数据模板引擎的任务,它还提供了页面布局的功能.本文详细介绍使用vue.js进行页面布局的强大工具,vue.js组件系统. 一.Vue.js组件系统 每一个 ...

  3. Vue学习之--------组件的基本使用(非单文件组件)(代码实现)(2022/7/22)

    文章目录 1.为啥要使用组件 2.基本使用 3.代码实例 4.测试效果 5.注意点 1.为啥要使用组件 好用啊.像堆积木一样 2.基本使用 Vue中使用组件的三大步骤: 一.定义组件(创建组件) 二. ...

  4. vue学习笔记——组件的优化

    Vue 应用性能优化指南 1 给组件定义name,然后在同级目录新建index文件: import Count from './count.vue' export Count; 2 优化大数据的列表 ...

  5. Vue 学习笔记 — 组件初始化

    简书 在vue中有3个概念很容易搞混,data,computed,props,特别是我们这些原后端开发人员. new Vue({ el: "#x", data: { id: 1 } ...

  6. Vue学习之组件切换及父子组件小结(八)

    一.组件切换: 1.v-if与v-else方式: <!DOCTYPE html> <html lang="en"> <head> <met ...

  7. Vue学习笔记-组件通信-子传父(自定义事件)

    props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中.我们应该如何处理呢?这个时候,我们需要使用自定义事件来完成.什么时候需要自定义事件呢?当子组件需要向父组件传递 ...

  8. Vue学习之--------组件嵌套以及VueComponent的讲解(代码实现)(2022/7/23)

    欢迎加入刚建立的社区:http://t.csdn.cn/Q52km 加入社区的好处: 1.专栏更加明确.便于学习 2.覆盖的知识点更多.便于发散学习 3.大家共同学习进步 3.不定时的发现金红包(不多 ...

  9. 40.VUE学习之--组件之间的数据传参父组件向子组件里传参,props的使用实例操作

    父组件向子组件里传参,props的使用实例 <!DOCTYPE html> <html> <head> <meta charset="utf-8&q ...

  10. 43.VUE学习之--组件之使用.sync修饰符与computed计算属性超简单的实现美团购物车原理

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. [OpenCV实战]14 使用OpenCV实现单目标跟踪

    目录 1 背景 1.1 什么是目标跟踪 1.2 跟踪与检测 2 OpenCV的目标跟踪函数 2.1 函数调用 2.2 函数详解 2.3 综合评价 3 参考 在本教程中,我们将了解OpenCV 3中引入 ...

  2. Java基础篇——集合框架

    集合--对象的容器 集合与数组相似,不同的是,集合的长度可变并且只能组合引用类型数据,如果要组合基本类型,则需要装箱成包装类 Collection体系集合 Collection父接口 Collecti ...

  3. Java 进阶P-4.6+P-4.7

    向上造型 造型cast 子类的对象可以赋值给父类的变量 注意! java中不存在对象对对象的赋值!! 父类的对象不能赋值给子类的变量 可以用造型: c=(Car) v; (只有当v这个变量实际管理的是 ...

  4. ffmpeg拉取rtsp视频流

    公司项目需要提供实时显示网络摄像头实时视频. void RTSPFFmpeg::rtsp_open(const char *url) { AVFormatContext* format_ctx = a ...

  5. 【Oculus Interaction SDK】(一)设置 VR 相机与控制器 && 实现简单的抓取功能

    前言 前段时间 Oculus 的 SDK 频繁更新,很多已有的教程都不再适用于现在的版本了.本系列文章的主要目的是记录现版本常见功能的实现方法,便于自己后续开发.当然,不排除我文章刚写完 SDK 又变 ...

  6. 《Terraform 101 从入门到实践》 第五章 HCL语法

    <Terraform 101 从入门到实践>这本小册在南瓜慢说官方网站和GitHub两个地方同步更新,书中的示例代码也是放在GitHub上,方便大家参考查看. 介绍了Terraform一些 ...

  7. IDEA 2022 开启热部署

    POM.XML <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  8. 二分查找 & 移除元素

    一.二分查找 704.二分查找 leetcode链接 1.二分查找方法概述 二分查找是针对有序数组的一种查找方式.是利用(letf+right)/2 = mid的方式来对半缩短搜索范围的一种方法,一次 ...

  9. JS逆向实战11——某金属集团动态cookie加密

    本文来自:来自: https://www.cnblogs.com/zichliang/ 目标网站 aHR0cDovL3d3dy50bm1nLmNvbS5jbi9pbmZvcm1hdGlvbi9pbmZ ...

  10. bat脚本登陆ftp服务器

    用bat脚本登录ftp服务器,下载指定文件. 第一次脚本,有问题,你发现了么? 由于每个">>"重定向符号之前都习惯用空格(python style),导致写道ftp. ...