Будет ли вычисляемое свойство зависеть от свойства данных, если я использую свойство данных только для проверки, определено ли оно?

#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 вычислении свойства вы используете:

  1. editor свойство (в начале вашего троичного, this.editor ? ... )
  2. если 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):


Что касается бесконечного цикла, обработчик 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>  

В таком случае перед внесением изменений необходима дополнительная проверка.