一般情况下,我们开发一个vue项目,都是使用组件化的方式来进行开发,使得项目更加容易管理和维护。虽然组件化开发有其优点,但是缺点也存在,比如组件与组件之间的数据联动以及管理,父子组件传值还好说,组件与组件的传值那就麻烦了,而且不容易对数据进行管理。于是在这种情况下,vuex出来了,我们可以先到官方网站看vuex的具体介绍。
用大白话说就是vuex是一个公共数据存放仓库,其中的数据是和N个组件共享的,当在某个组件内改变了该数据,那么另一些与之关联的组件数据也会发生变化。下面来看基础的使用步骤:
- 1、下载安装:npm install vuex --save
- 2、创建一个存储数据的仓库,为了方便管理我们可以在src目录下创建一个store目录,然后在里面创建数据仓库文件index.js,具体代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// state为驱动应用的数据源
state: {
city: '北京'
}
})
- 3、我们需要将该数据仓库import到main.js中使关键字“store”成为全局能使用的API,具体代码如下:
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
- 4、由于我们在main.js将store这个玩意加载到了new Vue实例中,因此我们要在组件中调用数据仓库中存储的数据那就十分简单,下面看示例代码:
<div class="header-right">
{{this.$store.state.city}}
</div>
以上就是基础的vuex使用方式,下面我们需要实现的触发某事件,然后数据发生变化的操作,在开始看具体之前,先来琢磨一下官方给出的这张数据流向图:
结合这张图我们可知在组件中的数据是通过dispatch
这个方法传递出去,核心代码实现如下:
//HTML代码,定义一个方法,在方法中派发一个changeCity事件,并传递参数
<div class="title border-bottom">热门城市</div>
<div class="button-list">
<div class="button-wrapper" v-for="item of hot" :key="item.id" @click="handleCityClick(item.name)">
<div class="button">{{item.name}}</div>
</div>
</div>
//Vue实例代码,通过dispatch派发成一个事件,并接收传值然后再传出去
methods: {
handleCityClick (city) {
this.$store.dispatch('changeCity', city)
this.$router.push({
path: '/'
})
}
}
继续看官网的数据流向图,可以知道此时数据来到了存储数据的仓库,此时的代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '上海'
},
actions: {
//ctx参数代表上下文,与mutations进行通信,city是组件传递过来的数据
//commit()方法的作用是将city数据传递给MchangeCity这个方法
changeCity (ctx, city) {
ctx.commit('MchangeCity', city)
}
}
})
继续看官网的数据流向图,可以知道数据即将要来到最初始的位置,只要在这个位置将变动的代码传递给state即走完了整个流程,下面看具体代码:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: '上海'
},
actions: {
changeCity (ctx, city) {
ctx.commit('MchangeCity', city)
}
},
mutations: {
//state代表了最开始存放的区域,即驱动应用的数据源
MchangeCity (state, city) {
state.city = city
}
}
})
虽然以上就是完整的实现了组件之间数据联动的功能,但是事情还没结束呢,因为刷新页面时,数据还是会变回state中最初始的值,那么该怎么办呢?此时,就到了HTML5中的localstorage大显神威的时候了!下面请看具体代码,简直太简单了:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
city: localStorage.city || '上海'
},
actions: {
changeCity (ctx, city) {
ctx.commit('MchangeCity', city)
}
},
mutations: {
MchangeCity (state, city) {
state.city = city
localStorage.city = city
}
}
})
为了避免用户将浏览器的本地存储关闭而导致的错误使网站奔溃,我们应该编写以下更加合理的代码(代码真有意思,呵呵呵~):
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let defaultcity = '上海'
try {
if (localStorage.city) {
defaultcity = localStorage.city
}
} catch (e) {}
export default new Vuex.Store({
state: {
city: defaultcity
},
actions: {
changeCity (ctx, city) {
ctx.commit('MchangeCity', city)
}
},
mutations: {
MchangeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) {}
}
}
})
其实对于vuex数据的传递,我们还有一个简洁的方法,就是定义一个数组项来映射vuex中的数据,使HTML代码中调用数据的代码量减少,同时方便管理,下面看具体代码:
<!-- {{this.$store.state.city}}变成了this.city -->
<div class="header-right">
{{this.city}}
</div>
<script>
import { mspState } from 'vuex'
export default {
name: 'HomeHeader',
computed: {
...mapState(['city'])
}
}
</script>
<script>
//我们也能传递个对象过去
//此时this.city就要变成this.currentCity了
import { mspState } from 'vuex'
export default {
name: 'HomeHeader',
computed: {
...mapState({
currentCity: 'city'
})
}
}
</script>
在项目开发中,完整的代码可能是这样的,…mapState的作用不过是将在store保存好的数据返回而已。
<template>
<div class="apply">
<p class="p2">{{this.Lphone}}</p>
</div>
</template>
<script>
import axios from 'axios'
import { mapState } from 'vuex'
export default {
name: 'Apply',
data() {
return {
phone: ''
}
},
created() {
this.$nextTick(function() {
this.getloanerInfo()
})
},
computed: {
...mapState(['Lphone'])
},
methods: {
// 判断用户是否登录
getloanerInfo() {
let loanerInfo = sessionStorage.getItem('loanerInfo')
if(loanerInfo) {
let loanerInfoParse = JSON.parse(loanerInfo)
let phone = loanerInfoParse.loanerPhone
this.phone = phone
this.$store.dispatch('loaner', this.phone)
}
}
}
}
</script>
<style lang="stylus" scoped="scoped"></style>
<!--index.js-->
<script>
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
Lphone: ''
},
actions: {
loaner(ctx, info) {
ctx.commit('getLoaner', info)
}
},
mutations: {
getLoaner(state, info) {
state.Lphone = info
}
}
})
</script>
以上是单个数据的传递简洁写法,下面是传递多个数据方法的简洁写法:
<script>
import Bscroll from 'better-scroll'
//import进来mapActions这个玩意,这点得好好思考下为什么要import进mapActions,而不是其他,比如mapMutations
import { mapState, mapActions } from 'vuex'
export default {
name: 'CityList',
props: {
hot: Array,
cities: Object,
letter: String
},
computed: {
...mapState({
currentCity: 'city'
})
},
methods: {
handleCityClick (city) {
//直接使用这个方法传值,而不是this.$store.dispatch('changeCity', city)
this.changeCity(city)
this.$router.push({
path: '/'
})
},
//映射changeCity这个方法
...mapActions(['changeCity'])
}
}
</script>
通过这种方式,我们能够管理多个数据,下面请看具体代码
<template>
<div class="apply">
<p class="p2">{{this.xphone}}</p>
<p class="p2">{{this.xname}}</p>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
name: 'Apply',
data() {
return {
phone: ''
}
},
created() {
this.$nextTick(function() {
this.getloanerInfo()
})
},
computed: {
...mapState({
xphone: 'Lphone',
xname: 'Lname'
})
},
methods: {
// 判断用户是否登录
getloanerInfo() {
let loanerInfo = sessionStorage.getItem('loanerInfo')
if(loanerInfo) {
let loanerInfoParse = JSON.parse(loanerInfo)
let phone = loanerInfoParse.loanerPhone
let loanerName = loanerInfoParse.loanerName
this.phone = phone
// 接收手机号码和用户姓名到vuex中
this.loanerPh(phone)
this.loanerNa(loanerName)
} else {
this.isLogin = false
}
},
...mapActions(['loanerPh', 'loanerNa'])
}
}
</script>
<style lang="stylus" scoped="scoped"></style>
<!--index.js-->
<script>
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
Lphone: '',
Lname: ''
},
actions: {
loanerPh(ctx, info) {
ctx.commit('getPhone', info)
},
loanerNa(ctx, name) {
ctx.commit('getName', name)
}
},
mutations: {
getPhone(state, info) {
state.Lphone = info
},
getName(state, name) {
state.Lname = name
}
}
})
</script>
Vuex中getters的作用以及用法
getters这个对象有点类似计算属性computed,它能够实现将多个state区域中的属性值进行操作,具体看下面的代码:
首先定义好getters
//已经对state、actions和mutations这是三个区域的代码进行了封装
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import actions from './actions'
import mutations from './mutations'
Vue.use(Vuex)
export default new Vuex.Store({
state: state,
actions: actions,
mutations: mutations,
//getters中派发一个doubleCity方法,事件从state区域获得两个数据对其进行操作(这两个数据可以相同,也可以不同)
getters: {
doubleCity (state) {
return state.city + ' ' + state.city
}
}
})
接着在组件中使用派发出来的方法
<!--HTML结构代码-->
<div class="header-right">
{{this.doubleCity}}
<span class="iconfont arrow-icon"></span>
</div>
<!--vue实例代码-->
<script>
import { mapState, mapGetters } from 'vuex'
export default {
name: 'HomeHeader',
computed: {
...mapState(['city']),
...mapGetters(['doubleCity'])
}
}
</script>
Vuex中跳过actions的用法
我们在应用vuex的时候还可以将actions这个步骤直接忽略掉,使代码变得更加简洁
// 组件代码
let status = sessionStorage.getItem("systemStatus");
this.$store.commit('systemSta', status);
// vuex文件代码
state: {
systemStatus: ""
},
mutations: {
systemSta(state, value) {
state.systemStatus = value;
}
}
// 另一个组件代码
let status = this.$store.state.systemStatus;
以上关于Vuex的内容整理几乎都是大白话式的,为了更好的深入理解和学习Vuex,请立刻前来官方网站
热门评论
?