vue:vuex(状态管理器)

Vuex

vuex-store

最简单的store.js

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

Vue.use(Vuex);

const store = new Vuex.Store({
	state:{
		count:3
	},
	mutations:{
		increment(state){
			state.count++;
		}
	}
})
store.commit('increment');
console.log(store.state.count);//4

State:单一状态树、唯一数据源、与Vue实例中的data遵循相同的规则、和模块化不冲突

State

1、如何在 Vue 组件中展示状态呢?

由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态;
每当 store.state.count 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。

1.1 计算属性

// 创建一个 Counter 组件
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

然而,这种模式导致组件依赖全局状态单例。在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入,并且在测试组件时需要模拟状态。

1.2 Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中(需调用 Vue.use(Vuex)

const app = new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})

mapState

vuex-mapState

// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 箭头函数可使代码更简练
    count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}

当映射的计算属性的名称state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

computed: mapState([
  // 映射 this.count 为 store.state.count
  'count'
])
对象展开运算符(…):将…mapState与外部对象放在一起

对象展开运算符
不是所有的状态都需要放到Vuex,有的明显是局部的状态就放到单个的组件中。

Getter

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算
Getter 接受 state 作为其第一个参数:

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})
怎么访问Getters?

1、通过属性访问
Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值store.getters.doneTodos

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
	state: {
		todos: [{
				id: 1,
				text: '...',
				done: true
			},
			{
				id: 2,
				text: '...',
				done: false
			}
		]
	},
	getters: {//vuex中的“计算属性”
		doneTodos: state => {
			return state.todos.filter(todo => todo.done)
		}
	},
	mutations: {
		
	}
})
console.log(store.getters.doneTodos)

在这里插入图片描述
计算过滤处理的数组长度

getters: {//vuex中的“计算属性”
		doneTodos: state => {
			return state.todos.filter(todo => todo.done)
		},
		doneTodosCount: (state, getters) => {
		    return getters.doneTodos.length
		  }
	},
console.log(store.getters.doneTodosCount)

注意:getter 在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的

通过方法访问
getters: {
  // ...
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}

注意,getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果

mapGetters

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性import { mapGetters } from 'vuex'

在这里插入图片描述

mutations

  1. Mutation 需遵守 Vue 的响应规则
  2. 使用常量替代mutation的事件类型
  3. Mutation 必须是同步函数
  4. 在组件中提交 Mutation

在这里插入图片描述

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

Vue.use(Vuex);

const store = new Vuex.Store({
	state: {
		count: 3,
		},
mutations: {
		increment(state) {
			state.count++;
		},
		incrementByN(state,n){
			state.count+=n
		}
	}
	});
store.commit('increment');
console.log(store.state.count);//4
store.commit('incrementByN',10);
console.log(store.state.count);//14
提交载荷(Payload)
incrementByN(state,n){
	state.count+=n
}

注意:通常情况下,载荷是一个对象,可以包含多个字段。

.....
incrementByOBJ(state,payload){
	state.count+=payload.amount
}
......
store.commit('incrementByN',{amount:5});//可以使用
//一般情况下如下书写commit:对象风格的提交方式
store.commit({
	type:'incrementByOBJ',
	amount:20
});

mutation更多参考官网上

.....
const store = new Vuex.Store({
	state: {
		obj:{},
	}
})
//当需要在对象上添加新属性时
Vue.set(store.state.obj, 'newProp', 123)
console.log(store.state);

vue.set

//以新对象替换老对象
store.state.obj = { ...store.state.obj, newProp: 789 }
console.log(store.state);//

规则2:使用常量替代mutation的类型

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})
mutation必须是同步函数,异步逻辑都应该封装到 action 里面
someMutation (state) {
        api.callAsyncMethod(() => {
            state.count++
        })
    }
在组件中提交mutation

在这里插入图片描述
更多:
1、Vuex 的 store 接受 plugins 选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数,它接收 store 作为唯一参数:

const myPlugin = store => {
  // 当 store 初始化后调用
  store.subscribe((mutation, state) => {
    // 每次 mutation 之后调用
    // mutation 的格式为 { type, payload }
  })
}
const store = new Vuex.Store({
  // ...
  plugins: [myPlugin]
})

函数说明:

store.subscribe: subscribe,调用此方法返回的函数可停止订阅。》??在vue内声明一个变量,用来接住subscribe返回的函数,然后在beforeDestroy中调用其返回的函数即可
api.callAsyncMethod:api异步执行函数

2、如何将状态和状态变更事件分布到各个子模块中?


推荐
vue#data
Array的filter方法
vuex学习推荐
更多冷门知识推荐
vue构造函数(根实例化时和组件实例对象选项)参数:选项详解

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值