vuex 状态管理(重点)
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
集中式状态管理,可预期的对状态进行改变。
状态就是数据。
vuex 解决的是什么问题?
一个 vue 项目是由若干个组件组合而成的,复杂的组件关系中,数据如何来管理,以前用 eventbus 来解决,现在官方推出了 vuex ,我们用 vuex 来解决它。
安装 vuex
vuex 需要独立安装
npm install vuex -S
创建 store 对象
每一个 Vuex 应用的核心就是 store(仓库)
store 基本上就是一个容器
新建 store.js 页面,在里面写代码:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex); // 让每一个组件都能够使用vuex
// 创建vuex实例
const store = new Vuex.Store({
state : {
goods : []
}
})
// 导出模块
export default store;
将 store 注入到 vue 中
在 main.js 页面中引入 store
import store from './store.js';
new Vue({
store
})
vuex 提供了一些属性
- state 用来存储状态的容器
- mutations 用来存储改变state的方法的容器
- actions 用来存储异步代码和业务逻辑代码,组件页用户触发的是这个函数
- getters 类似计算属性
- modules 状态特别多时,可以用modules将状态进行分类
state
state 单一状态树:每个应用只能包含一个 store 实例。
state 就是用来存储状态的容器,状态就是数据。
store.js
const store = new Vuex.Store({
state: {
count: 0
}
});
abc.vue
export default {
data () {
return { }
},
computed: {
count(){
// 把vuex中的count属性赋给vue组件中count属性
return this.$store.state.count;
}
}
}
mutations
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
store.js
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
// 定义方法,这个方法的作用是更新count的状态
fn2(state){ state.count++; }
}
})
abc.vue
export default {
computed: {
count(){
return this.$store.state.count;
}
},
methods: {
fn(){
// 调用 vuex 中 mutations 中的方法
this.$store.commit('fn2');
}
}
}
<div @click="fn">{{count}}</div>
actions
业务逻辑代码和异步任务代码不应该写在 mutations 中,而应该写在 actions 中,这样的划分,是代码更具有层次,便于后期维护。
const store = new Vuex.Store({
state : {
count: 1
},
mutations : {
fn2(state, payload){
state.count++;
}
},
actions:{
fn1(context, payload){
context.commit('fn2');
}
}
})
abc.vue
export default {
computed: {
count(){
return this.$store.state.count;
}
},
methods: {
fn(){
// 调用 vuex 中 actions 中的方法
this.$store.dispacth('fn1');
}
}
}
<div @click="fn">{{count}}</div>
getters
getters 就是 vuex 中的计算属性,它具有缓存的特点。
const store = new Vuex.Store({
getters:{
allMoney( state ){
return 123
}
}
})
abc.vue
export default {
computed: {
allMoney(){
return this.$store.getters.allMoney;
}
}
}
辅助函数
- mapState 在vue组件页中,快速接收vuex中state中的数据。
- mapMutations 在vue组件页中,快速接收vuex中mutations中的数据。
- mapActions 在vue组件页中,快速接收vuex中actions中的数据。
- mapGetters 在vue组件页中,快速接收vuex中getters中的数据。
abc.vue
import {mapState, mapMutations, mapActions, mapGetters} from 'vuex'
export default {
computed: {
...mapState(['a']),
...mapGetters(['b'])
},
methods: {
...mapMutations(['c']),
...mapActions(['d'])
}
}
在组件页面中,使用辅助函数接收到的vuex数据,可以直接使用。
modules
一个项目中,代码特别多时,可以用模块将代码分割开。
store.js
const store = new Vuex.Store({
modules: {
a : {
state:...
mutations:...
actions:...
}
}
})
abc.vue
this.$store.state.a
在vue组件页获取模块中的state,需要用到模块名称;在模块页mutations、actions中不需要用模块名称就可以直接获取当前模块的state。
state 需要通过模块名称查找,而mutations、actions、getters是不需要的
例如:this.$store.dispatch('abc')
如果多个模块中都存在abc这个事件,那么这几个事件都会被触发。
namespaced
给模块设置命名空间后,调用mutations、actions、getters时,需要加上命名空间。
const store = new Vuex.Store({
modules:{
a : {
actions:{
add(){
console.log('a')
}
}
},
b : {
namespaced:true,
actions:{
add(){
console.log('b')
}
}
},
c : {
actions:{
add(){
console.log('c')
}
}
}
}
})
// 可以单独执行 b 模块下的 add 事件
this.$store.dispatch("b/add");
// 可以执行 a 和 c 模块下的 add 事件
this.$store.dispatch("add");
辅助方法及modules
{
methods:{
...mapActions({
sub : 'g/sub',
add : 'g/add'
})
},
computed:{
/*
goods(){
return this.$store.state.g.goods;
},
allMoney(){
return this.$store.getters['g/allMoney'];
}
*/
...mapState({
goods: (state,getters)=>{
return state.g.goods;
}
}),
...mapGetters({
allMoney: 'g/allMoney'
})
}
}
subscribe
每次执行vuex中mutation函数后,会自动触发订阅事件。
store.js
const store = new Vuex.Store({
...
})
store.subscribe((mutation, state)=>{
// 每次执行完 mutation 后,该订阅函数会被自动触发
})
plugin 插件
面试时如果问我们有没有封装个UI插件、定义过全局组件,其实说的就是 plugin 插件。
插件可以使一段程序更加独立,可以使用 npm install 下载使用。
使用插件注册全局组件
插件为 Vue 提供全局功能
plugins/abc/index.js 定义插件
const plugin = {
install(Vue, options){
Vue.component(options.a, {
render(createElement){
return createElement('div', `插件内容 ${options.b}`)
}
})
}
}
export default plugin
main.js 引入及使用
import abc from './plugins/abc/index.js'
Vue.use(abc, {a:"xyz", b:123})
// 当执行 Vue.use 时,实际执行的就是 abc对象中的 install 方法,options 接收 {a:"xyz",b:123}
因为定义插件时,注册的是全局组件,所以任意.vue页面中可以直接使用
<xyz></xyz>
toast 插件
index.js
import Toast from "./Toast.vue";
const toast = {}
toast.install = function(Vue, options){
const Comp = Vue.extend(Toast);
const vm = new Comp().$mount();
document.body.appendChild(vm.$el);
Vue.prototype.$toast = function(text){
vm.show = true;
vm.txt = text;
setTimeout(()=>{
vm.show = false;
}, 2000)
}
}
export default toast;
Toast.vue
<template>
<transition
enter-active-class="animated fadeIn"
leave-active-class="animated fadeOut"
>
<div class="toast" v-if="show">{{txt}}</div>
</transition>
</template>
<script>
export default {
data(){
return {
txt : "",
show : false
}
}
}
</script>
<style scoped>
.toast{
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
background:rgba(0,0,0,.8);
color: white;
padding: 10px;
border-radius: 5px;
}
</style>
main.js
import toast from './plugins/toast/index.js'
Vue.use(toast)
UI 框架
vue 中有很多 UI 框架,业内比较常用的是 “饿了吗” 提供的两款框架,分别是移动端的 Mint-UI,和 PC 端的 Element-UI。
Mint-UI
http://mint-ui.github.io/#!/zh-cn
环境
# 创建项目
vue create my-app
# 进入项目
cd my-app
# 下载 Mint-UI
npm install mint-ui -S
# 启动项目
npm run serve
使用
// main.js
import Mint from 'mint-ui'
import 'mint-ui/lib/style.css'
Vue.use(Mint) // 全局注册之后,任意的组件页就可以直接使用Mint提供的组件了。
<mt-button>按钮</mt-button>
Element-UI
http://element.eleme.io/#/zh-CN/component/installation
下载
npm i element-ui -S
使用
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
<el-button>Click Me</el-button>
网友评论