Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change Vue prototype variable in all components

Tags:

vue.js

vuejs2

I'm wanting to change the global variable below throughout the page

Vue.prototype.$color = 'green';

I tried using the code below but it only changes within the component I created

watch: {
   cor(newValue, oldVlue) {
       this.$color = newValue;
   }
}

is it possible for me to create a way to change the prototype variable across all components of the page?

like image 910
Rafael de Azeredo Avatar asked Mar 13 '18 12:03

Rafael de Azeredo


2 Answers

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/[email protected]/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/[email protected]/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/[email protected]/dist/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]/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>
like image 195
acdcjunior Avatar answered Sep 22 '22 17:09

acdcjunior


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"
like image 41
Shqi.Yang Avatar answered Sep 22 '22 17:09

Shqi.Yang