16

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?

1

5 Answers 5

19

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>

Sign up to request clarification or add additional context in comments.

4 Comments

I didn't like Vuex much, so I used MiniMongo from #Meteor with Mixin but I had to find a Vue native way as an alternative thank you.
Mixins are pretty complex and can slow Vue down, isn't there any other way to do this? How does Vuex do it?
This solution works well as if mutable instance property. Thank you for your showing good solution!
@NickSteele I reckon this is a bit late, but the vuex solution is in other answer to this same question.
13

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"

1 Comment

For some reason this is not the case when I test it, not sure if I am doing something wrong though...
4

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>

2 Comments

A more simple approach to your solution would be to just use the computed $color with a getter and setter. Then j you would just do let color = this.$color and this.$color = 'red'. With this approach to don't need updateColor method, because the setter will set the Vuex $color.
@Culda-DaisaAndrei see in the example the third Vue instance (look for #app3).
4

If you want a global reactive variable, you can use this.$root inside child components. There is an example in vuejs docs:

// The root Vue instance
new Vue({
  data: {
    foo: 1
  },
  computed: {
    bar: function () { /* ... */ }
  },
  methods: {
    baz: function () { /* ... */ }
  }
})
// Get root data
this.$root.foo

// Set root data
this.$root.foo = 2

// Access root computed properties
this.$root.bar

// Call root methods
this.$root.baz()

But consider using Vuex in most cases as official docs recommends.

Comments

0

Do this in the component as well

Vue.prototype.$color= 'colorName'

It worked for me.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.