vue2的状态管理
vuex
vuex官网:https://vuex.vuejs.org/
vuex安装
在vue2中使用vuex的3版本:npm i vuex@3
在vue3中使用vuex的4版本:npm i vuex@4
vuex全局配置使用
导出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
})
vuex中的state配置项
注册全局状态
vuex中的actions配置项
响应组件中的动作
vuex中的mutations配置项
修改state中的数据,可以被vuex的开发者工具检测到
vuex中的getter配置项
依赖于state去计算出新值
vuex中的modules配置项,实现模块化
如果页面中很多不同模块的组件都存储在vuex中,可以分模块
modules配置项可以实现
import Vue from 'vue'
import Vuex from 'vuex'// 命名空间nameSpace
// 命名空间的作用是在使用mapState()、mapActions、mapMutations()的时候作为第一个参数,快速获取
// 到各个模块的状态、action、mutations、getterconst demo1 = {nameSpace: true,actions: {},state: {},mutations: {},getter: {},
}const demo2 = {nameSpace: true,actions: {},state: {},mutations: {},getter: {},
}export default new Vuex.store({modules: {demo1,demo2}
})
在组件中获取store中的数据
有两种方法:
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('模块名称', [])
vue3的状态管理
pinia
pinia官网:Pinia | The intuitive store for Vue.js
pinia安装: npm i pinia
pinia使用:
// 第一步:pinia引入
import {creatPinia} from 'pinia'// 第二步:创建pinia
const pinia = creatPinia()// 第三步:安装pinia
const app = cratApp()
app.use(pinia)
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
pinia修改状态
// 首先把之前定义的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
})
storeToRefs
为什么要有这个API?
把全局状态引入之后,在使用的时候每次都要多取一层,这个的目的是把状态结构出来,并且是响应式的
import {storeToRefs} from 'pinia'const demoStore = useDemoStore()const {demo} = storeToRefs(demoStore)
getters
和vuex中的getter一样,都是计算状态值的
$subscribe
这个API的作用是来监听某个store中的值是否有变化,若是监听到变化可以做一些逻辑操作,类似于watch监听
const demoStore = useDemoStore()const {demo} = storeToRefs(demoStore)// 接收一个函数作为参数
// 函数接收两个参数,参数一是本次修改信息,参数二是state
demoStore.$subscribe((mutate, state) => {})
react的状态管理
redux
react-redux
mobx
mobx中文文档:https://cn.mobx.js.org
mobx安装:npm i mobx mobx-react
mobx存储和读取数据
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}
}
mobx修改状态
computed
计算属性,类似于vue中的computed
import {observable, computed} from 'mobx'class user {// 熟悉类的装饰器,会更好理解当前的状态和函数的定义@observable demoName = '小刘'@computed get changeDemoName() {return this.demoName += '==='}}
action
对状态的操作
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(() => {// 直接在这里改变状态值})}}
mobx的动态检测
autorun
接收一个函数作为参数,默认会执行一次,当内部依赖的被观测值发生改变时会再执行一次
import {observable, computed, autorun} from 'mobx'class user {// 熟悉类的装饰器,会更好理解当前的状态和函数的定义@observable demoName = '小刘'@computed get changeDemoName() {return this.demoName += '==='}}autorun(() => {this.demoName += 'autorun监测改变'
})
when
当满足条件时,只执行一次
接收两个函数作为参数,参数一是判断被监测的值是否满足条件,满足条件执行第二个函数
import {observable, computed, when} from 'mobx'class user {// 熟悉类的装饰器,会更好理解当前的状态和函数的定义@observable demoName = '小刘'@computed get changeDemoName() {return this.demoName += '==='}}when(() => {return a > 10
}, () => {// 满足条件时执行代码
})
reaction
初始化不会执行,也可手动停止监测,只有被监测的数据发生改变才会触发
接收两个函数作为参数,第一个参数的返回值会作为第二个函数参数的第一个参数,
第二个参数是一个函数,接收两个参数,第一个参数就是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()来停止继续监测的数据// 满足条件时执行代码
})
小程序的状态管理
mini-program
微信中的全局状态管理使用的是mobx-miniprogram和westore两种、
注意:mobx-miniprogram搭配mobx-miniprogram-bindings
创建store
import {observable,action
} from "mobx-miniprogram";export observable({// datademo1: 1,demo2: 2,// action来改变数据updataDemo1: action(function(argument){})})
在页面中使用store
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()
在组件中使用store
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划分模块
直接在store文件夹下新建相应的.js文件就行
westore
westore有俩个核心的api
创建页面
create(store,option)
创建组件
create(option)
更新页面或组件
this.update()
1、为了避免组件和页面中data的值被store中的值覆盖掉,使用store.data来访问
创建store
// 创建单一的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}
}
在页面中使用更新store
import store from "../../store"create(store, {data: {count: null},// 更新 countincrease() {this.store.data.count += 1this.update()}
})
在组件中使用更新store
import create from "../../utils/create"create({data: {count: null},methods: {increase() {this.store.data.count += 1this.update()}}
})
this.update()
this.update()方法返回一个promise对象,当视图层页面渲染完成后调用resolve()
this.update().then((data) => {console.log('视图已完成数据的更新', data)})