Vuex初探之旅

Vuex是什么

关于Vuex是什么这个问题,官方给的答复案是:一个专为 Vue.js 应用程序开发的状态管理模式。所谓官方答案就等于标准答案,你能想得到的只能是参考答案。官方:你能想到?能看懂算我输…

就我个人的理解,Vuex是一个管理工具,专门负责管理页面中的共享数据,这里的管理可以理解为广义上的修改和查询。网友@世家将Vuex类比于数据库,简直是再合适不过了。

假定现在有这个一个场景:你的一个页面中存在两个模块module_a和module_b,这两个模块共享一个变量num,那么我们理所应当地想到把这个num定义为全局变量:window.num = xxx,然后在module_a和module_b中都使用window.num获取即可。那么当有100个共享变量的时候我再将这100个变量都挂载到window对象上,1000个?10000个呢?(当然没有人搞这么多,他这是作死)。这里想说的是把共享变量搞成全局可能面临的问题是不易分辨,你想啊,这么多变量命名方式不能和已知的和未知的官方命名相同,既然是共享的,那么某个模块在使用该变量的时候,其他模块是不是也应该在view上面有所体现,这个时候开发人员必须熟悉哪些模块使用了这该死的共享变量,然后逐个更新(oh,no此时我怀疑开发者心中定有千万只神兽奔腾而过)。

有人会说了,可以把这些数据放进数据库里面做持久化,这样让第三方软件代替保存着,每次请求以获取当前的值。恩,年轻人你的想法和当初开发Vuex的工程师想到一块儿了(只可惜太年轻,这个人头被他抢走了,可气的是连个助攻都没搞到手,是不是很失落?)。Vuex作为前端共享变量的临时数据库就这么不知不觉诞生了。

上面提到的共享模型我们用一个抽象的词语来形容——数据库,这是后端的叫法,前端我们叫它仓库或者商店(你想成背包都可以),起个高端的英文名叫store。有了仓库,仓库里存放的东西也就是共享变量(在数据库中叫数据结构)我们也给它起个名字,声明?规定?(还不错的名字,很有诗意和远方),也用个英文名装装逼,我们就叫它state吧。有了数据库和数据结构接下来大家会想到CURD,所谓的CURD是指数据库的增删改查,同样的我们的仓库也需要这样的操作,获取啦、修改啦(为什么没有删除和修改呢?这是模拟的数据库,只有声明和使用的用途所以不需要增加和删除),我们把获取起个名字叫getter,修改起个名字叫mutations。讲到这里你应该明白了,原来Vuex是搞这个事情的啊!另外,熟悉MVC结构的小伙伴都知道,要操作model层的数据要写一系列的API来暴露给controller,通俗地讲就是不能把仓库的钥匙直接提供给他人,你得找一个管理员带着你进仓库取东西,所以我们得封装一套修改仓库内容的API,我们叫它actions,这是暴露给调用它的模块。

上面介绍了这么多,想必你应该对Vuex有了初步的了解,下面我们看一下这个所谓的仓库长什么样?

{
    state: {
        …
    },
    mutations: {
        …
    },
    actions: {
        …
    },
    getters: {
        …
    }
}

没错,跟我们之前描述的一模一样,主要由这四部分构成。这时候你可能会失望,满心期待的高端技术就是这个玩意儿?(心中千万只…)

等等,别着急,我们下面看一个例子你就知道为什么要介绍这玩意儿了。(提示:下面的例子是建立在vue的基础之上,你要构建一个vue工程,包括webpack的构建才能进行后续的操作)

这个例子实现的功能是把输入的内容加上当前计数的值作为当前计数的值(说着很拗口),直接看图:

当前的值为1,输入的内容为0,点击按钮值还是1

输入变成3然后点击按钮当前值就变成了4,就是这么一个简单的应用我们分别使用vuex和不使用vuex实现。

整个工程结构如下:

首先创建第一个组件display.vue

<template>
    <div>
        <h4>Count is {{counts}}</h4>
    </div>
</template>

<script>
    export default {
        props: ['counts']
    }
</script>
创建第二个组件increment.vue

<template>
    <div>
        <input type="text" v-model="num">
        <button @click="addNum">Increment + {{num}}</button>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                num: 1
            }
        },
        methods: {
            addNum() {
                this.$emit('adds', parseInt(this.num))
            }
        }
    }
