Vue 不使用Vuex的情況下進行狀態管理


在封裝自己的Vue ui庫的時候,往往要封裝一些比較復雜的組件,比如說table,form之類。這些組件由於功能繁雜,還涉及到子組件嵌套及通信,如果沒有一套狀態管理方案的話很容易導致代碼難以閱讀、難以維護、難以修改等問題,但引入vuex的話又過於沉重。鑒於業內已經有element-ui這樣比較成熟的案例,我們可以看看element-ui是怎么在沒有vuex的情況下進行狀態管理的。

Element-ui主要以兩種形式進行狀態管理:provider和自定義store。provider比較簡單,父組件將數據裝入providder,子組件用inject進行接收。這種方法優點是拿來即用,十分簡單。缺點是子組件無法修改數據。所有局限性還是比較大的。

第二種方法是封裝自定義store。我們參考element-ui中table組件,element-ui首先定義了一個table-store.js文件,存放store:

const TableStore = function(table, initialState = {}) {
  if (!table) {
    throw new Error('Table is required.');
  }
  this.table = table;

  this.states = {
    ...
  }

TableStore.prototype.mutations = {
    ...
}

TableStore.prototype.actions = {
    ...
}

除了沒有actions以外其他基本和vuex差不多。

element-ui寫tableStore用的是es5語法,這里用一個異步設置msg字段的typescript案例來進行講解:

export class TestStore {

  public states: IState = {
    msg: ''
  };

  public commit(action: string, ...args: any[]) {
    const mutations = this.mutations as any;
    if (mutations[action]) {
      mutations[action].apply(this, [this.states].concat(args));
    } else {
      throw new Error(`Action not found: ${action}`);
    }
  }

  public mutations = {
    setMsg(states: IState, msg: any) {
      states.msg = msg;
    }
  };
}

interface IState {
  msg: string
}

使用的時候先在父組件上掛載store並傳遞給子組件:

<template>
    <div class="home">
        <img alt="Vue logo" src="../assets/logo.png">
        <HelloWorld :store="store" />
        '
        <p>
            {{store.states.msg}}
        </p>
    </div>
</template>

<s cript lang="ts">
  import { Component, Vue } from 'vue-property-decorator';
  import HelloWorld from '@/components/HelloWorld.vue';
  import { TestStore } from '@/utils/testStore';

  @Component({
    components: {
      HelloWorld,
    }
  })
  export default class Home extends Vue {
    store: TestStore = new TestStore();
  }
</s cript>


然后子組件用props接受store,並提交setMsg操作:

<template>

</template>

<s cript lang="ts">
  import { Component, Prop, Vue } from 'vue-property-decorator';

  @Component({
  })
  export default class HelloWorld extends Vue {
    @Prop() private store!: any;

    public created() {
      setTimeout(() => {
        this.store.commit('setMsg', 'changed');
      }, 1000);
    }
  }
</s cript>

然后Home組件template中的msg就會在相應的時間更新。這樣我們就實現了不依賴vuex進行狀態管理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM