为了更好的缓存,想出一个小小的设计思路,用来处理 Vuex 和 localStorage 数据的绑定,并且能够根据页面的操作来进行自动更新,并反馈到页面上。
必备知识
- Vuex State、Mutations、Action、getter,使用和原理
- Vue 计算属性、生命周期、响应原理和局限等等。
- localStorage。
准备工作
- 对 localStorage 封装。
export default {
get(key) {
let val = localStorage.getItem(key);
if (!val) {
return null;
}
//考虑只存数组情况
if (val.substr(0, 1) === "{" || val.substr(0, 1) === "[") {
return JSON.parse(val);
} else {
return val.split(",");
}
},
set(key, data) {
data instanceof Set && (data = [...data]);
localStorage.setItem(key, JSON.stringify(data));
},
remove(key) {
//删除逻辑要进行获取判断验证
localStorage.removeItem(key);
return this.get(key) === null ? true : false;
},
clear() {
localStorage.clear();
}
};
- 助手函数
//根据id 在数组中查找数据 返回 是否存在,所在位置,详细信息
hasIdByArr(arr = [], id) {
let a = { has: false, index: undefined, data: [] };
for (let i = 0; i < arr.length; i++) {
if (arr[i].id == id) {
a.has = true;
a.index = i;
a.data = arr[i];
break;
}
}
return a;
},
主要思想
获取的阶段
在一个需要用到缓存的组件的时候,我在生命周期的beforeCreate
阶段去获取一下 Vuex 中Mutations
的一个方法,这个方法就是去获取localStorage
的需要的属性值,把它赋值为State
。
这样设计,不会在初次加载的时候就获取所有的缓存数据,只有在使用的时候才会去获取。去提取
localStorage
在Create
阶段获取也一样,但是我感觉应该和页面的数据获取分开,因为操作的是 Vuex 所以在beforeCreate
阶段也是可以的。
这样 Vuex 中就有了需要的缓存值。页面展示的时候,直接使用 Vue 的计算属性获取就可以了,如果你想要筛选数据就可以使用 Vuex 的getter
。
例如:
//在 created 阶段获取一个传值的 getter
const { onceCount, onceStar } = this.$store.getters.getOnceCart(this.id);
this.count = onceCount;
this.favorite = onceStar;
// 在 getter 中的定义
getOnceCart: ({ cart, star }) => id => {
return {
onceCount:
cart.filter(val => val.id == id).length > 0
? cart.filter(val => val.id == id)[0].count
: 0,
onceStar: star.filter(val => val.id == id).length > 0 ? true : false
};
};
因为当前的页面缓存属性,需要你先去让获取后才会有,所以需要等数据获取后才能去 getter 筛选,所以在创建阶段赋值。
设置阶段
在页面渲染后,我们可能会对页面进行操作,从未触发页面的缓存修改。
- 在 Vuex 方面
使用 mutations 去提交修改 State 和 localStorage。
changeStar({ star }, news) {
star = news;
storage.set("star", star);
},
- 使用 Action 对组件提交过来的数据进行处理和拦截,然后抛给 mutations 保存
pushStarData({ commit }, news) {
const { starData, status } = news;
const { id } = starData;
let old = this.state.star || [];
const { index, has } = help.hasIdByArr(old, id);
if (status) {
old.push(starData);
} else {
old.splice(index, 1);
}
commit("changeStar", old);
},
- 在组件中的使用
changeFa() {
let { count, checkBox, ...starData } = this.getCartData()
starData.time = this.$help.getUTCTime();
starData.specifications = this.specifications;
this.$store.dispatch('pushStarData', { starData, status: this.favorite });
}
总结
总的来说就是在一个组件使用的时候去请求 Vuex 把 localStorage 的数据保存到 State 中,组建可以使用计算属性或 vuex 的 getter 去筛选或直接获取数据。
在页面操作的时候,使用 dispatch 提交需要缓存的数据,在 Vuex 中的 action 中去修改,处理,拦截等操作,完成后去提交 mutations,mutations 同步修改 vuex 和 localStorage。这个设计完全符合 Vue 的响应模式,修改的只是 Vuex 的 State 而已,页面的属性是计算属性或 getter 动态获取的,页面能够直接响应修改。
注意
- 在涉及到 form 的时候,比如 checkBox ,使用 change 事件较好,如果使用监听器,会在首次就去触发一次修改,因为你这个组件的默认值和你的缓存值不一样,这时也会触发修改的。