#vue.js
#vue.js
Вопрос:
У меня есть этот компонент vue:
export default {
data: function() {
return {
editor: new Editor({
//some options
}),
}
},
computed: {
doc(){ // <--------------------- take attention on this computed property
return this.editor ? this.editor.view.state.doc : null;
},
},
watch: {
doc: {
handler: function(val, OldVal){
// call some this.editor methods
},
deep: true,
immediate: true,
},
},
}
Будет ли вычисляемое свойство doc
зависеть от свойства данных editor
, если я использую this.editor
только для проверки, определено ли оно, и не использую его для присвоения doc
? Я имею в виду, если я изменю this.editor
doc
, будет изменено? Кроме того, у меня включен наблюдатель doc
, поэтому мне нужно знать, вызову ли я бесконечный цикл.
Комментарии:
1. Почему бы не поставить несколько
console.log
операторов и проверить.2. @ravikumar, у меня есть страница зависания после некоторой модификации кода, поэтому я пытаюсь понять, как работает система зависимостей vue. Я имею в виду понимать, а не угадывать. Вот почему я спрашиваю.
3. 1. В вашем обработчике вы должны использовать
Vue.nextTick()
модификации редактора для преодоления рекурсивных изменений и зависания. 2. Ваши изменения могут воссоздать в редакторе некоторые структуры и могут привести к бесконечному циклу без дополнительной проверки4. @Darius, 2) похоже, что это действительно так.
Ответ №1:
При doc
вычислении свойства вы используете:
editor
свойство (в начале вашего троичного,this.editor ? ...
)- если
editor
существует,editor.view.state.doc
свойство
Таким образом, вычисление doc
будет зарегистрировано системой реактивности Vue как эффект, связанный со свойствами editor
и (при условии, что editor
он существует) to editor.view.state.doc
. Другими словами, doc
свойство будет переоцениваться каждый раз, когда изменяется одно из этих двух свойств.
=> чтобы ответить на первоначальный вопрос, doc
действительно будет зависеть от editor
.
Это можно смягчить, поскольку под «изменением свойства» мы подразумеваем:
- для свойств примитивных типов переназначается другое значение
- для объектов, имеющих новую ссылку
Итак, в нашем случае if editor
, который является объектом, просто мутирует, и эта мутация не касается его свойства editor.view.state.doc
, тогда doc
не будет переоценен. Вот несколько примеров:
this.editor = { ... } // doc will be reevaluated
this.editor.name = ' ... ' // doc will NOT be reevaluated
this.editor.view.state.doc = { ... } // doc will be reevaluated
Если вы хотите понять это под капотом, я бы рекомендовал эти ресурсы (для Vue 3):
- курс реактивности по освоению Vue (бесплатно)
- этот отличный доклад и демонстрация (создание простой системы реактивности, подобной Vue)
Что касается бесконечного цикла, обработчик doc
наблюдателя будет выполняться только:
- if
doc
переназначается другим значением - в случае, когда
doc
это объект, еслиdoc
он изменен (поскольку вы применили этуdeep
опцию кdoc
наблюдателю)
Единственной возможностью запустить бесконечный цикл было бы doc
изменить или присвоить новое значение doc
(или) в обработчике наблюдателя editor.view.state.doc
. Например (см. ответ @Darius):
watch: {
doc: {
handler: function(val, OldVal){
// we give a new ref each time this handler is executed
// so this will trigger an infinite loop
this.editor.view.state.doc = {}
},
// ...
},
}
=> чтобы ответить на второй вопрос, кроме этих крайних случаев, ваш код не будет запускать цикл. Например:
watch: {
doc: {
handler: function(val, OldVal){
// even if we mutate the editor object, this will NOT trigger a loop
this.editor.docsList = []
},
// ...
},
}
Комментарии:
1.
editor
было добавлено кdoc
зависимостям, потому что внутри вычисляемого метода вызывался получатель редактораdoc
. Итак, на самом деле это ответ на мой вопрос, и вы были гораздо более понятны. Кроме того, у меня есть некоторый наблюдатель сval = {} and oldVal = {}
— это разные объекты, поэтому они не равны, несмотря на то, что они пусты — это было причиной моего бесконечного цикла. Я могу пометить ваш ответ как принятый. Спасибо!
Ответ №2:
Изменение editor
переменной должно работать, но изменение Editor
содержимого может и не работать, поскольку это зависит от Editor
класса и того, как он учитывает реактивность.
Например:
export default {
data: function() {
return {
editor: {text: '' }
}
}
}
...
this.editor.text = 'Text' // works
this.editor.text = {param: ''} // works
this.editor.text.param = 'value' // works
this.editor.param = {} // does't work, as creation of new property is not observable
Если editor
observer работает, и вы меняете свойство editor в observer, которое «повторно инициализирует» внутренние структуры, это может привести к бесконечному циклу:
var Editor = function() {
this.document = {}
this.change = () => { this.document = {} }
}
var data = new Vue({
data: () => ({
editor: new Editor(),
check: 0
}),
watch: {
editor: {
handler() {
this.check
console.log('Changed')
if (this.check < 5)
this.editor.change()
else
console.log('Infinite loop!')
},
deep: true,
immediate: true
}
}
})
data.editor.change()
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
В таком случае перед внесением изменений необходима дополнительная проверка.