Vue.js 2.x笔记:状态管理Vuex(7)

1. Vuex简介

  Vuex是为vue.js应用程序开发的状态管理模式,解决的问题:

    ◊ 组件之间的传参,多层嵌套组件之间的传参以及各组件之间耦合度过高问题

    ◊ 不同状态中的行为需要多份复制的问题

  Vuex采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

  核心思想:抽取组件的共享状态,以一个全局单例的模式进行管理。

  核心:store(仓库)

  核心组成:

    ◊ state:存放项目中需要多组件共享的状态变量

    ◊ getters:读取器,从state中派生出状态,如:将state中的某个状态进行过滤然后获取新的状态。

    ◊ mutations:修改器,存放更改state里状态的方法。

    ◊ actions:动作,mutation的加强版,可以通过commit mutations中的方法来改变状态,最重要的是可以进行异步操作。

    ◊ modules:模块化,将状态和管理规则模块化封装。

    

  Vuex文档:https://vuex.vuejs.org/zh/

2. Vuex基本使用

2.1 State

  npm安装:

npm install vuex -S

  基础示例:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>libing.vue</title>

    <script src="node_modules/vue/dist/vue.min.js"></script>
    <script src="node_modules/vuex/dist/vuex.min.js"></script>
</head>

<body>
    <div id="app">
        Copyright &copy; {{ author }} - 2018 All rights reserved
    </div>

    <script>
        Vue.use(Vuex);

        const store = new Vuex.Store({
            // 定义状态
            state: {
                //key: value
                author: 'Libing'
            }
        });

        new Vue({
            el: "#app",
            store: store,
            computed: {
                author: function () {
                    return this.$store.state.author
                }
            }
        });
    </script>
</body>

</html>

  vue-cli示例:

  

  /store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    // 定义状态
    state: {
        //key: value
        author: 'libing'
    }
})

  HelloWorld.vue

<template>
    <div>Copyright &copy; {{ author }} - 2018 All rights reserved</div>
</template>

<script>
export default {
    name: "HelloWorld",
    computed: {
        author: function() {
            return this.$store.state.author;
        }
    }
};
</script>
<template>
    <div id="app">
        <HelloWorld/>
    </div>
</template>

<script>
import HelloWorld from "./components/HelloWorld";

export default {
    name: "App",
    components: {
        HelloWorld
    }
};
</script>
App.vue

  main.js

import Vue from 'vue'
import App from './App'

import store from './store/index'

Vue.config.productionTip = false

new Vue({
    el: '#app',
    store,
    components: {
        App
    },
    template: '<App/>'
})

  mapState:当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,可以使用 mapState 辅助函数帮助生成计算属性。

  store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1,
    todos: [{
        id: 1,
        text: 'ToDo',
        status: false
      },
      {
        id: 2,
        text: 'Doing',
        status: false
      },
      {
        id: 3,
        text: 'Done',
        status: true
      }
    ]
  }
})

  Home.vue

<template>
    <div class="home">
        <ul>
            <li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
        </ul>
    </div>
</template>
<script>
import { mapState } from "vuex"

export default {
    computed: mapState({
        count: state => state.count,
        todos: state => state.todos,
        dones(state) {
            return state.todos.filter(todo => todo.status);
        }
    })
};
</script>

2.2 Getter

  Vuex 允许在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

  Getter 接受 state 作为其第一个参数:

  store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1,
    todos: [{
        id: 1,
        text: 'ToDo',
        status: false
      },
      {
        id: 2,
        text: 'Doing',
        status: false
      },
      {
        id: 3,
        text: 'Done',
        status: true
      }
    ]
  },
  getters: {
    dones: state => {
      return state.todos.filter(todo => todo.status);
    }
  }
})

  Getter 会暴露为 store.getters 对象,以属性的形式访问这些值:

  Home.vue

<template>
    <div class="home">
        <ul>
            <li v-for="todo in dones" :key="todo.id">{{ todo.text }}</li>
        </ul>
    </div>
</template>
<script>
export default {
    computed: {
        dones() {
            return this.$store.getters.dones;
        }
    }
};
</script>

  通过方法访问,让 getter 返回一个函数,来实现给 getter 传参。

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1,
    todos: [{
        id: 1,
        text: 'ToDo',
        status: false
      },
      {
        id: 2,
        text: 'Doing',
        status: false
      },
      {
        id: 3,
        text: 'Done',
        status: true
      }
    ]
  },
  getters: {
    dones: state => {
      return state.todos.filter(todo => todo.status);
    },
    getTodoById: (state) => (id) => {
      return state.todos.find(todo => todo.id === id);
    }
  }
})

  Getter 也可以接受其他 getter 作为第二个参数:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1,
    todos: [{
        id: 1,
        text: 'ToDo',
        status: false
      },
      {
        id: 2,
        text: 'Doing',
        status: false
      },
      {
        id: 3,
        text: 'Done',
        status: true
      }
    ]
  },
  getters: {
    dones: state => {
      return state.todos.filter(todo => todo.status);
    },
    donesCount(state, getters) {
      return getters.dones.length;
    }
  }
})

2.3 Mutation

  更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是实际进行状态更改的地方,并且它会接受 state 作为第一个参数。

  不能直接调用一个 mutation handler,要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit()。

  store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  }
})

  Home.vue

<template>
    <div class="home">
        {{ count }}
        <input type="button" value="添加" @click='handleIncrement'>
    </div>
</template>
<script>
export default {
    data() {
        return {
            count: this.$store.state.count
        };
    },
    methods: {
        handleIncrement() {
            this.$store.commit("increment");
            console.log(this.$store.state.count)
        }
    }
};
</script>

2.4 Action

  Action 类似于 mutation,不同在于:

    ◊ Action 提交的是 mutation,而不是直接变更状态。

    ◊ Action 可以包含任意异步操作。

  store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  mutations:{
    increment(state) {
      state.count++;
    }
  },
  actions:{
    plus(context){
      context.commit('increment')
    }
  }
})

  Home.vue

<template>
    <div class="home">
        {{ count }}
        <input type="button" value="添加" @click='add'>
    </div>
</template>
<script>
export default {
    computed: {
        count() {
            return this.$store.state.count;
        }
    },
    methods: {
        add() {
            this.$store.dispatch('plus');
        }
    }
};
</script>

3. Vuex插件

3.1 vuex-persist状态持久化

3.2 vuex-i18n语言本地化

原文地址:https://www.cnblogs.com/libingql/p/9224333.html