Vue 整理

computed 计算属性

computed 和方法

computed: 计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。
方法:每次都会执行

在计算比较复杂的情况下,computed 会是更优的选择

computed 和 watch

主要是使用场景上的区别。

  • computed:一个数据依赖于其他数据,使用 computed 会是一个更好的选择
  • watch:如果需要在某个数据变化的时候做一些事情,比如数据变化之后执行一个请求,这种情况下 watch 会是更好的选择

v-if 和 v-show

  • v-if:在条件切换的时候,都会触发销毁和重新渲染。如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
  • v-show:元素一定会被渲染,并且只是基于 CSS 的 display 进行切换。

一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

v-if 和 v-for

当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。
原因:for 循环中如果只想渲染部分节点的时候,for 优先级更高才能实现这种情况,但是不推荐使用,一般用计算属性过滤后展示。

不一起用的原因:只渲染出一小部分用户的元素,也得在每次重渲染的时候遍历整个列表,不论活跃用户是否发生了变化。这是 v-for 和 v-if 不能一块用的原因。

key 的作用

Vue 会复用已有元素,下面这种情况并不会清除用户的输入,只是替换了 placeholder。添加对应的 key,才能保证唯一的。

1
2
3
4
5
6
7
8
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" />
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" />
</template>

diff 算法中识别节点的机制。在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会尝试就地修改/复用相同类型元素的。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

响应式

Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。

对于 对象 和 数组,可以使用 Vue.set 来触发状态更新

Vue 封装的数组操作?

push,pop,shift,unshift,splice,sort,reverse

对于 push 和 unshift 这种插入数据的,会使用 observer 来让数据变成响应式的。
然后所有操作执行的时候,都会手动触发 依赖更新 dep.notify()

v-model 实现

1
2
3
4
5
6
7
8
9
10
11
12
// 组件 v-model input输入封装
Vue.component("my-input", {
props: ["inputValue"],
template: `
<div>
<input
:value="inputValue"
@input="$emit('input', $event.target.value)"
></input>
<div>
`,
})

插槽,具名插槽,作用域插槽

1
2
3
4
5
6
7
8
9
10
11
12
<my-slot>
{{ fatherText }}
<!-- 具名插槽 -->
<template v-slot:extra>
<div>extra content</div>
</template>

<!-- 作用域插槽 -->
<template v-slot:scopeslot="{ obj }">
<div>{{ obj.new }}</div>
</template>
</my-slot>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Vue.component("my-slot", {
data() {
return {
childObj: {
old: "text",
new: "new Text",
},
}
},
template: `
<div>
Error:<slot>default content</slot>
<slot name="extra"></slot>
<slot name="scopeslot" :obj="childObj">{{ childObj.old }}</slot>
</div>
`,
})

keep-alive

一般和动态组件一起用<component :is="currentTabComponent"></component>
<keep-alive>包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
include 和 exclude 允许组件有条件地缓存。根据组件 name 来确认,有两个生命周期activateddeactivated

keep-alive 是一个内置组件,对于 Vue 来讲,渲染过程是:template -> parse/optimize/generate -> render function -> VNode -> (createElm 转换)真实 DOM。在转换过程中,会在组件实例化之后缓存下来,其中的缓存策略是 LRU,如果存在缓存,会从缓存中获取组件实例,如果不存在缓存,会将组件的 key 放入缓存数组。

异步组件

需要提供一个工厂函数,异步组件只有在被渲染的时候才会触发工厂函数,工厂函数会收到一个 resolve 回调,然后把结果缓存起来供以后渲染。

1
2
3
4
5
6
7
8
Vue.component("my-async-component", (resolve, reject) => {
// 满足某些条件(比如 ajax请求某些结果之后额)
fetch("/example").then((res) => {
resolve({
template: `<div>异步组件</div>`,
})
})
})

ES6 + webpack code-splitting 功能

1
2
3
4
5
Vue.component(
"async-webpack-example",
// 这个动态导入会返回一个 `Promise` 对象。
() => import("./my-async-component")
)