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
Post a Comment