组件(优化)

动态组件

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. [常用工具] 深度学习Caffe处理工具

    目录 1 Caffe数据集txt文本制作 2 jpg图像完整性检测 3 图像随机移动复制 4 图像尺寸统计 5 图像名字后缀重命名 6 两文件夹文件比对 7 绘制caffe模型的ROC曲线(二分类) ...

  2. NOIP2022 退役记

    无所谓,我还能卡队线. 无所谓,我还能被卡校线.

  3. PKUSC2022 润摆寄

    Day 0 模拟赛的题目竟是 寄 摆 润!预示着我的 PKUSC. Day 1 猜中主角(指九条可怜)原来都是芳文厨 看错时间以为考 \(5h\),于是告诉自己 优势在我可以慢慢做. T1 很显然的 ...

  4. python进阶之路17 包的使用、collections、time、random模块

    包 大白话: 多个py文件的集合>>>:文件夹 专业:内部含有__init__.py文件的文件夹(python2 必须要求 python3无所谓) 包的具体使用 虽然python3对 ...

  5. P1848 [USACO12OPEN]Bookshelf G

    简要题意 给你 \(N\) 本书 \((h_i,w_i)\),你要将书分成任意段(顺序不能改变),使得每一段 \(j\) 中 \(\sum\limits_{i \in j} w_i \leq L\), ...

  6. 使用英特尔 Sapphire Rapids 加速 PyTorch Transformers 模型

    大约一年以前,我们 展示 了如何在第三代 英特尔至强可扩展 CPU (即 Ice Lake) 集群上分布式训练 Hugging Face transformers 模型.最近,英特尔发布了代号为 Sa ...

  7. order by 语句怎么优化?

    说明 当前演示的数据库版本5.7 一.一个简单使用示例 先创建一张订单表 CREATE TABLE `order_info` ( `id` int NOT NULL AUTO_INCREMENT CO ...

  8. 【原创】项目六 Load Of The Root

    实战流程 新创建文件夹,在这个文件夹里进行操作 nmap扫描下网段 根据nmap逐个排查,发现目标主机,但只有22端口 因此进一步扫描22端口的具体信息,没有扫出很有用的信息 发现靶场又提示一个用户, ...

  9. ReentrantLock介绍及源码解析

    ReentrantLock介绍及源码解析 一.ReentrantLock介绍 ReentrantLock是JUC包下的一个并发工具类,可以通过他显示的加锁(lock)和释放锁(unlock)来实现线程 ...

  10. java画海报

    package demotest; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; impor ...