面试题答案
一键面试让新增属性具备响应式的方法
- 使用
Vue.set
(Vue 2.x) 或this.$set
(在组件实例中):- 示例:
import Vue from 'vue'; const vm = new Vue({ data: { obj: { name: 'John' } } }); Vue.set(vm.obj, 'age', 30);
- 在组件中使用:
export default { data() { return { obj: { name: 'John' } }; }, mounted() { this.$set(this.obj, 'age', 30); } };
- 使用
Object.assign
创建新对象 (Vue 2.x):- 示例:
import Vue from 'vue'; const vm = new Vue({ data: { obj: { name: 'John' } } }); vm.obj = Object.assign({}, vm.obj, { age: 30 });
- 在Vue 3.x中使用
reactive
和ref
:- 使用
reactive
:
import { reactive } from 'vue'; const state = reactive({ obj: { name: 'John' } }); // 新增响应式属性 state.obj.age = 30;
- 使用
ref
:
import { ref } from 'vue'; const objRef = ref({ name: 'John' }); // 新增响应式属性 objRef.value.age = 30;
- 使用
原理
- Vue 2.x:Vue在初始化数据时,会通过
Object.defineProperty
方法将数据的属性转换为getter
和setter
,从而实现数据劫持和响应式追踪。当新增属性时,默认不会进行这种转换,所以不会具备响应式。Vue.set
方法会对新添加的属性进行Object.defineProperty
转换,使其具备响应式。Object.assign
方法是通过创建一个新对象,重新对新对象的所有属性进行响应式转换,从而使得新属性也具备响应式。 - Vue 3.x:Vue 3.x 使用
Proxy
来实现响应式系统。Proxy
可以直接监听对象的操作,包括新增属性,所以在reactive
创建的响应式对象上新增属性会自动具备响应式。而ref
本质上也是基于reactive
实现的,通过.value
访问内部值,对其进行操作也能实现响应式。
相关API使用场景和限制
Vue.set
/this.$set
(Vue 2.x):- 使用场景:适用于在已有的响应式对象上动态添加属性,并且希望该属性能够被Vue的响应式系统追踪的场景,例如在组件中动态给对象添加新字段。
- 限制:
- 必须传入目标对象、属性名和属性值三个参数,使用相对固定。
- 如果目标对象是一个数组,不能使用它来直接修改数组的长度,应使用数组的变异方法(如
push
、pop
等)。
Object.assign
(Vue 2.x):- 使用场景:适用于需要一次性添加多个属性到响应式对象,并且需要让这些新属性都具备响应式的场景。
- 限制:
- 创建新对象会产生额外的性能开销,尤其是对象较大时。
- 会丢失原对象的原型链,因为
Object.assign
创建的是一个全新的普通对象。
reactive
和ref
(Vue 3.x):- 使用场景:
reactive
适用于创建复杂的响应式对象,ref
适用于创建基础类型或对象的响应式引用,在Vue 3项目开发中广泛使用。 - 限制:
reactive
创建的对象是深度响应式的,但对一些原生数据结构(如Map
、Set
)的响应式支持有一定的局限性,需要手动处理某些操作。ref
在模板中使用时,对于对象类型,需要通过.value
访问,在某些场景下可能略显繁琐。
- 使用场景: