zoukankan      html  css  js  c++  java
  • 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进行状态管理。

  • 相关阅读:
    BZOJ1229 USACO2008 Nov toy 玩具 【三分+贪心】*
    BZOJ1304 CQOI2009 叶子的染色 【树形DP】
    BZOJ1131 POI2008 Sta 【树形DP】
    BZOJ1096 ZJOI2007 仓库建设 【斜率优化DP】
    BZOJ4540 Hnoi2016 序列 【莫队+RMQ+单调栈预处理】*
    Codeforces 1012C Hills【DP】*
    POJ1741 Tree + BZOJ1468 Tree 【点分治】
    BZOJ2152 聪聪可可 【点分治】
    HDU1693 Eat the Trees 【插头DP】*
    RUAL1519 Formula 1 【插头DP】
  • 原文地址:https://www.cnblogs.com/axel10/p/10641279.html
Copyright © 2011-2022 走看看