如何在组件 vuejs 中观察全局变量?

Tom*_*Tom 3 vue.js

我需要全局变量来处理错误。但我不想为每个组件设置输入变量。如何在没有输入变量的情况下观察组件 ABC 中的 $errors?

(without <abc :errors="$errors"></abc>)
Run Code Online (Sandbox Code Playgroud)

索引.js:

Vue.prototype.$errors = {};

new Vue({
    el: '#app',
    render: h => h(App),
}
Run Code Online (Sandbox Code Playgroud)

应用程序.vue:

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

组件 ABC:

<template>
<div>{{ error }}</div>
</template>
...
watch: {
???
}
Run Code Online (Sandbox Code Playgroud)

ski*_*tle 8

这是一个如何完成的示例:

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')
    }
  }
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>

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

<div id="app2">
  <pre>{{ $errors }}</pre>
</div>
Run Code Online (Sandbox Code Playgroud)

我创建了两个 Vue 实例来说明该值确实是共享的。在第一个实例中单击按钮将更新 的值,$errorswatch在第二个实例中触发。

这里有一些技巧。

首先,反应性只能跟踪可观察对象属性的读取和写入。所以我们要做的第一件事就是创建一个合适的对象:

const errors = Vue.observable({ errors: {} })
Run Code Online (Sandbox Code Playgroud)

然后我们需要将它连接到Vue.prototype.$errors. 通过为该属性定义一个getand set,我们可以代理到可观察对象中的底层属性。

所有这些都非常接近data属性在幕后的工作方式。对于data属性,可观察对象被称为$data。Vue 然后使用definePropertywithgetset来代理从 Vue 实例到$data对象,就像在我的例子中一样。