Problems encountered:
In a requirement, the change of a form needs a function of history recording. Because the form is very large (it is to edit an article), it is impossible to be specific to a certain attribute, so the method of watch monitoring is adopted, and {deep: true}
is set. However, when previewing, I encountered the error of rangeerror: maximum call stack size exceeded
. After some investigation, I found that it was caused by watch monitoring, and then I didn’t know what the problem was.
Even if nothing is written in the business code, a simple console.log will not work. As long as deep: true
is set, an error will be reported, which is a headache. I didn’t find a similar case on the Internet. I thought again: since the error lies in the watch, can I dynamically monitor
and cancel monitoring
?I found the answer on the official website https://cn.vuejs.org/v2/api/#vm -watch
Basic use of $watch (refer to the official website)
VM. $watch (exporfn, callback, [options])
the return value is a {function} unwatch
, which returns a function to cancel the observation, which is used to stop the trigger callback option: deep, deep listening option: immediate, whether to execute once immediately
// Key Path
vm.$watch('a.b.c', function (newVal, oldVal) {
// Do something
})
// function
var unwatch = vm.$watch(
function () {
// The expression `this.a + this.b` is called every time a different result is reached
// the handler function will be called.
// This is like listening for an undefined computed property
return this.a + this.b
},
function (newVal, oldVal) {
// Do something
}
)
// Cancel the listener
unwatch()
My solution, for reference
// Call setWatchChapters when created, call removeWatchChapters in other cases, depending on the business case
export default {
...
data () {
return {
unWatchChapters: null
}
},
created(){
this.setWatchChapters()
},
methods:{
setWatchChapters () { // Setting up a listener for chapters
if (!this.unWatchChapters) { // prevent setting listeners more than once
setTimeout(() => { // There are still some bugs, so use setTimeout to add to the event queue
this.unWatchChapters = this.$watch('report.chapters', () => {
// do something
}, { deep: true })
}, 0)
}
},
removeWatchChapters () { // Unlisten to chapters
if (this.unWatchChapters) {
this.unWatchChapters()
this.unWatchChapters = null
}
}
}
}