Vue.js的全局更新事件

时间:2018-03-24 15:38:13

标签: javascript vue.js

在Vue.js中,如果有任何组件更新其数据,有没有办法注册事件?

我的用例:我通过一组Javascript类建模RPG角色。 TCharacter类有几个可以修改的属性:名称,级别,HP,魔术。虽然" name"是一个简单的字符串," HP"和#34;魔术"是一个自定义类TResource,它有自己的消费和重新填充规则。

TCharacter类的实例是事实的来源,我创建了一些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 } }
})

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

现在,我希望每次用户进行修改时将角色对象保存到localstorage:更改其名称,点击消耗魔法点的按钮等。

因此,例如,我希望收到通知,ch.name的值已更改,因为用户在输入框中键入了某些内容。或者因为用户点击了一个按钮而丢失了一个魔法点。

我可以通过安装character处理程序检测updated()组件的更改,该处理程序会在修改DOM时通知我(viz)。但是,在修改子组件resource时,不会触发此操作。我需要为所有其他组件添加单独的updated()处理程序。这非常繁琐。

我想象的是一个全局updated()处理程序,它会在任何组件注册更改时随时触发。或者更好的是,指定update应该触发组件的子项的方法也会发生变化。

编辑:我已经重写了部分问题,以澄清我想要完成的事情。 有些人已经建议过Vuex。但是,根据我的理解,Vuex强制成为真理的唯一来源 - 我已经拥有单一的事实来源。 Vuex与众不同/更好?

2 个答案:

答案 0 :(得分:1)

您需要编写lancelot的序列化版本才能写出来。您可以使用computed执行此操作。然后你可以watch计算出来,看看有什么变化。

或者,您可以 watch每个特征,并在其发生变化时将其写出来。

&#13;
&#13;
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);
&#13;
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="main">
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

我不确定我是否完全理解用例,但如果我的假设是正确的,您需要根据对象的更新(对象属性的更新)更新组件,因为您可以使用{ {3}}。虽然我不确定您是否仅限于使用其他库

此处作为示例,您可以添加一个名为character的状态值,该值为object,类似于

const state = {
 character = {}; 
}

现在你可以使用vuex Vuex来改变这种情况。

commit('set_character', your_new_value)

既然你说你需要根据任何突变来更新所有或部分组件,请使用vuex mutations来监听该对象的任何变异,并更新组件的状态。

 store.subscribe(mutation => {
  if (mutation.type === 'set_character') {
    // do whatever you want here
  }
})

以上所有内容仅仅是基于您提到的内容的大纲,但这只是一个启动者,您可能会或可能不想将character添加到商店的状态中,而只是将这些属性添加到商店中为magichp