4

I have a mobile webview that is injected with some global config object:

Vue.prototype.$configServer = {
  MODE: "DEBUG",
  isMobile: false,
  injected: false,
  version: -1,
  title:"App",
  user: null,
  host: "http://127.0.0.1:8080"
}

Later the WebView inject this:

Vue.prototype.$configServer = {
  MODE: "DEBUG",
  title: "App",
  version: "2.0",
  isMobile: true,
  injected: true,
  host: "http://127.0.0.1:8081"
}

And try to use it for the component:

const HomePage = {
  key: 'HomePage',
  template: '#HomePage',
  components: { toolbar },
  data() {
    return {
      items: [
        {name:"Login", link:"login"},
      ]
    }
  },
  computed:{
    config() {
      return Vue.prototype.$configServer
    }
  },
};

However the page is not updated. How react to the change?

P.D: I confirm the object is updated with the safari debug tools. Also test in a local html.

mamcx
  • 15,916
  • 26
  • 101
  • 189
  • Adding a property to the Vue prototype does not make it reactive. In order to make it reactive you would need to do something like what is [described here](https://stackoverflow.com/questions/45111200/writing-to-a-global-variable-in-vuejs/45111258#45111258). – Bert Jul 11 '18 at 02:16
  • Can you put your config in main vue instance’s data? In that case vue will make sure that it will be reactive at all cost – Ankit Kumar Ojha Jul 11 '18 at 02:24
  • Yeah, that work. I need to access this.$root. Please add as answer. – mamcx Jul 11 '18 at 12:39

2 Answers2

11

Instead of putting the config into the prototype of Vue, you can actually add it as a data option inside the main vue instance which will guarantee you that all your config properties will be reactive. As mentioned in the docs

When you pass a plain JavaScript object to a Vue instance as its data option, Vue will walk through all of its properties and convert them to getter/setters using Object.defineProperty.

Having said that whenever you update your config properties, vue will react to it.

Now let's see how to do it in code:

new Vue(){
    data:{ //only place where data is not a function
        configServer = {
              MODE: "DEBUG",
              isMobile: false,
              injected: false,
              version: -1,
              title:"App",
              user: null,
              host: "http://127.0.0.1:8080"
        } 
    }
}

Now whenever you need to access your config you can directly access it from any component using $root. Like this.$root.configServer.

Well that's it.

I hope it helps.

Ankit Kumar Ojha
  • 2,296
  • 2
  • 22
  • 30
1

There are 3 ways to acheive what you want

1- Make sure you import vue in your component

import 'Vue' from vue
...
...
...
 computed:{
    config() {
      return Vue.prototype.$configServer
    }

2- If you don't want to import vue the you can directly access prototype using proto from any instance.

computed:{
        config() {
          return this.__proto__.$configServer
        }

3- As you have added the config in the prototype you can actually access is directly from the vue instance using this

computed:{
    config() {
      return this.$configServer
    }
  },

Well whatever style matches yours you can choose that.

But I would personally recommend using the 3rd one, because accessing the prototype of instance is sort of an anti-pattern.

I hope it helps.

Ankit Kumar Ojha
  • 2,296
  • 2
  • 22
  • 30