xb18
xb18
文章78
标签0
分类0
Vue3 vs Vue2

Vue3 vs Vue2

vue3

ref用于定义基本类型和引用类型,reactive仅用于定义引用类型
reactive只能用于定义引用数据类型的原因在于内部是通过ES6的Proxy实现响应式的,而Proxy不适用于基本数据类型
ref定义对象时,底层会通过reactive转换成具有深层次的响应式对象,所以ref本质上是reactive的再封装

ref

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// ref 的构造类
// 劫持这个 class 的
// get value 和 set value
class RefImpl<T> {
// 依赖集合
public dep: Dep
// get return 的值
private _value
// 因为 如果传入对象
// _value 在 初始化时已经被处理成 proxy 了
// 所以需要 _rawValue 来保存原始值 用于更新对比
public _rawValue
public __V_IS_REF: boolean = true
constructor(value: T) {
this._rawValue = value
this._value = convert(value) // 处理对象情况 用reactive
this.dep = new Set()
}
get value() {
// 收集依赖
trackRefValue(this)
return this._value
}
set value(newValue) {
// 防止 赋相同的值
// 会导致重新 trigger
if (!hasChanged(newValue, this._rawValue)) return
// set
this._value = convert(newValue)
this._rawValue = newValue
// trigger 触发deps作出更新
triggerEffects(this.dep)
}
}

export function ref<T>(value: T) {
return new RefImpl(value)
}

Vue3 vs Vue2

优势

组合式API:

  • 更好的逻辑复用
  • 更灵活的代码组织
  • 更好的类型推导
  • 更小的生产包体积

组合式API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script setup>
import { ref, onMounted } from 'vue'

// 响应式状态
const count = ref(0)

// 更改状态、触发更新的函数
function increment() {
count.value++
}

// 生命周期钩子
onMounted(() => {
console.log(`计数器初始值为 ${count.value}。`)
})
</script>

<template>
<button @click="increment">点击了:{{ count }}</button>
</template>

全局API

1
2
3
4
import { createApp } from 'vue'

const app = createApp({})

2.x 全局 API3.x 实例 API (app)
Vue.configapp.config
Vue.config.productionTip移除 (见下方)
Vue.config.ignoredElementsapp.config.compilerOptions.isCustomElement (见下方)
Vue.componentapp.component
Vue.directiveapp.directive
Vue.mixinapp.mixin
Vue.useapp.use (见下方)
Vue.prototypeapp.config.globalProperties (见下方)
Vue.extend移除 (见下方)

Treeshaking

1
2
3
4
5
6
import { nextTick } from 'vue'

nextTick(() => {
// 一些和 DOM 有关的东西
})

v-model 和 sync

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// vue2
<ChildComponent v-model="pageTitle" />
<!-- 是以下的简写: -->
<ChildComponent :value="pageTitle" @input="pageTitle = $event" />
<!-- sync -->
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
<ChildComponent :title.sync="pageTitle" /> <!-- 简写 -->

// vue3
<ChildComponent v-model="pageTitle" />
<!-- 是以下的简写: -->
<ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle = $event"
/>

key

1
2
3
4
5
6
7
8
9
10
11
<!-- Vue 2.x -->
<template v-for="item in list">
<div :key="'heading-' + item.id">...</div>
<span :key="'content-' + item.id">...</span>
</template>

<!-- Vue 3.x -->
<template v-for="item in list" :key="item.id">
<div>...</div>
<span>...</span>
</template>

v-if,v-for

2.x 版本中在一个元素上同时使用 v-ifv-for 时,v-for 会优先作用。

3.x 版本中 v-if 总是优先于 v-for 生效。

响应式原理

Vue 2 使用 getter / setters 完全是出于支持旧版本浏览器的限制。而在 Vue 3 中则使用了 Proxy 来创建响应式对象,仅将 getter / setter 用于 ref。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function reactive(obj) {
return new Proxy(obj, {
get(target, key) {
track(target, key)
return target[key]
},
set(target, key, value) {
target[key] = value
trigger(target, key)
}
})
}

function ref(value) {
const refObject = {
get value() {
track(refObject, 'value')
return value
},
set value(newValue) {
value = newValue
trigger(refObject, 'value')
}
}
return refObject
}

track收集依赖,trigger触发更新

vue2

生命周期

在Vue中,父子组件的生命周期执行顺序遵循以下规则:

  1. 父组件 beforeCreate
  2. 父组件 created
  3. 父组件 beforeMount
  4. 子组件 beforeCreate
  5. 子组件 created
  6. 子组件 beforeMount
  7. 子组件 mounted
  8. 父组件 mounted

更新过程中:

  1. 父组件 beforeUpdate
  2. 子组件 beforeUpdate
  3. 子组件 updated
  4. 父组件 updated

销毁过程中:

  1. 父组件 beforeDestroy
  2. 子组件 beforeDestroy
  3. 子组件 destroyed
  4. 父组件 destroyed

Vue 实例生命周期

provide/inject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// provide 多个方法给子组件使用
provide() {
return {
getBeCascaded: () => this.beCascaded
};
},

// inject
inject: ['beCascaded']
computed: {
beCascaded() {
return this.beCascaded();// created后能取到
}
}

this.beCascaded

// 或者provide一个对象给子组件使用 也能利用对象的引用 实现响应性
provide() {
return {
obj: {
beCascaded: this.beCascaded
}
};
}
inject: ['obj']

this.obj.beCascaded
1
===优先级最大,&&次之,||优先级最小
本文作者:xb18
本文链接:https://moelj.com/2023/10/16/Vue3%20vs%20Vue2/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可