vuex简单使用

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,本文会介绍怎么使用vuex,比较简单,如果想对vuex有更深入的理解可以去看官方地址
https://vuex.vuejs.org/zh/

一、创建store

  1. 在工程根目录新建文件夹store
  2. 在store文件夹中新建index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const store = new Vuex.Store({
    state:{
        global_count: 1,
        global_name:'张三'
    },
    mutations:{
        //global_count自增函数
        increment (state){
            state.global_count++
        },
        //global_count自减函数
        reduction (state){
            state.global_count--
        },
        //给global_count赋值
        setCount (state,num){
            state.global_count=num
        },
        //给global_name赋值
        setName (state,n){
            state.global_name=n
        }
    }
})

export default store
  1. main.js挂载store
import store from './store'  
Vue.prototype.$store = store 

二、在index.vue中使用(同步)

index.vue中代码为

<template>
    <view class="content">      
                <!-- 自定义导航栏,使用colurui -->
        <cu-custom bgColor="bg-white solid-bottom">
            <block slot="content">相册</block>
        </cu-custom>
        <view>
            <view class="count-style">count={{global_count}},name={{global_name}}</view>
            <button @click="increase">++</button>
            <button @click="reduction">--</button>
            <button @click="setCount">赋值100</button>
            <button @click="setName">那么修改为abc</button>
            <button @click="push">跳转到第二页</button>
        </view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
            }
        },
        computed:{
            global_count(){
                return this.$store.state.global_count
            },
            global_name(){
                return this.$store.state.global_name
            }
        },
        onLoad() {
        },
        methods: {
            increase: function(){
                this.$store.commit('increment')
            },
            reduction: function(){
                this.$store.commit('reduction');
            },
            setCount: function(){
                this.$store.commit('setCount',100)
            },
            setName: function(){
                this.$store.commit('setName','abc')
            },
            push: function(){
                uni.navigateTo({
                    url: 'countDetail/countDetail',
                    success: res => {},
                    fail: () => {},
                    complete: () => {}
                });
            }
        }
    }
</script>

<style>
    .count-style{
        width: 750upx;
        height: 100upx; 
        text-align: center;
        line-height: 100upx;
        font-size: 40upx; 
        color: #DD524D;
    }
</style>

countDetail.vue中代码为

<template>
    <view>
        <cu-custom bgColor="bg-white solid-bottom" :isBack="true">
            <block slot="content">第二页</block>
        </cu-custom>
        <view class="count-style">count={{global_count}},name={{global_name}}</view>
        <button @click="jiajia">++</button> 
        <button @click="jianjian">--</button>
        <button @click="changeName">name修改为tony</button>
    </view>
</template>

<script>
    export default {
        data() {
            return {
            }
        },
        computed:{
            global_count(){
                return this.$store.state.global_count
            },
            global_name(){
                return this.$store.state.global_name
            }
        },
        methods: {
            jiajia: function(){
                this.$store.commit('increment')
            },
            jianjian: function(){
                this.$store.commit('reduction')
            },
            changeName: function(){
                this.$store.commit('setName')
            }
        }
    }
</script>

<style>
.count-style{
        width: 750upx;
        height: 100upx; 
        text-align: center;
        line-height: 100upx;
        font-size: 40upx; 
        color: #DD524D;
    }
</style>
效果图.gif

三、使用actions(可以实现异步修改)

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

一个异步操作的小例子:

incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const store = new Vuex.Store({
    state:{
        global_count: 1,
        global_name:'张三'
    },
    mutations:{
        //global_count自增函数
        increment (state){
            state.global_count++
        },
        //global_count自减函数
        reduction (state){
            state.global_count--
        },
        //给global_count赋值
        setCount (state,num){
            state.global_count=num
        },
        //给global_name赋值
        setName (state,n){
            state.global_name=n
        }
    },
    
    
    actions:{
        a: function(context){
            //处理异步逻辑
            context.commit('increment');
        },
        b: function(context){
            //处理异步逻辑
            context.commit('reduction');
        },
        c: function(context,num){
            //处理复杂逻辑
            context.commit('setCount',num);
        },
        d: function(context,n){
            //处理异步逻辑
            context.commit('setName',n)
        }
    },
})

export default store

index.vue代码为

<template>
    <view class="content">      
           <!-- 自定义导航栏,使用colurui -->
        <cu-custom bgColor="bg-white solid-bottom">
            <block slot="content">相册</block>
        </cu-custom>
        <view>
            <view class="count-style">count={{global_count}},name={{global_name}}</view>
            <button @click="increase">++</button>
            <button @click="reduction">--</button>
            <button @click="setCount">赋值100</button>
            <button @click="setName">那么修改为abc</button>
            <button @click="push">跳转到第二页</button>
        </view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
            }
        },
        computed:{
            global_count(){
                return this.$store.state.global_count
            },
            global_name(){
                return this.$store.state.global_name
            }
        },
        onLoad() {
        },
        methods: {
            increase: function(){
                this.$store.dispatch('a');
            },
            reduction: function(){
                this.$store.dispatch('b')
            },
            setCount: function(){
                this.$store.dispatch('c',100)
            },
            setName: function(){
                this.$store.dispatch('d','abc')
            },
            push: function(){
                uni.navigateTo({
                    url: 'countDetail/countDetail',
                    success: res => {},
                    fail: () => {},
                    complete: () => {}
                });
            }
        }
    }
