在vue2中使用vuex的3版本:npm i vuex@3
在vue3中使用vuex的4版本:npm i vuex@4
导出vuex的状态配置: index.js
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- export default new Vuex.store({
- actions: {},
- state: {},
- mutations: {},
- getter: {},
- modules: {}
- })
全局配置: main.js
- import Vue from 'vue'
- import store from './store/index.js'
-
- // 在vue实例上注册使用
- new Vue({
- el: #app,
- render: h => h(APP),
- store
- })
注册全局状态
响应组件中的动作
修改state中的数据,可以被vuex的开发者工具检测到
依赖于state去计算出新值
如果页面中很多不同模块的组件都存储在vuex中,可以分模块
modules配置项可以实现
- import Vue from 'vue'
- import Vuex from 'vuex'
-
- // 命名空间nameSpace
- // 命名空间的作用是在使用mapState()、mapActions、mapMutations()的时候作为第一个参数,快速获取
- // 到各个模块的状态、action、mutations、getter
-
- const demo1 = {
- nameSpace: true,
- actions: {},
- state: {},
- mutations: {},
- getter: {},
- }
-
- const demo2 = {
- nameSpace: true,
- actions: {},
- state: {},
- mutations: {},
- getter: {},
- }
-
- export default new Vuex.store({
- modules: {
- demo1,
- demo2
- }
- })
有两种方法:
1、通过this.$store获取
如果项目中不分模块:
获取state:this.$store.state
获取getter: this.$store.getter
触发actions: this.$store.dispath()
触发mutations:this.$store.commit()
如果项目中分模块:
获取state:this.$store.state.模块名称
获取getter: this.$store.getter[‘模块名称/action名称’]
触发actions: this.$store.dispath(‘模块名称/action名称’)
触发mutations:this.$store.commit(‘模块名称/commit名称’)
2、通过mapState()、mapActions、mapMutations()、mapGetters()
如果项目中不分模块
以上方法只接收一个参数,可以是对象,也可以是数组
参数是对象:key是在项目中使用的方法名,value是store中的state名称,其他三个map方法使用类似
mapState({
key: value
})
参数是数组:每一项即是在项目中使用的名字,也是store中的名称
mapState([item, item1])
如果项目中区分模块:
以上方法接收两个参数,参数一是模块的名字, 参数二就是要引入的数据或者方法
以state为例,其他map方法都是类似的
mapState('模块名称', {})
mapstate('模块名称', [])
- // 第一步:pinia引入
- import {creatPinia} from 'pinia'
-
- // 第二步:创建pinia
- const pinia = creatPinia()
-
- // 第三步:安装pinia
- const app = cratApp()
- app.use(pinia)
pinia存储数据
- import {defineStore} from 'pinia'
-
- // defineStore接收两个参数,第一个参数是文件名字,第二个参数是store的配置项
- // 配置项目可以是选项式也可以是组合式
-
- // 选项式
- // 选项式第二个参数是对象
- export const useDemoStore = defineStore('demo', {
- // 配置状态
- // state是一个函数
- // 返回一个对象
- state() {
- return {
- demo: 1
- }
- },
-
- // 在这里可以获取this,this上有状态值
- action: {
- changeDemo() {
- this.demo = 3
- }
- }
- })
-
- // 组合式
- // 组合式第二个参数是函数
- import {ref} from 'vue'
- export const useDemoStore = defineStore('demo', () => {
- // 配置状态
- // 使用选项式API进行定义
- const demo = ref(0)
-
- // action中的函数正常写即可
- changeDemo() {
- demo = 3
- }
-
- // 如果要把这些状态和方法暴漏出去,需要有返回值
- return {
- demo,
- changeDemo
- }
- })
pinia读取数据
- // 首先把之前定义的demo引入
- import {useDemoStore} from './demo'
-
- // 之前定义的store有返回值,返回值中就有我们定义的方法和状态
- const demoStore = useDemoStore()
-
- // 获取状态
- // 第一种方法
- demoStore.demo
-
- // 第二种
- demoStore.$state.demo
- // 首先把之前定义的demo引入
- import {useDemoStore} from './demo'
-
- // 之前定义的store有返回值,返回值中就有我们定义的方法和状态
- const demoStore = useDemoStore()
-
- // 第一种:直接修改
- demoStore.demo = 2
-
- // 第二种: 可以批量修改
- demoStore.$patch({
- demo: 1,
- demo2: 2
- })
-
- // 第三种:使用action进行修改
- // 使用action进行修改的目的是如果是复杂的逻辑,可以进行服用
- demoStore.changeDemo({
- demo: 1,
- demo2: 2
- })
为什么要有这个API?
把全局状态引入之后,在使用的时候每次都要多取一层,这个的目的是把状态结构出来,并且是响应式的
- import {storeToRefs} from 'pinia'
-
- const demoStore = useDemoStore()
-
- const {demo} = storeToRefs(demoStore)
和vuex中的getter一样,都是计算状态值的
这个API的作用是来监听某个store中的值是否有变化,若是监听到变化可以做一些逻辑操作,类似于watch监听
- const demoStore = useDemoStore()
-
- const {demo} = storeToRefs(demoStore)
-
- // 接收一个函数作为参数
- // 函数接收两个参数,参数一是本次修改信息,参数二是state
- demoStore.$subscribe((mutate, state) => {})
- // store.js
-
- // 引入之前定义好的reduce的文件
- import demoReduce from './reduce/demoReduce.js'
-
- // 引入redux
- import {creatStore} from 'redux'
-
- // 导出store
- export default creatStore(demoReduce)
- // 引入store
- import store from './store'
-
- // 获取state
- store.getState().状态名称
-
- // 触发action
- store.dispath({type: '触发动作名字', data:‘传递的数据’})
是一个对象,接收一个对象
{
type: 触发的动作名称,
data: 触发时传递的数据
}
触发方式:dispath
异步action需要用到redux中applyMiddleware,执行中间件
处理异步action的中间件:redux-thunk
需要在creatStore中传入第二个参数注册中间件:creatStore(reduec, applyMiddleware(redux-thunk))
实质是一个函数,根据action中的type来处理数据
store.subscribe(),参数是一个箭头函数,可以拿到最新的state
store.getState()
需要使用redux中的combineReducers
- import {combineReducers} from 'redux'
- import demo1 from './demo1'
- import demo2 from './demo2'
-
-
- const reduces = combineReducers({
- demo1,
- demo2
- })
-
- export default creatStore(reduces)
在跟组件通过provide组件包裹根组件,并把store传入下层组件
1、数据改变试图更新的机制改变
redux使用store.sunscribe
react-redux使用provide注入组件之后,react-redux自己做了数据改变页面更新
2、使用store中的数据和方法改变
通过connect()()以props的方式注入到组件
- import {connect} from 'react-redux'
-
- // 第一种方式
- connect(
- (state)=>{
- return {
- demo1: state.demo1
- }
- },
- (dispath)=>{
- return {
- changeDemo1: dispath({type: 'changeDemo1', data,value})
- }
- }
- )(ui组件)
-
- // 第二种方式
- connect(
- (state)=>{
- return {
- demo1: state.demo1
- }
- },
- {
- changeDemo1: {type: 'changeDemo1', data,value}
- }
- )(ui组件)
observale/observer: 会使用到这俩装饰器,第一个是把普通状态定义为可以被mobx中的钩子函数监测的状态,第二个是把mobx和react组件进行关联
mobx存储数据
- import {observable, action} from 'mobx'
-
- class user {
- // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
- @observable demoName = '小刘'
-
- }
-
-
- // 通过props向下传递store中的数据
- ReactDOM.render(<App store={new user()} />, document.getElementById('#root'))
-
使用mobx中的数据
- import {observable, action} from 'mobx'
- import {observer} from 'mobx-react'
-
-
- // 组件中使用store
- // 从props中结构出store
-
- @observer
- class com extends React.component {
- render() {
- {store} = this.props
- }
- }
计算属性,类似于vue中的computed
- import {observable, computed} from 'mobx'
-
- class user {
- // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
- @observable demoName = '小刘'
-
- @computed get changeDemoName() {
- return this.demoName += '==='
- }
-
- }
对状态的操作
- import {observable, action} from 'mobx'
-
- class user {
- // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
- @observable demoName = '小刘'
-
- @action changeDemoName() {
- this.demoName += '==='
- }
-
- // action加一个限定词bound,目的是正确绑定实例this
- @acton.bound bchangeName() {
- this.demoName += '===bound改变'
- }
-
- // 异步action
- // action里面有异步操作,可以有以下三种方法
- @action syncChangName() {
- // 第一种
- 再写另外一个action去改变异步里面的值
- // 第二种
- // 第二个参数函数需要手动立即调用
- 使用action(‘方法名称’, 函数)
- // 第三种
- runInAction(() => {
- // 直接在这里改变状态值
- })
- }
-
- }
接收一个函数作为参数,默认会执行一次,当内部依赖的被观测值发生改变时会再执行一次
- import {observable, computed, autorun} from 'mobx'
-
- class user {
- // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
- @observable demoName = '小刘'
-
- @computed get changeDemoName() {
- return this.demoName += '==='
- }
-
- }
-
- autorun(() => {
- this.demoName += 'autorun监测改变'
- })
当满足条件时,只执行一次
接收两个函数作为参数,参数一是判断被监测的值是否满足条件,满足条件执行第二个函数
- import {observable, computed, when} from 'mobx'
-
- class user {
- // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
- @observable demoName = '小刘'
-
- @computed get changeDemoName() {
- return this.demoName += '==='
- }
-
- }
-
- when(() => {
- return a > 10
- }, () => {
- // 满足条件时执行代码
- })
初始化不会执行,也可手动停止监测,只有被监测的数据发生改变才会触发
接收两个函数作为参数,第一个参数的返回值会作为第二个函数参数的第一个参数,
第二个参数是一个函数,接收两个参数,第一个参数就是reaction第一个参数的返回值,第二个参数是reaction本身
- import {observable, computed, reaction} from 'mobx'
-
- class user {
- // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
- @observable demoName = '小刘'
-
- @computed get changeDemoName() {
- return this.demoName += '==='
- }
-
- }
-
- reaction(() => {
- return 10
- }, (data, reaction) => {
- // data是上个参数的返回值10
- // 第二个参数是reaction本身
- // 可以调用reaction.dispose()来停止继续监测的数据
- // 满足条件时执行代码
- })
微信中的全局状态管理使用的是mobx-miniprogram和westore两种、
注意:mobx-miniprogram搭配mobx-miniprogram-bindings
- import {
- observable,
- action
- } from "mobx-miniprogram";
-
-
- export observable({
-
- // data
- demo1: 1,
- demo2: 2,
-
- // action来改变数据
- updataDemo1: action(function(argument){})
-
- })
- import {
- createStoreBindings
- } from "mobx-miniprogram-bindings"
- import store from "../../store/index"
-
- Page({
- onLoad() {
- // 使用createStoreBindings将数据绑定到页面中
- this.storeBindings = createStoreBindings(this, {
- store,
- fields: ['demo1', 'demo2'],
- actions: ['updataDemo2']
- })
- },
-
- // count 递增
- increaseHandle() {
- this.updataDemo2(1)
- },
-
- // 页面卸载时,销毁当前页面的 store 绑定
- onUnload() {
- this.storeBindings.destroyStoreBindings();
- }
- })
1、createStoreBindings 方法调用会返回一个包含 updateStoreBindings,destroyStoreBindings 两个函数的对象,并且赋值给了当前页面实例的 storeBindings 属性。
2、当页面卸载(onUnload)时,调用 destroyStoreBindings 销毁当前页面的 store 绑定,避免造成内存泄露
3、updateStoreBindings函数涉及到延迟更新和立即更新的问题
3.1:为了提升性能,store中状态被更新时,不会立即更新到data中,而是在下次wx.nextTick()调用时才更新,可以减少setData的调用次数
3.2:如果想要立即更新,在页面中调用this.storeBindings.updateStoreBindings() ,在组件中调用this.updateStoreBindings()
- import {
- storeBindingsBehavior
- } from "mobx-miniprogram-bindings"
- import store from "../../store/index"
-
- Component({
- behaviors: [storeBindingsBehavior],
- storeBindings: {
- store,
- fields: ['demo2'],
- actions: ['updataDemo2']
- },
- methods: {
- // demo2 递增
- increaseHandle() {
- this.updataDemo2(1)
- }
- }
- })
直接在store文件夹下新建相应的.js文件就行
westore有俩个核心的api
创建页面
create(store,option)
创建组件
create(option)
更新页面或组件
this.update()
1、为了避免组件和页面中data的值被store中的值覆盖掉,使用store.data来访问
- // 创建单一的store
- export default {
- data: {
- userInfo: {
- name: 'zhangsan',
- age: 25,
- city: 'QingDao'
- },
- count: 0
- }
- }
-
- // 创建模块化store
- import user from "./user"
- import system from "./system"
-
- export default {
- data: {
- user,
- system
- }
- }
- import store from "../../store"
-
- create(store, {
- data: {
- count: null
- },
-
- // 更新 count
- increase() {
- this.store.data.count += 1
- this.update()
- }
- })
- import create from "../../utils/create"
-
- create({
- data: {
- count: null
- },
-
- methods: {
- increase() {
- this.store.data.count += 1
- this.update()
- }
- }
- })
this.update()方法返回一个promise对象,当视图层页面渲染完成后调用resolve()
- this.update()
- .then((data) => {
- console.log('视图已完成数据的更新', data)
- })