• vue、react和小程序的状态管理


    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

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. export default new Vuex.store({
    4. actions: {},
    5. state: {},
    6. mutations: {},
    7. getter: {},
    8. modules: {}
    9. })

    全局配置: main.js

    1. import Vue from 'vue'
    2. import store from './store/index.js'
    3. // 在vue实例上注册使用
    4. new Vue({
    5. el: #app,
    6. render: h => h(APP),
    7. store
    8. })

    vuex中的state配置项

    注册全局状态

    vuex中的actions配置项

    响应组件中的动作

    vuex中的mutations配置项

    修改state中的数据,可以被vuex的开发者工具检测到

    vuex中的getter配置项

    依赖于state去计算出新值

    vuex中的modules配置项,实现模块化

    如果页面中很多不同模块的组件都存储在vuex中,可以分模块

    modules配置项可以实现

    1. import Vue from 'vue'
    2. import Vuex from 'vuex'
    3. // 命名空间nameSpace
    4. // 命名空间的作用是在使用mapState()、mapActions、mapMutations()的时候作为第一个参数,快速获取
    5. // 到各个模块的状态、action、mutations、getter
    6. const demo1 = {
    7. nameSpace: true,
    8. actions: {},
    9. state: {},
    10. mutations: {},
    11. getter: {},
    12. }
    13. const demo2 = {
    14. nameSpace: true,
    15. actions: {},
    16. state: {},
    17. mutations: {},
    18. getter: {},
    19. }
    20. export default new Vuex.store({
    21. modules: {
    22. demo1,
    23. demo2
    24. }
    25. })

    在组件中获取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使用:

    1. // 第一步:pinia引入
    2. import {creatPinia} from 'pinia'
    3. // 第二步:创建pinia
    4. const pinia = creatPinia()
    5. // 第三步:安装pinia
    6. const app = cratApp()
    7. app.use(pinia)

    pinia存储和读取数据

    pinia存储数据

    1. import {defineStore} from 'pinia'
    2. // defineStore接收两个参数,第一个参数是文件名字,第二个参数是store的配置项
    3. // 配置项目可以是选项式也可以是组合式
    4. // 选项式
    5. // 选项式第二个参数是对象
    6. export const useDemoStore = defineStore('demo', {
    7. // 配置状态
    8. // state是一个函数
    9. // 返回一个对象
    10. state() {
    11. return {
    12. demo: 1
    13. }
    14. },
    15. // 在这里可以获取this,this上有状态值
    16. action: {
    17. changeDemo() {
    18. this.demo = 3
    19. }
    20. }
    21. })
    22. // 组合式
    23. // 组合式第二个参数是函数
    24. import {ref} from 'vue'
    25. export const useDemoStore = defineStore('demo', () => {
    26. // 配置状态
    27. // 使用选项式API进行定义
    28. const demo = ref(0)
    29. // action中的函数正常写即可
    30. changeDemo() {
    31. demo = 3
    32. }
    33. // 如果要把这些状态和方法暴漏出去,需要有返回值
    34. return {
    35. demo,
    36. changeDemo
    37. }
    38. })

    pinia读取数据

    1. // 首先把之前定义的demo引入
    2. import {useDemoStore} from './demo'
    3. // 之前定义的store有返回值,返回值中就有我们定义的方法和状态
    4. const demoStore = useDemoStore()
    5. // 获取状态
    6. // 第一种方法
    7. demoStore.demo
    8. // 第二种
    9. demoStore.$state.demo

    pinia修改状态

    1. // 首先把之前定义的demo引入
    2. import {useDemoStore} from './demo'
    3. // 之前定义的store有返回值,返回值中就有我们定义的方法和状态
    4. const demoStore = useDemoStore()
    5. // 第一种:直接修改
    6. demoStore.demo = 2
    7. // 第二种: 可以批量修改
    8. demoStore.$patch({
    9. demo: 1,
    10. demo2: 2
    11. })
    12. // 第三种:使用action进行修改
    13. // 使用action进行修改的目的是如果是复杂的逻辑,可以进行服用
    14. demoStore.changeDemo({
    15. demo: 1,
    16. demo2: 2
    17. })

    storeToRefs

    为什么要有这个API?

    把全局状态引入之后,在使用的时候每次都要多取一层,这个的目的是把状态结构出来,并且是响应式的

    1. import {storeToRefs} from 'pinia'
    2. const demoStore = useDemoStore()
    3. const {demo} = storeToRefs(demoStore)

    getters

    和vuex中的getter一样,都是计算状态值的

    $subscribe

    这个API的作用是来监听某个store中的值是否有变化,若是监听到变化可以做一些逻辑操作,类似于watch监听

    1. const demoStore = useDemoStore()
    2. const {demo} = storeToRefs(demoStore)
    3. // 接收一个函数作为参数
    4. // 函数接收两个参数,参数一是本次修改信息,参数二是state
    5. demoStore.$subscribe((mutate, state) => {})

    react的状态管理

    redux

    redux下载:npm i redux

    redux全局使用步骤:

    1. // store.js
    2. // 引入之前定义好的reduce的文件
    3. import demoReduce from './reduce/demoReduce.js'
    4. // 引入redux
    5. import {creatStore} from 'redux'
    6. // 导出store
    7. export default creatStore(demoReduce)

    redux中的数据在组件中使用

    1. // 引入store
    2. import store from './store'
    3. // 获取state
    4. store.getState().状态名称
    5. // 触发action
    6. store.dispath({type: '触发动作名字', data:‘传递的数据’})

    redux中的action

    是一个对象,接收一个对象

    {

            type: 触发的动作名称,

            data: 触发时传递的数据

    }

    触发方式:dispath

    redux处理异步action

    异步action需要用到redux中applyMiddleware,执行中间件

    处理异步action的中间件:redux-thunk

    需要在creatStore中传入第二个参数注册中间件:creatStore(reduec, applyMiddleware(redux-thunk))

    redux中的reduce

    实质是一个函数,根据action中的type来处理数据

    redux监听数据变化更新页面

    store.subscribe(),参数是一个箭头函数,可以拿到最新的state

    redux在页面中如何使用状态

    store.getState()

    redux中实现模块化

    需要使用redux中的combineReducers

    1. import {combineReducers} from 'redux'
    2. import demo1 from './demo1'
    3. import demo2 from './demo2'
    4. const reduces = combineReducers({
    5. demo1,
    6. demo2
    7. })
    8. export default creatStore(reduces)

    react-redux

    react-redux安装:npm i react-redux

    react-redux使用: 和redux类似

    react-redux监听数据改变更新页面和redux的差异

    在跟组件通过provide组件包裹根组件,并把store传入下层组件

    react-redux解决了redux的什么问题

    1、数据改变试图更新的机制改变

    redux使用store.sunscribe

    react-redux使用provide注入组件之后,react-redux自己做了数据改变页面更新

    2、使用store中的数据和方法改变

    通过connect()()以props的方式注入到组件

    1. import {connect} from 'react-redux'
    2. // 第一种方式
    3. connect(
    4. (state)=>{
    5. return {
    6. demo1: state.demo1
    7. }
    8. },
    9. (dispath)=>{
    10. return {
    11. changeDemo1: dispath({type: 'changeDemo1', data,value})
    12. }
    13. }
    14. )(ui组件)
    15. // 第二种方式
    16. connect(
    17. (state)=>{
    18. return {
    19. demo1: state.demo1
    20. }
    21. },
    22. {
    23. changeDemo1: {type: 'changeDemo1', data,value}
    24. }
    25. )(ui组件)

    mobx

    mobx中文文档:https://cn.mobx.js.org

    mobx安装:npm i mobx mobx-react

    mobx存储和读取数据

    observale/observer: 会使用到这俩装饰器,第一个是把普通状态定义为可以被mobx中的钩子函数监测的状态,第二个是把mobx和react组件进行关联

    mobx存储数据

    1. import {observable, action} from 'mobx'
    2. class user {
    3. // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
    4. @observable demoName = '小刘'
    5. }
    6. // 通过props向下传递store中的数据
    7. ReactDOM.render(<App store={new user()} />, document.getElementById('#root'))

    使用mobx中的数据

    1. import {observable, action} from 'mobx'
    2. import {observer} from 'mobx-react'
    3. // 组件中使用store
    4. // 从props中结构出store
    5. @observer
    6. class com extends React.component {
    7. render() {
    8. {store} = this.props
    9. }
    10. }

    mobx修改状态

    computed

    计算属性,类似于vue中的computed

    1. import {observable, computed} from 'mobx'
    2. class user {
    3. // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
    4. @observable demoName = '小刘'
    5. @computed get changeDemoName() {
    6. return this.demoName += '==='
    7. }
    8. }

    action

    对状态的操作

    1. import {observable, action} from 'mobx'
    2. class user {
    3. // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
    4. @observable demoName = '小刘'
    5. @action changeDemoName() {
    6. this.demoName += '==='
    7. }
    8. // action加一个限定词bound,目的是正确绑定实例this
    9. @acton.bound bchangeName() {
    10. this.demoName += '===bound改变'
    11. }
    12. // 异步action
    13. // action里面有异步操作,可以有以下三种方法
    14. @action syncChangName() {
    15. // 第一种
    16. 再写另外一个action去改变异步里面的值
    17. // 第二种
    18. // 第二个参数函数需要手动立即调用
    19. 使用action(‘方法名称’, 函数)
    20. // 第三种
    21. runInAction(() => {
    22. // 直接在这里改变状态值
    23. })
    24. }
    25. }

    mobx的动态检测

    autorun

    接收一个函数作为参数,默认会执行一次,当内部依赖的被观测值发生改变时会再执行一次

    1. import {observable, computed, autorun} from 'mobx'
    2. class user {
    3. // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
    4. @observable demoName = '小刘'
    5. @computed get changeDemoName() {
    6. return this.demoName += '==='
    7. }
    8. }
    9. autorun(() => {
    10. this.demoName += 'autorun监测改变'
    11. })
    when

    当满足条件时,只执行一次

    接收两个函数作为参数,参数一是判断被监测的值是否满足条件,满足条件执行第二个函数

    1. import {observable, computed, when} from 'mobx'
    2. class user {
    3. // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
    4. @observable demoName = '小刘'
    5. @computed get changeDemoName() {
    6. return this.demoName += '==='
    7. }
    8. }
    9. when(() => {
    10. return a > 10
    11. }, () => {
    12. // 满足条件时执行代码
    13. })
    reaction

    初始化不会执行,也可手动停止监测,只有被监测的数据发生改变才会触发

    接收两个函数作为参数,第一个参数的返回值会作为第二个函数参数的第一个参数,

    第二个参数是一个函数,接收两个参数,第一个参数就是reaction第一个参数的返回值,第二个参数是reaction本身

    1. import {observable, computed, reaction} from 'mobx'
    2. class user {
    3. // 熟悉类的装饰器,会更好理解当前的状态和函数的定义
    4. @observable demoName = '小刘'
    5. @computed get changeDemoName() {
    6. return this.demoName += '==='
    7. }
    8. }
    9. reaction(() => {
    10. return 10
    11. }, (data, reaction) => {
    12. // data是上个参数的返回值10
    13. // 第二个参数是reaction本身
    14. // 可以调用reaction.dispose()来停止继续监测的数据
    15. // 满足条件时执行代码
    16. })

    小程序的状态管理

    mini-program

    微信中的全局状态管理使用的是mobx-miniprogram和westore两种、

    注意:mobx-miniprogram搭配mobx-miniprogram-bindings

    创建store

    1. import {
    2. observable,
    3. action
    4. } from "mobx-miniprogram";
    5. export observable({
    6. // data
    7. demo1: 1,
    8. demo2: 2,
    9. // action来改变数据
    10. updataDemo1: action(function(argument){})
    11. })

    在页面中使用store

    1. import {
    2. createStoreBindings
    3. } from "mobx-miniprogram-bindings"
    4. import store from "../../store/index"
    5. Page({
    6. onLoad() {
    7. // 使用createStoreBindings将数据绑定到页面中
    8. this.storeBindings = createStoreBindings(this, {
    9. store,
    10. fields: ['demo1', 'demo2'],
    11. actions: ['updataDemo2']
    12. })
    13. },
    14. // count 递增
    15. increaseHandle() {
    16. this.updataDemo2(1)
    17. },
    18. // 页面卸载时,销毁当前页面的 store 绑定
    19. onUnload() {
    20. this.storeBindings.destroyStoreBindings();
    21. }
    22. })

    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

    1. import {
    2. storeBindingsBehavior
    3. } from "mobx-miniprogram-bindings"
    4. import store from "../../store/index"
    5. Component({
    6. behaviors: [storeBindingsBehavior],
    7. storeBindings: {
    8. store,
    9. fields: ['demo2'],
    10. actions: ['updataDemo2']
    11. },
    12. methods: {
    13. // demo2 递增
    14. increaseHandle() {
    15. this.updataDemo2(1)
    16. }
    17. }
    18. })

    store划分模块

    直接在store文件夹下新建相应的.js文件就行

    westore

    westore有俩个核心的api

    创建页面

    create(store,option)

    创建组件

    create(option)

    更新页面或组件

    this.update()

    1、为了避免组件和页面中data的值被store中的值覆盖掉,使用store.data来访问

    创建store

    1. // 创建单一的store
    2. export default {
    3. data: {
    4. userInfo: {
    5. name: 'zhangsan',
    6. age: 25,
    7. city: 'QingDao'
    8. },
    9. count: 0
    10. }
    11. }
    12. // 创建模块化store
    13. import user from "./user"
    14. import system from "./system"
    15. export default {
    16. data: {
    17. user,
    18. system
    19. }
    20. }

    在页面中使用更新store

    1. import store from "../../store"
    2. create(store, {
    3. data: {
    4. count: null
    5. },
    6. // 更新 count
    7. increase() {
    8. this.store.data.count += 1
    9. this.update()
    10. }
    11. })

    在组件中使用更新store

    1. import create from "../../utils/create"
    2. create({
    3. data: {
    4. count: null
    5. },
    6. methods: {
    7. increase() {
    8. this.store.data.count += 1
    9. this.update()
    10. }
    11. }
    12. })

    this.update()

    this.update()方法返回一个promise对象,当视图层页面渲染完成后调用resolve()

    1. this.update()
    2. .then((data) => {
    3. console.log('视图已完成数据的更新', data)
    4. })
  • 相关阅读:
    SpringCloud使用注解+AOP+MQ来实现日志管理模块
    el-tabs(标签栏)的入门学习
    springboot + nacos + aws secretmanager 做账号密码隐私处理
    vue-cli的安装
    如何免费获取基于公网 IP 的 SSL 证书 (无需域名)
    ECMAScript 6 Reflect / Proxy
    JZ2440笔记:热插拔驱动
    Linux基本操作指令(3)
    WM CJC8988多功能Codec芯片性能及应用介绍
    我只认两种产业互联网形态
  • 原文地址:https://blog.csdn.net/weixin_47808575/article/details/136336813