Change Vue Prototype Variable In All Components


Answer :

To have $color globally available, you can use a Mixin, more specifically a Global Mixin.

If you would only want it to be read-only, it is simplest solution (less code). See snippet:

Vue.mixin({   created: function () {     this.$color = 'green';   } })  new Vue({   el: '#app1',   data: {     message: 'Hello Vue.js!'   },   mounted() {     console.log('$color #app1:', this.$color);   } })  new Vue({   el: '#app2',   data: {     message: 'Hello Vue.js!'   },   mounted() {     console.log('$color #app2:', this.$color);   } })
<script src="https://unpkg.com/vue@2.5.15/dist/vue.min.js"></script>  <div id="app1">   <p>app1: {{ message }}</p> </div>  <div id="app2">   <p>app2: {{ message }}</p> </div>

Making $color reactive

To mave Vue react everywhere to changes to $color, you could use a Vuex store (see other answer).

But if you don't want to use Vuex just for that, another possibility is to create a Vue instance just to hold the "shared" data. After that, create a mixin with a computed property that references the $data of this "shared" Vue instance. See demo below.

// not using a Vuex store, but a separated Vue instance to hold the data // only use this if you REALLY don't want to use Vuex, because Vuex is preferrable let globalData = new Vue({   data: { $color: 'green' } }); Vue.mixin({   computed: {     $color: {       get: function () { return globalData.$data.$color },       set: function (newColor) { globalData.$data.$color = newColor; }     }   } })  // this.$color will be available in all Vue instances... new Vue({   el: '#app1' }) new Vue({   el: '#app2' }) // ...and components Vue.component('my-comp', {template: '#t3'}); new Vue({   el: '#app3', })
<script src="https://unpkg.com/vue@2.5.15/dist/vue.min.js"></script>  <div id="app1">Color: {{ $color }} <button @click="$color = 'red'">change to red</button></div> <div id="app2">Color: {{ $color }} <button @click="$color = 'yellow'">change to yellow</button></div>  <template id="t3">   <div>Color: {{ $color }} <button @click="$color = 'purple'">change to purple</button></div> </template> <div id="app3"><my-comp></my-comp></div>

For completeness, check below to see how using Vuex and Mixin would be (more details on how to use Vuex in the other answer).

// Using a Vuex to hold the "shared" data // The store is not added to any instance, it is just referenced directly in the mixin const store = new Vuex.Store({   state: { $color: 'green' },   mutations: { update$color: function(state, newColor) { state.$color = newColor; } } }); Vue.mixin({   computed: {     $color: {       get: function() { return store.state.$color },       set: function(newColor) { return store.commit('update$color', newColor); }     }   } })   // this.$color will be available in all Vue instances... new Vue({   el: '#app1' }) new Vue({   el: '#app2' }) // ...and components Vue.component('my-comp', {template: '#t3'}); new Vue({   el: '#app3', })
<script src="https://unpkg.com/vue@2.5.15/dist/vue.min.js"></script> <script src="https://unpkg.com/vuex@3.0.1/dist/vuex.min.js"></script>  <div id="app1">Color: {{ $color }} <button @click="$color = 'red'">change to red</button></div> <div id="app2">Color: {{ $color }} <button @click="$color = 'yellow'">change to yellow</button></div>  <template id="t3">   <div>Color: {{ $color }} <button @click="$color = 'purple'">change to purple</button></div> </template> <div id="app3"><my-comp></my-comp></div>


If you want a reactive global variable, Mixins may not be a good idea. Because even if you are using global Mixins, Vue actually import and inject this Mixin whenever mount new components, which means every time a new variable $color created.

I believe the mutable data types (Object or Array) combined with Vue.prototype can do the trick: In your main.js file:

Vue.prototype.$color = {value: "black"}; 

In your *.vue file:

this.$color.value = "red" 

In another *.vue file:

console.log(this.$color.value); // "red" 

Since you probably want $color to be a property that is not just available, but reactive (and the same) across all components, a possible solution is to use a quick/small Vuex store.

There's a runnable example below. In it you'll see three different Vue instances that will react to the same $color variable (that is at the Vuex store).

All three examples are functionally identical. I wrote them differently just to portrait different ways of using the API. Use what seems more intuitive for you.

const store = new Vuex.Store({   state: {     $color: 'green'   },   mutations: {     update$color: function(state, newColor) { state.$color = newColor; }   } });  new Vue({   store: store, // add this so the store is available   el: '#app1',   // explicitly via this.$store   computed: {     $color: function() { return this.$store.state.$color }   },   methods: {     update$color: function(newColor) { return this.$store.commit('update$color', newColor); }   } }) new Vue({   store, // shorthand for store: store   el: '#app2',   // using helpers mapState and mapMutations   computed: {     ...Vuex.mapState(['$color'])   },   methods: {     ...Vuex.mapMutations(['update$color'])   }, }) new Vue({   store,   el: '#app3',   // using computed properties, only   computed: {     $color: {       get: Vuex.mapState(['$color']).$color,       set: Vuex.mapMutations(['update$color']).update$color     }   }, })
<script src="https://unpkg.com/vue"></script> <script src="https://unpkg.com/vuex"></script>  <div id="app1">   Color: {{ $color }} <button @click="update$color('blue')">change to blue</button> (explicitly via this.$store) </div> <div id="app2">   Color: {{ $color }} <button @click="update$color('red')">change to red</button> (using helpers mapState and mapMutations) </div> <div id="app3">   Color: {{ $color }} <button @click="$color = 'orange'">change to orange</button> (using computed properties, only) </div>


Comments

Popular posts from this blog

Are Regular VACUUM ANALYZE Still Recommended Under 9.1?

Can Feynman Diagrams Be Used To Represent Any Perturbation Theory?