持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
这种题目在面试中出现的频率非常高,虽然题目很简单,但是要答到点子上,需要了解一些源码,如果在说出data是函数可以防止数据污染的基础上,再说出它的原理,会增分不少~
1、为什么组件中data的定义是一个函数而不是对象?
原因是创建两个组件,当其中一个组件修改data属性的值,另外一个组件中data属性的值也会随之改变(共用了同一个内存地址所,所有的实例共享引用同一个数据对象)
采用函数的形式不会造成上述问题,每个函数中对象指向的内存地址都不相同,每个组件中的属性值互不影响,不会受到其他实例对象数据的污染,一个组件被复用多次的话,也会创建多个实例
const component1 = new Component()
const component2 = new Component()
console.log(component1.data.id) // 运行结果:1
component1.data.id = 2
console.log(component2.data.id) // 运行结果:2
2、Vue中对象添加新的属性时,界面视图不自动刷新
如下图,当点击按钮为对象添加新的属性name字段时,控制台可以看到对象的结构已经改变,但界面视图并没有发生改变:
我们实际想要的效果应该是这样:
解决方式:
下面共列举出4种方法:
1. ... 展开语法
testFn() {
this.obj.name = 'haha'
this.obj = { ...this.obj }
console.log(this.obj)
注:
- 对象数据obj,使用
obj = {...obj} - 对于数组arr,使用
arr = [...arr]
2. Vue.set( target, key/index, value )
参数:( 源数据 , 需要修改的对象的键/数组的下标 , 修改的值 )
使用方法:
this.$set(this.obj, 'name', 'haha')
也可以:
Vue.set(this.obj, 'name', 'haha')
3. Object.assign()
创建一个新的对象,将原有对象和新添加的对象属性合并(需要创建新对象,否则不会触发更新)
this.obj = Object.assign({}, this.obj, { name: 'haha' })
也可以修改对象后,将其与空对象合并后重新赋值:
this.obj.name = 'haha'
this.obj = Object.assign({}, this.obj)
注: 如果是数组,将{}改为[]:Object.assign([], target)
4. 强制更新视图(不推荐)
执行后会触发updated生命周期:this.$forceUpdate()
注: 强制刷新仅仅影响实例本身和插入插槽内容的子组件,而不是所有的子组件