VueJS observe plugged parameter

230 Views Asked by At

I'm starting with VueJS 2 and I created a simple plugin which adds parameter to Vue instance.

I have problem because when I update this value my computed properties are still same.

My example plugin's code:

export default function (Vue) {
    Vue.MyProperty = "test"

    Object.defineProperties(Vue.prototype, {
        "$myProperty": {
            "get": function () {
                return Vue.MyProperty
            },

            "set": function (value) {
                Vue.MyProperty = value

                return this
            }
        }
    })
}

And my component's code

export default {
    "computed": {
        "test": function () {
            return this.$myProperty
        }
    }
}

When I changed this.$myProperty in other component my component returns vaid value (in example when I changed from "test" into "newvalue" I can see "newvalue") but computed property test is still old value ("test" in my example).

I tried to use this.$set(this, "$myProperty", value) but this still not working.

How can I use or declare this property to use it in computed or watched properties?

1

There are 1 best solutions below

1
On BEST ANSWER

The reason the data value is not automatically updated in the computed is because the property you added to Vue, MyProperty is not an observed property. Fundamentally, Vue's reactivity works because all values added to data are converted into observed properties; under the hood they are converted into getter/setter pairs with some additional code so that when one of those properties changes, Vue knows to propagate the changes to all the things that depend on it's value.

The code in the question, however, just adds a normal property to the Vue object. You can change it, but it's not reactive.

That said, it's relatively easy to make it reactive. I cover how to do this in the comments to my answer here. Basically, instead of adding your property to Vue, just create a new Vue object (which has very low overhead) and make the property you want to be reactive a property of that Vue. Here is a working example.

console.clear()

function MyPlugin(Vue) {
  let store = new Vue({data:{MyProperty: "some value"}})

    Object.defineProperties(Vue.prototype, {
        "$myProperty": {
            "get": function () {
                return store.MyProperty
            },

            "set": function (value) {
                store.MyProperty = value

                return this
            }
        }
    })
}

Vue.use(MyPlugin)

const MyComponent = {
  template:`<div>{{test}}</div>`,
    "computed": {
        "test": function () {
            return this.$myProperty
        }
    }
}

new Vue({
  el: "#app",
  components:{
    MyComponent
  }
})
<script src="https://unpkg.com/[email protected]"></script>
<div id="app">
  <my-component></my-component>
  <button @click="$myProperty = 'new value'">Change</button>
</div>