Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will computed property be dependent on a data property if I use data property only for checking if it is defined?

Tags:

vue.js

I have this vue component:

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,
        },
    },
}

Will computed property doc be dependent on a data property editor if I use this.editor only for checking if it is defined and not use it for assigning it to the doc? I mean, If I will change this.editor will doc be changed? Also, I have watcher on doc so I need to know if I will cause an infinite loop.

like image 841
webprogrammer Avatar asked Feb 01 '26 11:02

webprogrammer


2 Answers

In the doc property computation, you use:

  1. the editor property (at the beginning of your ternary, this.editor ? ...)
  2. if editor exists, the editor.view.state.doc property

So the computation of doc will be registered by Vue reactivity system as an effect related to the properties editor and (provided that editor exists) to editor.view.state.doc. In other words, the doc property will be reevaluated each time one of these two properties changes.

=> to reply to the initial question, doc will indeed depend on editor.

This can be toned though, because by 'property change', we mean:

  • for properties of primitive types, being reassigned with a different value
  • for objects, having a new reference

So, in our case, if editor, which is an object, is just mutated, and that this mutation does not concern it's property editor.view.state.doc, then doc will not be reevaluated. Here are few examples:

    this.editor = { ... }  // doc will be reevaluated
    this.editor.name = ' ... '  // doc will NOT be reevaluated
    this.editor.view.state.doc = { ... }  // doc will be reevaluated

If you want to understand this under the hood, I would recommand these resources (for Vue 3):

  • the reactivity course on Vue Mastery (free)
  • this great talk and demo (building a simple Vue-like reactivity system)

About the inifinite loop, the doc watcher handler will be executed only:

  • if doc is reassigned with a different value
  • in the case where docis an object, if doc is mutated (since you applied the deep option to the doc watcher)

The only possibility to trigger an infinite loop would be to, in the doc watcher handler, mutate or give a new value to doc (or editor.view.state.doc). For example (cf @Darius answer):

    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 = {}
            },
            // ...
        },
    }

=> to reply to the second question, apart from these edge cases, your code won't trigger a loop. For example:

    watch: {
        doc: {
            handler: function(val, OldVal){
                // even if we mutate the editor object, this will NOT trigger a loop
                this.editor.docsList = [] 
            },
            // ...
        },
    }
like image 60
Elise Patrikainen Avatar answered Feb 04 '26 00:02

Elise Patrikainen


Changing editor variable should work, but changing Editor content may not, as it depends on Editor class and how it respects reactivity.

For example:

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

If editor observer works and you are changing editor property in observer, which 'reinitializes' internal structures, it may lead to infinite loop:

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>

In such case, extra checking is necessary before making the change.

like image 22
Darius Avatar answered Feb 04 '26 02:02

Darius



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!