Day24:Vue

目标

1
2
3
4
5
6
1. Vue3 为什么出现(★★★)
2. Vue3 Composition API(★★★★★)
3. ref 和 reactive 区别(★★★★★)
4. computed 和 watch(★★★★★)
5. Vue 响应式原理(★★★★★)
6. 生命周期(★★★★)

Vue2 和 Vue3 为什么升级?

  1. Composition API
    Vue2 都是Options API配置项。一个业务逻辑可能分散。
    Vue3 组合式api相关逻辑放一起。
  2. 更好的 TypeScript 支持

Vue3 响应式原理

Vue3 使用 Proxy 实现响应式,通过代理对象拦截属性访问和修改,在数据变化时通知依赖更新。

Vue2使用 Object.defineProperty 监听getter/setter。
Vue3使用 Proxy。

ref 和 reactive 区别

ref

接收的数据可以是:基本类型、也可以是对象类型。
基本类型的数据:响应式依然是靠Object.defineProperty()的get与set完成的。
对象类型的数据:内部也是reactive函数

reactive

作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
reactive定义的响应式数据是“深层次的”。
内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。

对比 ref reactive
支持类型 任意类型 仅对象、数组等引用类型
底层 Ref 包装对象(对象内部仍使用 Proxy) Proxy
JS 中访问 count.value user.name
模板中访问 自动解包,不需要 .value 直接访问

computed 和 watch

computed

计算属性。有缓存。例如:

1
2
3
const fullName = computed(()=>{
return first.value + last.value
})

如果first、last没变化,不会重新计算。

watch

监听变化。例如:

1
2
3
4
5
6
watch(
()=>user.id,
()=>{
query()
}
)
函数 功能
computed 根据已有数据计算新数据。
watch 数据变化后执行动作。

Vue 生命周期

Vue 生命周期

常用:

1
2
3
4
5
6
7
setup()

onMounted()

onUpdated()

onUnmounted()

1. Vue3 为什么不用 Vue2 的 Object.defineProperty,而使用 Proxy?

Vue2 使用 Object.defineProperty 实现响应式,它只能监听对象已有属性,对新增、删除属性以及数组操作支持不好,需要使用 Vue.set 等额外 API。

Vue3 改为使用 Proxy,它代理的是整个对象,可以拦截对象的读取、修改、删除、属性新增以及数组操作等几乎所有行为,因此响应式能力更完善。同时,Proxy 不需要递归遍历整个对象,而是在访问嵌套对象时再进行代理(懒代理),性能和可维护性都更好。

Proxy 代理整个对象,功能更完整,对新增属性、删除属性和数组支持更好,并采用懒代理提升性能。

2. ref 和 reactive 有什么区别?

reactive 用于创建对象类型的响应式数据,底层基于 Proxy 实现,访问属性时不需要 .value。

ref 可以用于基本类型,也可以用于对象。它会将数据包装成一个带有 value 属性的响应式对象;如果包装的是对象,内部仍然会调用 reactive 将对象转换成 Proxy。

reactive 用于对象,底层是 Proxy;ref 用于任意类型,负责包装数据,包装对象内部仍然使用 reactive。

3. 为什么 ref 需要 .value?

因为 JavaScript 的基本类型无法直接使用 Proxy 代理,所以 Vue 会把基本类型包装成一个对象,例如 { value: 1 },真正具有响应式能力的是这个包装对象,因此在 JavaScript 中需要通过 .value 访问真实数据。

在模板中,Vue 编译器会自动解包,因此可以直接写 ,无需手动写 .value。

因为基本类型不能直接代理,Vue 把它包装成 { value },所以 JS 中需要 .value,模板会自动解包。

4. computed 和 watch 区别?

computed 用来根据已有数据计算新数据,并且具有缓存;watch 用来监听数据变化,执行回调函数,比如发送请求、修改其他状态。

5. 你的 GIS 平台页面打开分析任务列表,你会在哪个生命周期调用接口为什么?

DOM 已经挂载完成,页面初始化数据请求一般放在 onMounted 中。

6. v-if 和 v-show 有什么区别?

v-if 是真正的条件渲染,条件不满足时不会渲染 DOM;再次满足时会重新创建组件,因此切换开销较大,但首次渲染成本低。

v-show 始终会渲染 DOM,只是通过 display: none 控制显示和隐藏,不会销毁组件,因此切换速度快,但首次渲染成本较高。

一般来说,频繁切换用 v-show,条件很少变化用 v-if。

7. 为什么 v-for 必须写 key?

Vue 更新列表时,会比较新旧 Virtual DOM。如果没有 key,Vue 会尽可能复用已有 DOM,可能导致组件状态错乱,例如输入框内容、选中状态等发生错误。

key 用于唯一标识节点,帮助 Vue 快速定位哪些节点需要新增、删除或移动,提高 Diff 效率,并避免错误复用 DOM。

因此,通常应该使用业务唯一 ID 作为 key,而不是 index。只有列表完全不会增删改排序时,index 才勉强可以使用。