Data Management

Introduce

In react/vue, we often use redux/vuex for data management and maintain a unified set of data. Under the Eva.js system, we have designed a set of data management system called EVAX, through EVAX we can maintain For a common data, components on multiple different objects may use the same data for logical operation.

For example, the life value in the game will not only be displayed on the top of the person’s head, but the characters in the game will also display different forms according to the number of life values. We bind the EVAX component to the game object to perform a certain data Monitor, if the data changes, you can manipulate the data or events on other components of the current game object.

Eva.js does not rely heavily on EVAX to develop games, and can be used as needed.

Install

With NPM

  1. npm i @eva/plugin-evax

In Browser

  1. <script src="https://unpkg.com/@eva/plugin-evax@1.2.x/dist/EVA.plugin.EVAX.min.js"></script>

Create store

All data needs to be defined in advance, if it is not defined, it will not be monitored

  1. // Create Store
  2. const store = {
  3. user: {
  4. name:'Mingfei',
  5. age: 18
  6. },
  7. items: [
  8. {
  9. id: 1,
  10. name: '20191111'
  11. }
  12. ]
  13. }

Initialize EVAX

  1. // Introduce the evax plugin
  2. import {EvaXSystem, EvaX} from '@eva/plugin-evax'
  3. // Create a game and pass it to the store
  4. const game = new Game({
  5. autoStart: true, // optional
  6. frameRate: 60
  7. })
  8. const store = {a: 1}
  9. const evaxSystem = new EvaXSystem({
  10. store // Here pass the defined store
  11. })
  12. game.addSystem(evaxSystem)
  13. const evaxManager = new GameObject('evaxManager')
  14. evaxManager.addComponent(
  15. new EvaX({
  16. events: {
  17. 'store.a': () => {}
  18. }
  19. })
  20. )
  21. game.scene.addChild(evaxMangager)

Monitor data changes

  1. // Add evax component
  2. go.addComponent(
  3. new EvaX({
  4. events: {
  5. 'store.user': {
  6. deep: true, // property changes under store.user will also trigger
  7. handler(store, oldStore) {
  8. console.log(this) // current component
  9. }
  10. },
  11. 'store.user.age'(store, oldStore) {},
  12. 'store.items.0'(store, oldStore) {
  13. // The attribute change under 0 will not be triggered, if you need to monitor, you need to set deep
  14. },
  15. 'store.items.0.name'(store, oldStore) {
  16. // name change will trigger
  17. },
  18. popUp(arg1, arg2) {
  19. // This is an event, refer to the following event trigger
  20. }
  21. }
  22. })
  23. )

update data

Update a single value

Directly modify the value on the object, if the value is the same as before, it will also trigger an event that listens for this value change

  1. store.user.name ='Cailun'
  2. // or
  3. evaxSystem.store.user.name ='Cailun'

evax.updateStore Update all values

Tip: updateStore and forceUpdateStore will only trigger the change of the last layer of attributes.

Full coverage mode updates, compare content changes, the changed content will trigger the update,

  1. const newStore = {
  2. user: {
  3. name:'Cailun',
  4. age: 18
  5. }
  6. }
  7. evaxSystem.emit('evax.updateStore', newStore)

The above operation will trigger the update of store.user.name because the age has not changed

evax.forceUpdateStore forces all values ​​to be updated

Full coverage mode update, all values ​​will be updated once, triggering the listening events of all properties

  1. const newStore = {
  2. user: {
  3. name:'Cailun',
  4. age: 18
  5. }
  6. }
  7. evaxSystem.emit('evax.forceUpdateStore', newStore)

The above operation will trigger the store.user.name and store.user.age data change events, even if there is no change

Events trigger

Use the emit method to trigger an agreed event, the event don’t use evax. at the beginning

  1. evaxSystem.emit('popUp', arg1, arg2, //...) // Event convention, event **do not** use evax. at the beginning

Monitoring method:

  1. // Add evax component
  2. go.addComponent(
  3. new EvaX({
  4. events: {
  5. popUp(arg1, arg2) {}
  6. }
  7. })
  8. )

Usage

Create a text

In this case, if the text on the Store changes, we modify the content of the text on the corresponding component

  1. // Create an object, the text component uses the name in the store
  2. const go = new GameObject('go')
  3. const txt = go.addComponent(new Text({ text:'' }))
  1. Generally speaking, our business logic is written in the script component. When the EVAX component receives the time or data change, the method on the script component is called.
  2. Hang some components that need to be modified, such as Text, on the properties of the script component for subsequent operations.
  1. // Create a custom component and put the method in the custom component
  2. class AScriptComponent extends Component{
  3. static componentName:'AScriptComponent',
  4. start() {
  5. this.txt = this.gameObject.getComponent('Text')
  6. // Use evax in the component to bind the evax component first, get the evax object on the evax component, and perform event triggering and modification
  7. const evax = this.gameObject.getComponent('EvaX')
  8. this.evax = evax.evax
  9. },
  10. setName(store, oldStore) {
  11. txt.text = store.user.name // Set new text content
  12. setTimeout(()=>{
  13. this.evax.emit('animationDown') // Notify that the modification is complete, and other components will take over the changes, not in this case
  14. this.evax.store.age += 1 // other components will take over the changes, not in this case
  15. }, 1000)
  16. },
  17. popUp(store) {
  18. // Do event corresponding operations
  19. }
  20. })
  21. // Add custom components
  22. const aScript = go.addComponent(new AScriptComponent)

Create an evax component, write the event that needs to be bound, and call the event on the custom component

  1. // Add evax component
  2. go.addComponent(
  3. new EvaX({
  4. events: {
  5. 'store.user.name'(store, oldStore) {
  6. // It is recommended to place the trigger method inside other custom components for use with subsequent scene editors
  7. go.getComponent(AScriptComponent).setName(store, oldStore)
  8. },
  9. 'store.user.age'(store, oldStore) {
  10. // ...
  11. },
  12. popUp(...args) {
  13. go.getComponent(AScriptComponent).popUp(...args)
  14. }
  15. }
  16. })
  17. )