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

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、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
    }
})

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

redux下载:npm i redux

redux全局使用步骤:

// store.js

// 引入之前定义好的reduce的文件
import demoReduce from './reduce/demoReduce.js'

// 引入redux
import {creatStore} from 'redux'

// 导出store
export default creatStore(demoReduce)

redux中的数据在组件中使用

// 引入store
import store from './store'

// 获取state
store.getState().状态名称

// 触发action
store.dispath({type: '触发动作名字', data:‘传递的数据’})

redux中的action

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

{

        type: 触发的动作名称,

        data: 触发时传递的数据

}

触发方式:dispath

redux处理异步action

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

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

redux中的reduce

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

redux监听数据变化更新页面

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

redux在页面中如何使用状态

store.getState()

redux中实现模块化

react-redux

react-redux安装:

react-redux使用

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

react-redux解决了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(, 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({

    // data
    demo1: 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
  },

  // 更新 count
  increase() {
    this.store.data.count += 1
    this.update()
  }
})

在组件中使用更新store

import create from "../../utils/create"

create({
  data: {
    count: null
  },

  methods: {
    increase() {
      this.store.data.count += 1
      this.update()
    }
  }
})

this.update()

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

this.update()
 .then((data) => {
   console.log('视图已完成数据的更新', data)
 })

你可能感兴趣的:(vue.js,react.js,前端)