</script>
然后创建app.vue

<template>
    <div>
        <display :counts="count"></display>
        <increment @adds="add"></increment>
    </div>
</template>

<script>
    import display from '../page/display'
    import increment from '../page/increment'

    export default {
        data() {
            return {
                count: 0
            }
        },
        components: {
            display: display,
            increment: increment
        },
        methods: {
            add(num) {
                this.count += num
            }
        }
    }
</script>

<style scoped>
    h1, h2 {
      font-weight: normal;
    }

    ul {
      list-style-type: none;
      padding: 0;
    }

    li {
      display: inline-block;
      margin: 0 10px;
    }

    a {
      color: #42b983;
    }
</style>
创建main.js

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

new Vue({
    el: '#app',
    components: {
        myApp: App
    },
    template: '<my-app></my-app>'
})
创建index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <script type="text/javascript" src="build/index.bundule.js"></script>
</body>
</html>

Tip:以上代码使用的文件路径得换成自己的,否则会提示找不到文件。

接下来我们使用Vuex实现该功能,首先安装vuex模块:

npm install vuex –save-dev –registry=https://registry.npm.taobao.org
创建display.vue

<template>
    <div>
        <h4>Count is {{ getCount }}</h4>
    </div>
</template>

<script>
    import { mapGetters } from 'vuex'

    export default {
        computed: {
            ...mapGetters([
                'getCount'
            ])
        }
    }
</script>
创建increment.vue

<template>
    <div>
        <input type="text" v-model="num">
        <button @click='increment(num)'>Increment +{{num}}</button>
    </div>
</template>

<script>
    import { mapActions, mapGetters } from 'vuex'

    export default {
        data() {
            return {
                num: 1
            }
        },
        methods: {
            ...mapActions([
                'increment'
            ])
        },
        computed: {
            ...mapGetters([
                'getCount'
            ])
        }
    }
</script>
创建app.vue

<template>
    <div>
        <display></display>
        <increment></increment>
    </div>
</template>

<script>
    import display from '../page/display'
    import increment from '../page/increment'

    export default {
        components: {
            display: display,
            increment: increment
        }
    }
</script>

<style scoped>
    h1, h2 {
      font-weight: normal;
    }

    ul {
      list-style-type: none;
      padding: 0;
    }

    li {
      display: inline-block;
      margin: 0 10px;
    }

    a {
      color: #42b983;
    }
</style>
创建main.js

import Vue from 'vue'
import App from './app'
import store from '../vuex/store'

new Vue({
    el: '#app',
    store,
    data() {
        return {
            content: 'hello'
        }
    },
    components: {
        myApp: App
    },
    template: '<my-app></my-app>'
})
和第一种方式不同的是:我们得额外创建store.js

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

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        count: 1
    },
    mutations: {
        increment(state, amount) {
            state.count += parseInt(amount)
        }
    },
    actions: {
        increment(context, amount) {
            context.commit('increment', amount)
        }
    },
    getters: {
        getCount(state) {
            return state.count
        }
    }
})
index.html文件保持不变

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <script type="text/javascript" src="build/index.bundule.js"></script>
</body>
</html>

乍一看第二种方式代码量更多,这种装逼的方式难道失败了?答案是否定的,上完代码我们来分析一下代码顺便学习vuex是怎么使用的。

要使用vuex不仅要引入该模块还要讲该模块绑定到Vue上,具体代码是:

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

Vue.use(Vuex)


这个仓库创建好之后,需要使用的模块只需要引入该文件即可。在需要使用共享数据的地方vuex提供了mapGetters和mapActions这两个特殊的对象来获取。



值得注意的是,mapGetters可以直接放在methods里面当本组件的私有方法使用,mapGetters也能被当作计算属性使用。由于该组件的方法名称和store中一样,所以可以简写,如果不一样可以改写成这样:



Vuex的基础知识先介绍这些,明白了这些内容就可以解决多个组件中数据共享的问题。附上项目下载地址http://download.csdn.net/detail/lylwanan/9780956。内含代理工程,使用的时候先用npm安装依赖,然后将根目录下config.json文件中的path改为你的项目地址(config.json所在目录),然后双击run.bat即可。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值