</script>

<style>
    .count-style{
        width: 750upx;
        height: 100upx; 
        text-align: center;
        line-height: 100upx;
        font-size: 40upx; 
        color: #DD524D;
    }
</style>

countDetail.vue代码为

<template>
    <view>
        <cu-custom bgColor="bg-white solid-bottom" :isBack="true">
            <block slot="content">第二页</block>
        </cu-custom>
        <view class="count-style">count={{global_count}},name={{global_name}}</view>
        <button @click="jiajia">++</button> 
        <button @click="jianjian">--</button>
        <button @click="changeName">name修改为tony</button>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                
            }
        },
        computed:{
            global_count(){
                return this.$store.state.global_count
            },
            global_name(){
                return this.$store.state.global_name
            }
        },
        methods: {
            jiajia: function(){
                this.$store.dispatch('a')
            },
            jianjian: function(){
                this.$store.dispatch('b')
            },
            changeName: function(){
                this.$store.dispatch('d','Tony')
            }
        }
    }
</script>

<style>
.count-style{
        width: 750upx;
        height: 100upx; 
        text-align: center;
        line-height: 100upx;
        font-size: 40upx; 
        color: #DD524D;
    }
</style>

运行效果同上

四、对象展开运算符mapState

如果当前页面需要用到多个状态的时候我们需要在计算属性computed写多个声明,这回有些冗余,那么我们可以使用对象展开运算符mapState

<script>
    import {
        mapState
    } from 'vuex';
    export default {
        data() {
            return {
            }
        },
        computed:{
            ...mapState(['global_count','global_name'])
            // global_count(){
            //  return this.$store.state.global_count
            // },
            // global_name(){
            //  return this.$store.state.global_name
            // }
        },
        onLoad() {
        },
        methods: {
            increase: function(){
                this.$store.dispatch('a');
            },
            reduction: function(){
                this.$store.dispatch('b')
            },
            setCount: function(){
                this.$store.dispatch('c',100)
            },
            setName: function(){
                this.$store.dispatch('d','abc')
            },
            push: function(){
                uni.navigateTo({
                    url: 'countDetail/countDetail',
                    success: res => {},
                    fail: () => {},
                    complete: () => {}
                });
            }
        },
    }
</script>

五、Getter

我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:

store中的state

    state:{
        global_count: 1,
        global_name:'张三',
        global_arr: [{'name':'张零','score':88},
                    {'name':'张一','score':66},
                    {'name':'张二','score':44}]
    },

我们要筛选出60分以上的学生,那么我们可以在当前页面的计算属性中:

computed: {
    goodStudentNum(){
      return this.$store.state.global_arr.filter(todo=>todo.score>=60).length
    }
}

页面渲染

        <view>
            <view class="count-style">count={{global_count}},name={{global_name}},goodStuNum={{goodStudentNum}}</view>
            <button @click="increase">++</button>
            <button @click="reduction">--</button>
            <button @click="setCount">赋值100</button>
            <button @click="setName">那么修改为abc</button>
            <button @click="push">跳转到第二页</button>
        </view>
WechatIMG433.png

如果多个页面都需要使用筛选那么就需要写很多次,Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。

const store = new Vuex.Store({
  state:{
        global_count: 1,
        global_name:'张三',
        global_arr: [{'name':'张零','score':88},
                    {'name':'张一','score':66},
                    {'name':'张二','score':44}]
    },
  getters: {
    goodStudentNum: state => {
      return state. global_arr.filter(todo => todo. score>=60).length
    }
  }
})

使用

computed:{
            ...mapState(['global_count','global_name']),
            goodStudentNum(){
                return this.$store.getters.goodStudentNum
            },
        },

我们也可以从页面传入参数,例如传入要筛选的最小分数和最大分数

    getters:{
        goodStudentNum: (state) => (min,max) => {
            return state.global_arr.filter(todo => todo.score>=min&&todo.score<max).length
        }
    },
computed:{
            ...mapState(['global_count','global_name']),
            goodStudentNum(){
                return this.$store.getters.goodStudentNum(60,77)
            },
        },
WechatIMG434.png

Getter也有辅助函数mapGetter

        <view>
            <view class="count-style">count={{global_count}},name={{global_name}},goodStuNum={{goodStudentNum(60,77)}}</view>
            <button @click="increase">++</button>
            <button @click="reduction">--</button>
            <button @click="setCount">赋值100</button>
            <button @click="setName">那么修改为abc</button>
            <button @click="push">跳转到第二页</button>
        </view>
import {
        mapState,
        mapGetters
    } from 'vuex';
        computed:{
            ...mapState(['global_count','global_name']),
            ...mapGetters(['goodStudentNum']),
            // goodStudentNum(){
            //  return this.$store.getters.goodStudentNum(60,77)
            // },
        },

如果不使用store的方法,那么可以使用自定义的方法名跟其对应起来

mapGetters({
  // 把 `this.doneCount` 映射为 `this.$store.getters. goodStudentNum `
  doneCount: 'goodStudentNum'
})

gitHub: https://github.com/jizhigang/vuexDemo

参考文章
https://vuex.vuejs.org/zh/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335