May 31, 2021 Article blog
1. 1. Vue was unable to detect property that did not exist in data when the instance was created
2. 2. Vue cannot detect the addition or removal of object property
3. 3. Vue cannot detect the direct modification of an array item through an array index
4. 4. Vue cannot monitor changes in the length of an array that is directly modified
5. 5. The operation of the DOM data does not change until the asynchronous update is performed
6. 6. Loop nesting level is too deep, view is not updated?
7. 7. Expansion: When routing parameters change, the page is not updated (data is not updated)
The article comes from the public number: Pixel Swing, author Leiy
Cause: Because
Vue
performs a
getter/setter
conversion on property when the instance is initialized, property must exist on the
data
object in order for
Vue
to convert it to responsive.
scenario:
var vm = new Vue({
data:{},
// 页面不会变化
template: '<div>{{message}}</div>'
})
vm.message = 'Hello!' // `vm.message` 不是响应式的
Solution:
var vm = new Vue({
data: {
// 声明 a、b 为一个空值字符串
message: '',
},
template: '<div>{{ message }}</div>'
})
vm.message = 'Hello!'
Cause: Official - Due to
JavaScript
(ES5) restrictions, Vue .js
cannot detect the addition or deletion of object properties.
Because Vue .js converts the property to getter/setter when the instance is initialized, the property must be on the
data
object before Vue .js convert it to make it responsive.
scenario:
var vm = new Vue({
data:{
obj: {
id: 001
}
},
// 页面不会变化
template: '<div>{{ obj.message }}</div>'
})
vm.obj.message = 'hello' // 不是响应式的
delete vm.obj.id // 不是响应式的
Solution:
// 动态添加 - Vue.set
Vue.set(vm.obj, propertyName, newValue)
// 动态添加 - vm.$set
vm.$set(vm.obj, propertyName, newValue)
// 动态添加多个
// 代替 Object.assign(this.obj, { a: 1, b: 2 })
this.obj = Object.assign({}, this.obj, { a: 1, b: 2 })
// 动态移除 - Vue.delete
Vue.delete(vm.obj, propertyName)
// 动态移除 - vm.$delete
vm.$delete(vm.obj, propertyName)
Cause: Official - Due to JavaScript limitations, Vue cannot detect changes in arrays and objects;
scenario:
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
Solution:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// vm.$set
vm.$set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
Object.defineProperty() monitors array changes. However, the addition of an index to the array does not monitor for data changes because the subscript (index) of the new array cannot be monitored, as does deleting a property (index).
scenario:
var arr = [1, 2, 3, 4]
arr.forEach(function(item, index) {
Object.defineProperty(arr, index, {
set: function(value) {
console.log('触发 setter')
item = value
},
get: function() {
console.log('触发 getter')
return item
}
})
})
arr[1] = '123' // 触发 setter
arr[1] // 触发 getter 返回值为 "123"
arr[5] = 5 // 不会触发 setter 和 getter
Cause: Official - Due to JavaScript limitations, Vue cannot detect changes in arrays and objects;
scenario:
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items.length = 2 // 不是响应性的
Solution:
vm.items.splice(newLength)
Cause:
Vue
was
asynchronous
when updating the DOM. A
s soon as you hear data changes,
Vue
opens a queue and buffers all data changes that occur in the same event loop. I
f the same watcher is triggered more than once, it is pushed into the queue only once. T
his removal of duplicate data when buffering is important to avoid unnecessary calculations and DOM operations. T
hen, in the next event loop, tick,
Vue
refreshes the queue and performs the actual (de-heavy) work.
Vue
attempts to use native
Promise.then
MutationObserver
and
setImmediate
for asynchronous queues, and if the execution environment does not support it, it takes
setTimeout(fn, 0)
scenario:
<div id="example">{{message}}</div>
var vm = new Vue({
el: '#example',
data: {
message: '123'
}
})
vm.message = 'new message' // 更改数据
vm.$el.textContent === 'new message' // false
vm.$el.style.color = 'red' // 页面没有变化
Solution:
var vm = new Vue({
el: '#example',
data: {
message: '123'
}
})
vm.message = 'new message' // 更改数据
//使用 Vue.nextTick(callback) callback 将在 DOM 更新完成后被调用
Vue.nextTick(function () {
vm.$el.textContent === 'new message' // true
vm.$el.style.color = 'red' // 文字颜色变成红色
})
<!-- 页面显示:我更新啦! -->
<div id="example">{{message.text}}</div>
var vm = new Vue({
el: '#example',
data: {
message: {},
}
})
vm.$nextTick(function () {
this.message = {}
this.message.text = '我更新啦!'
})
In the previous section of code, we declared a
message
empty object in the
data
object, and then executed the following two pieces of code in the asynchronous callback triggered after the end of the next DOM update cycle:
this.message = {};
this.message.text = '我更新啦!'
Here, the template is updated, the page will finally show
我更新啦!
。
The template has been updated and should be responsive, so if you think so, you're already in the wrong place.
At first we just declared a
message
empty object in the
data
object and didn't have a
text
property, so the
text
property is not responsive.
But the template has actually been updated, and what's going on?
That's because Vue .js's DOM update is asynchronous, that is, when the
setter
operation occurs, the instruction is not immediately updated, the instruction update operation will have a delay, when the instruction update is actually executed, the
text
property has been assigned, so the instruction update template gets a new value.
Each instruction/data binding in the template has a corresponding watcher object that records properties as dependencies during calculations. Then, when the dependent setter is called, the watcher is triggered to recalculate, which causes its associated instructions to update the DOM.
The process is as follows:
this.message = {};
when
setter
is called.
message
setter
is called, triggering a
watcher
recalculation.
this.message.text = '我更新啦!';
The
text
property is assigned.
So the real trigger for a template update is
this.message = {};
This sentence is caused by the trigger
setter
so look at the above example alone, the data with responsive characteristics is only
message
layer, its dynamically added properties are not available.
Corresponding to the second point above - Vue cannot detect the addition or removal of object property
See some people on the Internet say that the level of data updates is too deep, resulting in data not being updated or slow updating leading to attempts not to update?
Since I haven't been in this situation, and I've tried to recreate this scenario, I've found that it didn't happen, so don't over-describe it (if someone is in a real situation).
The solution given for the above situation is to use forced updates:
If you find that you need to do a forced update in Vue, 99.9% of the time, you did something wrong somewhere.
vm.$forceUpdate()
Extending a problem where the page is not updated because of changes in routing parameters, and the non-update of the page is essentially that the data is not updated.
Cause: When a route view component references the same component, when a route changes, it causes the component to fail to update, which is what we often say is an issue where the page in cannot be updated.
scenario:
<div id="app">
<ul>
<li><router-link to="/home/foo">To Foo</router-link></li>
<li><router-link to="/home/baz">To Baz</router-link></li>
<li><router-link to="/home/bar">To Bar</router-link></li>
</ul>
<router-view></router-view>
</div>
const Home = {
template: `<div>{{message}}</div>`,
data() {
return {
message: this.$route.params.name
}
}
}
const router = new VueRouter({
mode:'history',
routes: [
{path: '/home', component: Home },
{path: '/home/:name', component: Home }
]
})
new Vue({
el: '#app',
router
})
In the previous section of code, we configured a dynamic route
'/home/:name'
in the routing build option
routes
which shares a routing component,
Home
which means that they reuse
RouterView
When routing, the page renders only the parameters that the first route matches to, and then route switching,
message
does not change.
Solution:
There are many ways to solve them, and here are just a few of the methods I use.
$route
through
watch
const Home = {
template: `<div>{{message}}</div>`,
data() {
return {
message: this.$route.params.name
}
},
watch: {
'$route': function() {
this.message = this.$route.params.name
}
}
}
...
new Vue({
el: '#app',
router
})
key
property
<router-view>
so that Vue thinks it's a different
<router-view>
Drawback: If we jump from
/home
to other routes such as
/user
we don't have to worry about component updates, so this time
key
property is redundant.
<div id="app">
...
<router-view :key="key"></router-view>
</div>
Here are
W3Cschool编程狮
seen about Vue data updates but pages that haven't been updated, and you've seen several related introductions that you'd
like to help.