vuex的使用、抽离异步组件(一)

安装好脚手架服务跑起来后,在src下新建vuex文件夹,vuex文件夹下新建js文件并配置:

我命名为index.js:

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

Vue.use(Vuex);

const store = new Vuex.Store({//创建仓库实例
	state:{//仓库中存放数据的地方
		count: 1
	}
})
export default store;


在入口文件main.js中引入并在vue实例中传入:

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './vuex' //这是利用了文件默认查找机制,找到./vuex/index.js文件

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,//告诉vue使用了仓库,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。
  components: { App },
  template: '<App/>'
})


创建一个单文件组件(pages/User.vue文件):

<template>
	<div class="user">
		<button @click="handleCount">改变count</button>
		{{count}}
	</div>
</template>

<script>
	export default{
		data(){
			return {

			}
		},
		computed: {
			count(){//如果去仓库拿数据,通过仓库实例对象 $store 
				return this.$store.state.count;
			}
		}
	}
</script>

<style>
	.user{
		background: red;
	}
</style>


说一下利用webpack的require.ensure实现异步组件+代码抽离(router/index.js):

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)
//异步组件的抽离,建立一个异步组件
//webpack的require.ensure webpack会将require.ensure中引入的代码从主boundle中抽离
// import Login from '@/pages/Login'
const Login =  r => require.ensure([], () => r(require('@/pages/Login.vue')), 'login')
const User=  r => require.ensure([], () => r(require('@/pages/User.vue')), 'login')

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },{
    	path: '/login',
    	name: 'Login',
    	component: Login
    },{
    	path: '/user',
    	name: 'User',
    	component: User
    }
  ]
})


目录结构:


获取数据:

辅助函数(语法糖)

当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键:

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

Vue.use(Vuex);

const store = new Vuex.Store({//创建仓库实例
	state:{//仓库中存放数据的地方
		count: 2,
		products: [{
			title: "东风标致", id: 8, buy: false
		},{
			title: "广州本田", id: 9, buy: true
		},{
			title: "一汽大众", id: 6, buy: true
		},{
			title: "东风悦达", id: 7, buy: true
		},{
			title: "长安铃木", id: 5, buy: false
		}]
	},
	getters: {//配置从state中衍生出来的数据
		tobuy(state){//默认第一个参数就是store的state
			return state.products.filter(v => v.buy);
		},
		nottobuy(state){
			return state.products.filter(v => !v.buy)
		}
	}
})
export default store;


获取tobuy、nottobuy数据:

<template>
	<div class="user">
		<button @click="handleCount">改变count</button>
		{{count}}
		<hr/>
		<ul>
			<li style="background:green">我要买的:</li>
			<li v-for="(v, i) in tobuy">{{v.title}}</li>
		</ul>
		<ul>
			<li style="background:orange">我不买的:</li>
			<li v-for="(v, i) in nottobuy">{{v.title}}</li>
		</ul>
	</div>
</template>

<script>
import {mapState, mapGetters} from 'vuex';//引入语法糖对象
	export default{
		data(){
			return {

			}
		},
		computed: {
			// count(){
			// 	return this.$store.state.count;
			// }
			// 当计算属性的key和store的state的属性名相同时可以用mapState,都需要es7...对象扩展运算符:
			...mapState(['count'])//数组语法
			// 当计算属性的key和srote的state的属性名不相同时:用对象语法,此时计算属性名称为counter
			// ...mapState({
			// 	counter: state => state.count
			// })
			,
			tobuy(){//同样state的衍生状态也可以使用语法糖,引入mapGetters,语法跟mapState一样
				return this.$store.getters.tobuy;
			},
			nottobuy(){
				return this.$store.getters.nottobuy;
			}
		},
		methods: {
			handleCount(){
				 console.log(this.count)
			}
		}
	}
</script>

<style>
	.user{
		background: red;
	}
</style>

渲染的结果:


改变数据:

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。

你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:

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

Vue.use(Vuex);

const store = new Vuex.Store({//创建仓库实例
	state:{//仓库中存放数据的地方
		count: 2,
		products: [{
			title: "东风标致", id: 8, buy: false
		},{
			title: "广州本田", id: 9, buy: true
		},{
			title: "一汽大众", id: 6, buy: true
		},{
			title: "东风悦达", id: 7, buy: true
		},{
			title: "长安铃木", id: 5, buy: false
		}]
	},
	getters: {//配置从state中衍生出来的数据
		tobuy(state){//默认第一个参数就是store的state
			return state.products.filter(v => v.buy);
		},
		nottobuy(state){
			return state.products.filter(v => !v.buy)
		}
	},
	mutations: {
		changeCount(state, payload){//第二个参数就是组件中传递过来的载荷
			state.count += payload;
		}
	}
})
export default store;

<template>
	<div class="user">
		<button @click="handleCount">改变count</button>
		{{count}}
		<hr/>
		<ul>
			<li style="background:green">我要买的:</li>
			<li v-for="(v, i) in tobuy">{{v.title}}</li>
		</ul>
		<ul>
			<li style="background:orange">我不买的:</li>
			<li v-for="(v, i) in nottobuy">{{v.title}}</li>
		</ul>
	</div>
</template>

<script>
import {mapState, mapGetters} from 'vuex';//引入语法糖对象
	export default{
		data(){
			return {

			}
		},
		computed: {
			// count(){
			// 	return this.$store.state.count;
			// }
			// 当计算属性的key和store的state的属性名相同时可以用mapState,都需要es7...对象扩展运算符:
			...mapState(['count'])//数组语法
			// 当计算属性的key和srote的state的属性名不相同时:用对象语法,此时计算属性名称为counter
			// ...mapState({
			// 	counter: state => state.count
			// })
			,
			tobuy(){//同样state的衍生状态也可以使用语法糖,引入mapGetters,语法跟mapState一样
				return this.$store.getters.tobuy;
			},
			nottobuy(){
				return this.$store.getters.nottobuy;
			}
		},
		methods: {
			handleCount(){
				 this.$store.commit("changeCount", 5)//提交一个名为changeCount的mutation,第二个可选参数表示载荷,也可以是一个对象传入,也可以将type和载荷写成一个对象传入{type: 'changeCount', payload: 5}
				 console.log(this.count)

			}
		}
	}
</script>

<style>
	.user{
		background: red;
	}
</style>

使用常量替代 Mutation 事件类型

使用常量替代 mutation 事件类型在各种 Flux 实现中是很常见的模式。这样可以使 linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然:

可以单独新建一个js文件命名为mutation-types.js专门用来配置要用到的事件类型名称的常量(变量大写是规范,不过这里最好值也大写,不然在后面用mapMutations的数组语法糖时会报出常量未定义的错):

export const CHANGECOUNT = 'CHANGECOUNT';

并更改mutation事件属性名,es6对象的动态属性写法:

mutations: {
		[CHANGECOUNT](state, payload){//第二个参数就是组件中传递过来的载荷
			state.count += payload;
		}
	}


然后在store文件中和其他用到的组件页引入:

import {CHANGECOUNT} from './mutation-types';
同样更改触发 mutation事件的事件属性名:


methods: {
			handleCount(){
				 this.$store.commit(CHANGECOUNT, 5)//提交一个名为changeCount的mutation,第二个可选参数表示载荷,也可以是一个对象传入,也可以将type和载荷写成一个对象传入{type: 'changeCount', payload: 5}
				 console.log(this.count)

			}
		}

同时mutation的所有事件函数中不能有异步,因为vue要监视状态的改变,数据和对应的状态必须一致。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值