javascript - Vue.js 的全局更新事件

标签 javascript vue.js

在 Vue.js 中,如果任何组件更新其数据,是否可以注册事件?

我的用例:我正在通过一组 Javascript 类对 RPG Angular 色进行建模。 TCharacter 类有几个可以修改的属性:名称、等级、HP、魔法。虽然“name”是一个简单的字符串,但“HP”和“magic”是一个自定义类TResource,它有自己的消耗和填充规则。

TCharacter 类的实例是事实来源,我创建了一些作为它的 View 的 Vue 组件。

我在 Vue 中创建了一个 character 组件和一个 resource 组件,大致如下:

<div class=template id=character>
   <input v-model="ch.name">
   <resource :attr="ch.magic"></resource>
   <resource :attr="ch.hp"></resource>
</div>

<div class="template" id="resource">
   you have {{ attr.available }} points
   <button @click="attr.consume">X</button>
</div>

<div id="main">
   <character :ch="lancelot"></character>
</div>

和 JavaScript:

class TCharacter {
  constructor() {
    this.name = "Lancelot"
    this.hp = new Resource(20)
    this.magic = new Resource(10)
  }
}

class TResource {
  constructor(limit) {
    this.available = limit
    this.limit = limit
  }

  consume() {
    if (this.available > 0) this.available--;
  }
}

let lancelot = new TCharacter()

Vue.component('character', {
  template: '#character',
  props: ['ch'],
})

Vue.component('resource', {
  template: '#resource',
  props: ['attr'],
})

new Vue({
  el: "#main",
  data() { return { lancelot } }
})

(我不确定代码是否完全按照编写的方式工作,但希望意图很明确。与此非常相似的东西已经为我工作了。)

现在,我想在每次用户进行修改时将 Angular 色对象保存到本地存储:更改其名称、单击消耗魔法点的按钮等。

例如,我希望收到通知,因为用户在输入框中输入了某些内容,所以 ch.name 的值发生了变化。或者因为用户点击了一个按钮而丢失了一个魔法点。

我可以通过安装 updated() 处理程序来检测 character 组件的更改,该处理程序会在 DOM 被修改时通知我 ( viz )。但是,当子组件 resource 被修改时,这不会触发。我需要向所有其他组件添加一个单独的 updated() 处理程序。这很快就会变得乏味。

我正在想象类似全局 updated() 处理程序的东西,它会在任何任何组件注册更改时触发。或者更好的是,指定 update 也应该在组件的子级更改时触发的方法。

编辑:我重新表述了问题的部分内容,以澄清我想要完成的任务。 你们中的一些人已经推荐了 Vuex。但是,据我了解,Vuex 强制成为单一事实来源——我已经拥有单一事实来源。 Vuex 有何不同/更好?

最佳答案

您将需要 lancelot 的序列化版本来编写。您可以使用 computed 来做到这一点。然后您可以观察计算结果以查看何时发生任何变化。

或者,您可以观察每个单独的特征,并在其变化时将其写下来。

class TCharacter {
  constructor() {
    this.name = "Lancelot"
    this.hp = new TResource(20)
    this.magic = new TResource(10)
  }
}

class TResource {
  constructor(limit) {
    this.available = limit
    this.limit = limit
  }

  consume() {
    if (this.available > 0) this.available--;
  }
}

let lancelot = new TCharacter()

Vue.component('character', {
  template: '#character',
  props: ['ch'],
})

Vue.component('resource', {
  template: '#resource',
  props: ['attr'],
})

const vm = new Vue({
  el: "#main",
  data() {
    return {
      lancelot
    }
  },
  computed: {
    serializedLancelot() {
      return JSON.stringify(this.lancelot);
    }
  },
  watch: {
    serializedLancelot(newValue) {
      console.log("Save update:", newValue);
    }
  }
});

setTimeout(() => {
  vm.lancelot.hp.consume();
}, 500);
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="main">
</div>

关于javascript - Vue.js 的全局更新事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49466584/

相关文章:

php - 如何使用 vuex 和 cookies 而不是使用 localStorage 使 vue.js 登录/注册

javascript - 将 HTML 附加到带有 JSON 数据的文档的正确方法

javascript - WordPress 被黑客入侵以包含反向链接

javascript - 如何从递归异步回调返回值?

javascript - 图像未在嵌套路由vue js中加载

javascript - 如何在vue loader组件中导入JS脚本?

javascript - 使用 `this` 的 JS 对象给出了未定义的结果

javascript - jQuery设置属性值问题

javascript - 我对所有值求和,但为什么它不适用于所有动态总计字段

javascript - 在 VueJS 中同时播放一个音频