小项目还用Vuex?vue2使用Vue.observable手写一个状态管理吧,vue3直接使用reactive手写store
为什么用这个,首先想要手写仓库,那么你使用的数据就必须是响应式数据,不然你改变了,页面却没有改。
而Vue.observable和reactive都是把数据变成响应式的方法
故vue2的做法是
import Vue from 'vue'
export const store=Vue.observable({
userInfo:null,
})
// 定义 mutations, 修改属性
export const mutation={
setUserInfo(user){
store.userInfo=user
}
}
//actions处理异步
export const actions={
async login(loginInfo){
//登录处理...
}
}
但是这样做有缺陷,如果外部直接改变store对象里面的数据而不通过mutations的方法改变,那写这个mutations又有什么意义呢
所以我们得思考怎么把返回的store对象是个只读属性不让外部进行修改,要修改值只能通过mutations里面的方法进行修改;
于是想到了es6的proxy代理对象来进行操作,返回的是一个代理对象,mutations修改的是这个js内部的对象,而不是直接修改store对象
修改后代码如下
import Vue from 'vue'
//初始化数据只能内部修改,外部只能通过mutations中的方法才能访问
let _state = Vue.observable({
userInfo: {
name:{
name1: '12323'
},
},
testVal: {a: 1, b: 2}
});
/**
* 使用proxy代理对象更好的监听数据变化
* 设置只读对象
* @type {{name: string}}
*/
export const state = readonlyPoxy(_state);
/**
* 在mutations设置值的时候设置的是
* @type {{setUserInfo(*): void}}
*/
export const mutations = {
setUserInfo(user) {
_state.userInfo = user;
},
setTest(val){
_state.testVal= val;
}
}
/**
* 创建只读的代理对象
* @param needProxyObj 需要代理的对象
* @param needProxyObj
* @returns {boolean|any}
*/
function readonlyPoxy(needProxyObj) {
return new Proxy(needProxyObj, {
set(target, propertyKey, value) {
console.error(`${propertyKey} is readonly `)
return true
},
get(target, propertyKey) {
if(target[propertyKey] instanceof Object){
return readonlyPoxy(target[propertyKey])
}
return Reflect.get(target, propertyKey);
}
})
}
以上做法就相当于vue3中的readonly方法一样外部无法更改该值
vue3中的做法
import {reactive, readonly} from "vue";
import {getAbout} from "../api/about/index";
//数据初始化
const state = reactive({
isLoading: false,
userInfo: ""
})
//readonly保证该数据导出是只读数据
export const aboutInfo = readonly(state);
//做一些异步处理
export async function getAboutInfo() {
//...
}
在组件中直接导出使用就行
<template>
<div>
{{ userInfo.name }}
</div>
</template>
<script>
import { state, mutations } from '../store'
export default {
computed: {
userInfo() {
return state.userInfo
}
},
created() {
mutations.setUserInfo({
name: '子君'
})
}
}
</script>