vue+vuex初入门

Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

解决问题:

  • 传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。

  • 采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。

参考文档:

  • https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart
  • https://vuex.vuejs.org/zh-cn/getting-started.html

数据流动

开始

让我们做一个添加列表的功能

目录结构

 
├── index.css
├── index.js
├── store
│   ├── index.js
│   ├── main.js
│   └── modules
│       └── card.js
└── vue-mods
    ├── card.vue
    └── index.vue
 

定义store.js

 
import Vue from 'vue'
import Vuex from 'vuex'
​
import card from "./modules/card.js";
​
//初始化store
export default new Vuex.Store({
    //store的子模块
    modules : {
        card
    },
    //定义状态
    state : {
        msg : "hello, this msg is from vuex.store",
        name : "zhangjian",
        location : "zhengjiang"
    },
    //设置状态的获取,可以做一些特殊的定制
    getters : {
        detail : state => {
            return state.msg + state.name
        }
    },
    //mutation,用来修改state
    mutations : {
        CHANGE_LOCATION (state, location = "beijing"){
            state.location = location;
        }
    },
    //事件处理,主要是由外部触发store
    actions : {
        changeLocation ({ commit, state }){
            commit("CHANGE_LOCATION");//触发mutation
        },
        changeLocationAsync ({commit, state}, {location}){
            setTimeout(function (){
                commit("CHANGE_LOCATION", location);
            }, 1000);
        }
    }
});
 

modules/card.js ,和store.js和一致,只是输出的是一个模块

let state = {
    list : [],
    message : "this is card"
}
​
let getters = {
​
}
​
let mutations = {
    ADD_CARD (state, card){
        state.list.unshift(card)
    },
    UPDATE_MESSAGE (state, message){
        state.message = message;
    },
    DELETE_CARD_BY_INDEX (state, index){
        state.list.splice(index, 1);
    }
}
​
let actions = {
    addcard ({commit, state}, card){
        let message = state.message;
        let time = new Date().getTime();
​
        commit("ADD_CARD", {name : `${message} card - ${time}`})
    },
    updateMessage ({commit, state}, message){
        commit("UPDATE_MESSAGE", message);
    },
    deleteCard ({commit, state}, index){
        commit("DELETE_CARD_BY_INDEX", index);
    }
}
​
export default{
    state, getters, mutations, actions
}

入口文件 App.vue

<style lang="less">
</style>
<template>
    <div>
        <p>{{msg}}</p>
        <p>{{name}}</p>
        <p>{{location}}</p>
        <p>detail : {{detail}}</p>
        <button @click="change">change location</button>
        <button @click="asyncChange">async change location</button>
        <card></card>
    </div>
</template>
<script>
    import store from "../store/";
    import Card from "./card.vue";
​
    export default {
        components : {
            Card
        },
        store,
        created () {},
        computed : {
            msg (){
                return "msg : " + this.$store.state.msg
            },
            name (){
                return "name :" + this.$store.state.name
            },
            location (){
                return "location :" + this.$store.state.location
            },
            detail (){
                return this.$store.getters.detail
            }
        },
        ready() {
​
        },
        methods : {
            change (){
                this.$store.dispatch("changeLocation")
            },
            asyncChange (){
                this.$store.dispatch("changeLocationAsync", {
                    location : "china"
                });
            }
        },
        watch : {
        },
        filters: {
        }
      }
</script>

子模块 card.vue

 
<style lang="less">
</style>
<template>
    <div>
        <button @click="add">add card</button>
        <input type="text" name="" @input="updateMessage" :value="message">
        <span>{{cardCount}}</span>
        <div v-for="(index, card) in list">{{card.name}}<span @click="del(index)">x</span></div>
    </div>
</template>
<script>
    export default {
        components : {
        },
        computed : {
            list (){
                return this.$store.state.card.list
            },
            cardCount (){
                return this.$store.state.card.list.length;
            },
            message (){
                return this.$store.state.card.message
            }
        },
        created () {
            
        },
        ready() {
​
        },
        methods : {
            add (){
                this.$store.dispatch("addcard");
            },
            updateMessage (e){
                this.$store.dispatch("updateMessage", e.target.value)
            },
            del (index){
                this.$store.dispatch("deleteCard", index);
            }
        },
        watch : {
​
        },
        filters: {
        }
      }
</script>

附上webpack.config.js

var webpack = require('webpack');
var vue = require('vue-loader')
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
 
module.exports = {
    //插件项
    plugins: [
        new ExtractTextPlugin("[name].css")
    ],
    //页面入口文件配置
    entry: {
        index : './src/index.js'
    },
    //入口文件输出配置
    output: {
        path: './dist/',
        filename: '[name].js'
    },
    module: {
        //加载器配置
        loaders: [
            { test: /\.css$/, loader: ExtractTextPlugin.extract("css") },
            { test: /\.less$/, loader: ExtractTextPlugin.extract("css!less") },
            { test: /\.js$/, loader: "babel",query: {presets: ['es2015']},exclude: /node_modules/ },
            { test: /\.vue$/, loader: 'vue'}
        ]
    },
    vue : {
      loaders: {
        css: ExtractTextPlugin.extract("css"),
        less: ExtractTextPlugin.extract("css!less")
      },
      autoprefixer: { browsers: ["ios_saf >= 7", "android >= 4"] }
    },
    externals: {
        vue: "window.Vue",
        vuex : "window.Vuex"
    }
};

注意:这里,我针对vue和vuex2个仓库,做了一个全局引用,这样打包出来的boundle不会太大。

 

 

posted @ 2016-12-08 14:29  buzzjan  阅读(339)  评论(0编辑  收藏  举报