美文网首页转载的~vuevue
Vue.js状态管理工具Vuex快速上手

Vue.js状态管理工具Vuex快速上手

作者: _ihhu | 来源:发表于2017-03-10 15:10 被阅读6830次

    状态管理: 简单理解就是统一管理和维护各个vue组件的可变化状态(你可以理解成 vue 组件里的某些 data)

    Vuex是什么

    Vuex是集中的应用程序架构为了Vue.js应用程序状态管理。灵感来自 FluxRedux ,但简化的概念和实现是一个专门为 Vue.js 应用设计的状态管理架构。

    为什么要用vuex

    随着应用复杂度的增加,组件之间传递数据或组件的状态就会越来越多,如果我们按照最基本的方式来进行通信,代码就会变得十分混乱,特别在多人合作的时候。
    此时vuex出现了,他就是帮助我们把公用的状态全抽出来放在vuex的容器中,然后根据一定的规则来进行管理

    Vuex的核心

    Vuex.Store构造器

    Vuex 中 Store 的模板化定义如下:


    • state定义了应用状态的数据结构,同样可以在这里设置默认的初始状态。
        state:{
            todoLists:[],
        },
    
    • getters就是从state中派生出状态,比如获取state中todoLists的总数。类似vue中计算属性(computed)
        //Getters函数 接受 state 作为其第一个参数
        getters:{
            todoCount(state){
                return state.todoLists.length;
            }
        },
    
    • mutations是唯一允许更新应用状态的地方。类似vue中的$on事件:每个 mutation 都有一个字符串的事件类型 (type)和 一个回调函数 (handler)
        //和Getters函数一样 接受 state 作为其第一个参数
        mutations:{
            //新増 TodoList item
            ONADDTODO(state,item){
                state.aTodos.push(item);
            },
            //删除 TodoList item
            ONDELTODO(state,index){
                state.aTodos.splice(index,1);
            },
            //设置 错误提示信息
            ONERROR(state,str){
                state.massage=str;
            }
        },
    
    • actions定义提交触发更改信息的描述,在actions中可做任意异步操作,常见的例子有从服务端获取数据,在数据获取完成后会调用store.commit()(类似vue中$emit)来调用更改 Store 中的状态。可以在组件中使用dispatch来发出 Actions。
        //Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,
          因此你可以调用 context.commit 提交一个 mutation,
          或者通过 context.state 和 context.getters 来获取 state 和 getters
        actions:{
            //提交 ONADDTODO
            onAddTodo(context,item){
                if(item.value!=""){
                    context.commit("ONADDTODO",item);
                    context.commit("ONERROR","");
                }else{
                    context.commit("ONERROR","添加失败")
                }
            },
            //提交 ONDELTODO
            //可利用 ES2015 的 [参数解构] 来简化代码
            onDelTodo({commit},index){
                //commit=context.commit
                commit("ONDELTODO",index);
            }
    
        }
    
    • modules对象允许将单一的 Store 拆分为多个 Store 的同时保存在单一的状态树中。随着应用复杂度的增加,这种拆分能够更好地组织代码,更多细节参考这里

    Vuex辅助函数

    • Vuex.mapState(map: Array<string> | Object): Object
      创建组件的计算属性返回 Vuex store 中的状态。

    • Vuex.mapGetters(map: Array<string> | Object): Object
      创建组件的计算属性返回 getter 的返回值。

    • Vuex.mapActions(map: Array<string> | Object): Object
      创建组件方法分发 action。

    • Vuex.mapMutations(map: Array<string> | Object): Object
      创建组件方法提交 mutation。

    Vuex辅助函数具体用法参看:API文档

    TodoList示例

    在理解了 Vuex 的基础概念之后,我们会创建一个todolist来熟悉整个使用流程。

    • 使用vue-cli工具创建项目目录,并安装vuex
    vue init webpack-simple vue-vuex-todolist
    npm install 
    npm install vuex --save
    npm run dev   //启动项目
    
    • src 目录下创建名为 store 的目录来存放状态管理相关代码,首先创建 index.js
    import Vue from "vue";
    import Vuex from "vuex";
    Vue.use(Vuex);
    
    const store = new Vuex.Store({
        state:{
            massage:"",
            aTodos:[{value:"默认默认",id:0}],
        },
        getters:{
            nCounts(state){
                return state.aTodos.length;
            }
        },
        mutations:{
            //新増 TodoList item
            ONADDTODO(state,item){
                state.aTodos.push(item);
            },
            //删除 TodoList item
            ONDELTODO(state,index){
                state.aTodos.splice(index,1);
            },
            //设置 错误提示信息
            ONERROR(state,str){
                state.massage=str;
            }
        },
        actions:{
            //提交 ONADDTODO
            onAddTodo(context,item){
                if(item.value!=""){
                    context.commit("ONADDTODO",item);
                    context.commit("ONERROR","");
                }else{
                    context.commit("ONERROR","添加失败")
                }
            },
            //提交 ONDELTODO
            onDelTodo({commit},index){
                commit("ONDELTODO",index);
            }
    
        },
        modules:{}
    });
    
    export default store;
    
    • main.js 文件中将该 Store 实例添加到构造的 Vue 实例中
    import Vue from 'vue';
    import App from './App.vue';
    import store from './store';
    
    new Vue({
      el: '#app',
      store,
      render: h => h(App)
    })
    
    
    • src 目录下创建名为 components的目录来存放vue组件,并创建input.vue,list.vue文件

    input.vue

    <template>
        <div class="form-group ">
          <input type="text" class="form-control"  placeholder="" v-model="value"  />
          <button type="buttom" class="btn btn-default" @click="addItem">Add Item</button>
        </div>
    </template>
    <script>
        export default{
            data(){
                return {
                    value:"",
                    id:0
                }
            },
            methods:{
                addItem(){
                    let item={value:this.value,id:++this.id};
                    this.value="";
                    this.$store.dispatch("onAddTodo",item);
                }
            }
    
        }
    </script>
    <style lang="scss">
        %box{display:-webkit-box;-webkit-box-pack:center;-webkit-box-align:center;}
        .form-group{@extend %box;
            .form-control{-webkit-box-flex:1;}
        }
    </style>
    

    list.vue

    <template>
        <div class="todolist">
          <ul class="list-group">
            <li class="list-group-item" v-for="(item,index) in aTodos" >
                <span>{{item.value}}</span>
                <button class="btn btn-default" @click="delItem(index)">删除</button>
            </li>
           </ul>
        </div>
    </template>
    <script>
        import {mapState} from "vuex";
        export default{
            data(){
                return {}
            },
            methods:{
                delItem(index){
                    this.$store.dispatch('onDelTodo',index);
                }
            },
            computed:{
                ...mapState([
                    'aTodos'
                ])
            }
        }
    </script>
    <style lang="scss">
        %box{display:-webkit-box;-webkit-box-pack:center;-webkit-box-align:center;}
        .list-group-item{display: -webkit-box;-webkit-box-align:center;
            span{
                display: block;
                -webkit-box-flex:1;
            }
        }
    </style>
    
    • 修改App.vue文件
    <template>
      <div id="app">
        <h1>Vue.js Vue TodoList</h1>
        <hr>
        <todoInput />
        <todoList />
        <p>todoList 数量:{{todoCount}}</p>
        <pre>{{$store.state}}</pre>
      </div>
    </template>
    
    <script>
    import todoInput from './components/input.vue';
    import todoList from './components/list.vue';
    import {mapGetters} from "vuex";
    
    export default {
      name: 'app',
      data () {
        return {
          msg: 'Welcome to Your Vue.js App'
        }
      },
      computed:{
        ...mapGetters({
          todoCount:"nCounts"
        })
      },
      components:{
        todoInput,
        todoList
      }
    }
    </script>
    
    <style lang="scss">
      %box{display:-webkit-box;-webkit-box-pack:center;-webkit-box-align:center;}
      #app{width:400px;margin:0 auto;}
      h1{text-align:center;}
    </style>
    
    • index.html添加bootstrap.css
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <title>vue-vuex-demo</title>
        <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
        <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
      </head>
      <body>
        <div id="app"></div>
        <script src="/dist/build.js"></script>
      </body>
    </html>
    

    最后运行查看效果


    最后再附上:vuex入门demo无需依赖任何打包工具http://runjs.cn/code/7enrwlef

    相关文章

      网友评论

      本文标题:Vue.js状态管理工具Vuex快速上手

      本文链接:https://www.haomeiwen.com/subject/bajngttx.html