vuex的使用

Vuex

概念:状态管理模式

中文学习网址:
https://vuex.vuejs.org/zh/

安装

npm install vuex --save(或 -S)

引用

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

Vue.use(Vuex)

其解决了组件数据复杂传值的问题 更符合单项数据流:

view 		-----------> 		actions
			<---state<-----

其将组件中的data抽离出来 不在组件中大量的使用data

使用状态管理器:

1、新建文件夹及文件src/store/index.js

index.js
	import Vue from 'vue'
	import VueX from 'vueX'
	Vue.use(VueX)
	const store = new VueX.Store({
		modules: {

		}
	})
	export default store // 暴露模块

main.js
	import store from '@/store' // 引入要使用的vueX的模块	
	new Vue({
		el: '#app',
		store, // 在此调用模块 在任何一个组件中都可以用this.$store访问

2、以分类页面为例 练习使用vueX
注:以前的数据是存在vue文件下 export default { data () { return{ 该处存放数据 }}}
现在将数据放在如下文件中
新建文件夹及文件src/store/kind/index.js

const store = {
    state: { // 存放页面的状态

    },
    getters: { // 状态的衍生值 其实就是state的计算属性

    },
    actions: { // 处理组件中的异步操作

    },
    mutations: { // 唯一改变当前页面的状态的地方
        
    }
}
export default store

3、在store/index.js引入关于分类页面的状态管理

	import kindStore from './kind' 
	modules: {
       		kindStore
   	}

4、定义更改状态的方法

store/kind/index.js
	state: {
		bannerdata: ['banner1','banner2'],
    	prolist: ['pro1','pro2']
	},
	mutations: { 
		changeBannerData (state, data) { // state就是上面代码的state
			state.bannerdata = data // 改变状态管理器中的数据
		},
		changeProList (state, data) {
			state.prolist = data 
		}
	}

5、将初始化数据渲染到页面中

	kind.vue
	computed: { // 计算属性
		bannerdata () {
			return this.$store.state.kindStore.bannerdata
		},

	{{bannerdata}}

6、使用mapState辅助函数结合计算属性获取状态

	export default {
	name: 'kind',
	computed: { // 计算属性
		...mapState({	// 使用对象展开运算符 会将此对象混入到外部对象中
			bannerdata: state => state.kindStore.bannerdata,
			prolist: state => state.kindStore.prolist
		})
	{{bannerdata}}

7、请求数据渲染
新建src/api/kind/index.js — 用来请求数据

	import axios from 'axios'
	const api = {
		requestdata (url) {
			return new Promise((resolve, reject) => {
				axios.get(url).then(data => {
					console.log(data.data)
					resolve(data.data)
				}).catch(err => reject(err))
			})
		}
	}
	export default api
kind.vue
	import api from '@/api/kind'
	export default {
		……
	created () { // vue的生命周期钩子函数
		api.reqestdata('https://www.daxunxun.com/douban')
		.then(data => {
			this.$store.commit('changeProList', data) // 会触发api/kind/index.js中mutations-->changeProList方法
			this.$store.commit('changeBannerData', data)
		})
	}
	以上请求的数据会被渲染到store/kind/index.js中
		state: {
    		bannerdata: ['banner1', 'banner2'],	数据同步到该处

抽离异步请求

kind.vue
注释如下代码
// import api from '@/api/kind'
created () { // vue的生命周期钩子函数
    // api.reqestdata('https://www.daxunxun.com/douban')
    //   .then(data => {
    //     this.$store.commit('changeProList', data) // 会触发api/kind/index.js中mutations-->changeProList方法
    //     this.$store.commit('changeBannerData', data)
    // })

	//在钩子函数中添加该话执行异步请求 执行下段代码中的函数
	this.$store.dispatch('requestBannerdata')
	this.$store.dispatch('requestProlist')
}

即异步请求不在vue文件中执行了

src/store/kind/index.js
const store = {
  ……
  actions: { // 处理组件中的异步操作 将请求放在该处
    requestBannerdata (context) {
      api.requestdata('https://www.daxunxun.com/banner').then(data => {
        console.log(data)
        context.commit('changeBannerData', data) // 会触发api/kind/index.js中mutations-->changeProList方法
      })
    },
    requestProlist (context) {
      api.requestdata('https://www.daxunxun.com/douban').then(data => {
        console.log(data)
        context.commit('changeProList', data)
      })
    }
  },

使用mapAction分发action

以前分发action的方式为:
kind.vue
created () { // vue的生命周期钩子函数
	this.$store.dispatch('requestBannerdata')
    this.$store.dispatch('requestProlist')
}

修改代码为:

kind.vue
import { mapState, mapActions } from 'vuex' // 引入mapActions
export default {
  ……
  created () { // vue的生命周期钩子函数
    this.requestBannerdata()
    this.requestProlist()
  },
  methods: {
    ...mapActions([
      'requestBannerdata',
      'requestProlist'
    ])
  }
}

getters的使用

src/store/kind/index.js
const store = {
  ……
  getters: { // 状态的衍生值 其实就是state的计算属性
	year1994 (state) {
      		return state.prolist.filter(item => { // 过滤上面state中prolist数组的值
       			if (item.year >= 1994) {
          				return true // 返回true 得到满足条件的值
        			}
      		})
    	}
  },
kind.vue
// mapGetters 用来获取vuex中的getters
import { ……, mapGetters } from 'vuex'
export default {
  ……
  computed: { // 计算属性
    // year1994 () {
    //   return this.$store.getters.year1994
    // }, 或者如下

    // ...mapGetters({
    //   year1994: 'year1994'
    // }),或者如下

    ...mapGetters(['year1994']),

通过状态管理实现购物车

新建文件夹及文件
src/api/cart/index.js 代码如下

			const api = {
				requestdata () {
					const cartArr = [ // 模拟数据
						{
							id: 1,
							name: '方便面',
							num: 3,
							price: 1,
							flag: false // 该属性用来判断是否被选中
						},
						{
							id: 2,
							name: '火腿',
							num: 5,
							price: 3,
							flag: false // 该属性用来判断是否被选中
						},
						{
							id: 3,
							name: '面包',
							num: 2,
							price: 10,
							flag: false // 该属性用来判断是否被选中
						}
					]
					return new Promise((resolve, reject) => {
						// 模拟请求成功后的数据
						resolve(cartArr)
					})
				}
			}
			export default api

新建文件夹及文件
src/store/cart/index.js 代码如下


			import api from '@/api/cart'
			const store = {
				state: { // 存放页面的状态
					cartlist: []
				},
				getters: { // 状态的衍生值 其实就是state的计算属性
					totalPrice (state) { // 计算总价格
						return state.cartlist.reduce((sum, item) => {
							if (item.flag) { // 判断是否勾选
								return sum + item.price * item.num
							} else {
								return sum
							}
						}, 0)
					},
					totalNum (state) { // 计算总数量
						return state.cartlist.reduce((sum, item) => {
							if (item.flag) { // 判断是否勾选
								return sum + item.num
							} else {
								return sum
							}
						}, 0)
					}
				},
				actions: { // 处理组件中的异步操作
					requestdata (context) {
						api.requestdata().then(data => {
							console.log(data)
							context.commit('changeCartList', data)
						})
					}
				},
				mutations: { // 唯一改变当前页面的状态的地方
					changeCartList (state, data) { // state就是上面代码的state
						state.cartlist = data // 改变状态管理器中的数据
					}
				}
			}
			export default store

修改Cart.vue
代码如下

			<div class="content">
				<ul>
					<li v-for="item of cartlist" :key="item.id">
						<input type="checkbox" v-model="item.flag" />
						{{item.name}} ----{{item.price}} ---- {{ item.num }}
					</li>
				</ul>
				总价格:{{ totalPrice }} ---- 总数量:{{ totalNum }}
			</div>

			import {mapState, mapActions, mapGetters} from 'vuex'
			export default {
				computed: { // 计算属性
					...mapState({
						cartlist: state => state.cartStore.cartlist
					}),
					...mapGetters(['totalPrice', 'totalNum'])
				},
				methods: { // 方法
					...mapActions(['requestdata'])
				},
				created () {
					this.requestdata()
				},

修改src/store/index.js

import cartStore from './cart'	// 导入磨矿
const store = new VueX.Store({
	modules: {
		kindStore,
		cartStore		// 在此引入
	}
})

购物车实例代码下载网址入下:
https://github.com/vuejs/vuex/tree/dev/examples/shopping-cart

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值