Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How watch global variable in component vuejs?

Tags:

vue.js

I need global variables for errors. But I don't want set input variable for every component. How I can watch $errors in component ABC without input variable?

(without <abc :errors="$errors"></abc>)

index.js:

Vue.prototype.$errors = {};

new Vue({
    el: '#app',
    render: h => h(App),
}

App.vue:

...
name: 'App',
components: {
ABC
}
...
methods:{
getContent() {
this.$errors = ...from axis...
}

Component ABC:

<template>
<div>{{ error }}</div>
</template>
...
watch: {
???
}
like image 269
Tom Avatar asked Dec 11 '22 01:12

Tom


1 Answers

Here's an example of how it could be done:

const errors = Vue.observable({ errors: {} })

Object.defineProperty(Vue.prototype, '$errors', {
  get () {
    return errors.errors
  },
  
  set (value) {
    errors.errors = value
  }
})

new Vue({
  el: '#app',
  
  methods: {
    newErrors () {
      // Generate some random errors
      const errors = {}
      
      for (const property of ['name', 'type', 'id']) {
        if (Math.random() < 0.5) {
          errors[property] = 'Invalid value'
        }
      }
      
      this.$errors = errors
    }
  }
})

new Vue({
  el: '#app2',
  
  watch: {
    $errors () {
      console.log('$errors has changed')
    }
  }
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>

<div id="app">
  <pre>{{ $errors }}</pre>
  <button @click="newErrors">New errors</button>
</div>

<div id="app2">
  <pre>{{ $errors }}</pre>
</div>

I've created two Vue instances to illustrate that the value really is shared. Clicking the button in the first instance will update the value of $errors and the watch is triggered in the second instance.

There are a few tricks in play here.

Firstly, reactivity can only track the reading and writing of properties of an observable object. So the first thing we do is create a suitable object:

const errors = Vue.observable({ errors: {} })

We then need to wire this up to Vue.prototype.$errors. By defining a get and set for that property we can proxy through to the underlying property within our observable object.

All of this is pretty close to how data properties work behind the scenes. For the data properties the observable object is called $data. Vue then uses defineProperty with get and set to proxy though from the Vue instance to the $data object, just like in my example.

like image 57
skirtle Avatar answered Dec 15 '22 10:12

skirtle