1.获取不到DOM的解决方案(使用$nextTick)
定义:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
理解:nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数.
使用场景:
1.1、Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载已完成。1.2、当项目中你想在改变DOM元素的数据后基于新的dom做点什么,对新DOM一系列的js操作都需要放进Vue.nextTick()的回调函数中;通俗的理解是:更改数据后当你想立即使用js操作新的视图的时候需要使用它
1.3、在使用某个第三方插件时 ,希望在vue生成的某些dom动态发生变化时重新应用该插件,也会用到该方法,这时候就需要在 $nextTick 的回调函数中执行重新应用插件的方法。
new Vue({
el: '#app',
data: {
list: []
},
mounted: function () {
this.get()
},
methods: {
get: function () {
this.$http.get('/api/article').then(function (res) {
this.list = res.data.data.list
// ref list 引用了ul元素,我想把第一个li颜色变为红色
this.$refs.list.getElementsByTagName('li')[0].style.color = 'red'
})
},
}
})我在获取到数据后赋值给数据模型中list属性,然后我想引用ul元素找到第一个li把它的颜色变为红色,但是事实上,这个要报错了,我们知道,在执行这句话时,ul下面并没有li,也就是说刚刚进行的赋值操作,当前并没有引起视图层的更新。因此,在这样的情况下,vue给我们提供了$nextTick方法,如果我们想对未来更新后的视图进行操作,我们只需要把要执行的函数传递给this.$nextTick方法,vue就会给我们做这个工作。
this.$nextTick(()=> {
// DOM 更新了
this.$refs.list.getElementsByTagName('li')[0].style.color = 'red'
})2.改变数据DOM不更新的解决方案
2.1数组
由于 JavaScript 的限制,Vue 不能检测以下变动的数组:
当你利用索引直接设置一个项时,例如:this.items[indexOfItem] = newValue
当你修改数组的长度时,例如:this.items.length = newLength
解决方案:
- Vue.set(this.items, indexOfItem, newValue)
- this.items.splice(indexOfItem, 1, newValue)
- this.$set(this.items, indexOfItem, newValue) (this.$set 实例方法是全局方法 Vue.set 的一个别名)
- this.items.splice(newLength)
2.2对象
由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:
var vm = new Vue({
data: {
userProfile: {
name: 'Anika'
}
}
})
//你可以添加一个新的 age 属性到嵌套的 userProfile 对象:
Vue.set(vm.userProfile, 'age', 27)
//你还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名:
this.$set(this.userProfile, 'age', 27)
//有时你可能需要为已有对象赋予多个新属性,比如使用 Object.assign() 或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。
this.userProfile = Object.assign({}, this.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
通俗来说:
方案一:利用 Vue.set(object,key,value);
方案二:利用this.$set(this.obj,key,value);
方案三:利用Object.assgin({},this.obj)
//删除对象属性的方法(前面对象名称,后面具体属性名):
this.$delete(this.userProfile, "name");