Vuex原来可以这样上手

     在Mvc模式大行其道的今天,后端通过各种Mvc框架实现视图与数据模型的隔离,而前端这方面也发展迅速。vue实现了Dom与viewModel双向绑定,使其视图的更新影响模型,模型的更新影响视图,你会不会觉得这就是Mvc库呢,实则不然,因为他还差一个重要的C(也就是控制器)。以下是鄙人对Mvc的个人理解,如有失误还请各位道友指正。

  • M:模型用于表示各种事物及事物特性的数据
  • v:view + viewModel,此处鄙人认为v不能单纯的理解为视图,而应该是视图+视图模型。
  • c:控制器,用于协调M与v之间的关系。

第一部分:我对vuex的理解

     这个重要的C是谁呢,鄙人认为就是此文章要介绍的Vuex(如果你想初识vue,可以移步vue原来可以这样上手这篇博文)。如此理解也是可以的:vue + vuex = 前端mvc框架

  • flux(单向数据流)
    • actions:一个动作,可以是view创建的,也可以是程序其他逻辑创建的
    • dispatcher:将业务逻辑与用户界面分离,负责响应action动作事件,并意向传遍整个系统
    • store:业务逻辑处理
    • view:视图
  • vuex是借鉴了flux、redux、The Elm Architecture等相关思想。

第二部分:揭开vuex面纱

本示例实现为一个输入框动态向下拉列表增加选择项的功能源码下载地址,先看效果图:


为了展示vuex的作用,此示例你可以看到如下内容:

  • 两个局部组件:输入和下拉列表组件
  • 一个全局组件:App,也是整个Vue实例的顶级组件
  • 一个jquery.js和bootstrap.js,用于实例下拉组件,jquery只辅助用于bootstrap。
  • 还有一个bootstrap.css,用于美化样式。

一、实现vuex的store实例

//Vue.use(Vuex);//如果是window引入方式,vuex会自动附加到Vue上。
var state = {
    list: [{"id":1, "name": "001"}]
};
var mutations = {
    ADDITEM: function(argState, item){
        argState.list.push(item);
    }
};
var getters = {
    getList:function(argState){
        return argState.list;
    }
}
var actions = {
    addItem:function(dis,item){
        dis.commit('ADDITEM',item);
    }
}
var _storeObj = new Vuex.Store({
    "state": state,
    "mutations": mutations,
    "getters": getters,
    "actions": actions
});

vuex更新数据流程:

  • dispatch可以是view视图中触发,也可以是程序业务逻辑来触发
  • actions通过commit方法发出一个改变事件
  • mutations中具体操作state的改变
  • state的改变通过getter暴露给view,state改变后会立即通知用getter关联起来的view。
  • 创建一个Vuex.Store的实例,用于Vue实例。

二、实现vue的组件

var inputComp = {
    render:function(createElement){
        var self = this; 
        return createElement('div',{
            attrs:{
                "data-id": "001"
            },
            class:{
                "form-inline":true
            },
            style:{
                "display": "inline-block"
            }
        },[createElement('input',{
           attrs:{
               type: 'text'
           },
           class:{
                "form-control": true
           },
           domProps:{
               value: self.value
           },
           on:{
               input:function(event){
                   self.value = event.target.value;
               }
           } 
        }),createElement('button',{
            on:{
                "click": function(event){
                   self.$store.dispatch('addItem',{"id":2,"name": self.value});
                }
            },
            class:{
                "btn":true,
                "btn-primary": true
            },
            domProps:{
                type: 'button'
            }
        },"添加")]);
    }
};
//下拉列表组件
var ComboComp = {
    render:function(createElement){ 
        var self = this;
        return createElement("div",{
            attrs:{
                "data-id": "ComboComp"
            },
            class:{
                "dropdown":true
            },
            style:{
                "display": "inline-block"
            }
        },[
            createElement("button",{
                class:{
                    "btn": true,
                    "btn-default": true,
                    "dropdown-toggle": true
                },
                attrs:{
                    "type": "button",
                    "id": "dr02",
                    "data-toggle": "dropdown"
                }
            },[ createElement("span", "选择"), createElement("span",{
                class:{
                    "caret":true
                }
            })])
            ,
            createElement("ul",
            {
                class:{
                    "dropdown-menu":true
                },
                attrs:{
                    "aria-labelledby":"dr02"
                }
            }, self.$store.getters["getList"].map(function(item){
                return createElement("li",item.name);
            }))
        ])
    }
};
Vue.component('App',{
    template:'<div class="wrap" ><ComboComp></ComboComp> <InputComp></InputComp></div>',
    components:{
        "InputComp": inputComp,
        "ComboComp": ComboComp
    }
});
  • inputComp(局部组件):提供输入
  • ComboComp(局部组件):实现列表内容的展示
  • App(全局组件):顶级组件,组合inputComp和ComboComp组件。
  • 组件参数说明:
    • render:返回一个组件,其中包含视图,data等。this为vue实例,参数是createElement方法,用于创建VNode。
  • 重点关注inputComp组件中button子元素的on中的click方法,内部用dispatch触发了store中对应Id的actions。
createElement('button',{
on:{
    "click": function(event){
       self.$store.dispatch('addItem',{"id":2,"name": self.value});
    }
}

三、输出

html部分代码:

<div class="wrap" id="app">
    <App></App>
</div>

js部分代码:

var _vue = new Vue({
    el: '#app',
    store: _storeObj
});
  • 视图中引入了App这个全局组件
  • 生成Vue实例的时候将vuex中创建的store实例传递进去。
posted @ 2017-02-12 21:48  小龙女先生  阅读(4420)  评论(0编辑  收藏  举报