Vuex stores arrays (new, added, deleted, updated) and saves them in localstorage for regular deletion

Vuex stores arrays (new, added, deleted, updated) and saves them in localstorage for regular deletion

use background

A complete array is initialized, but part or all of it will be updated or added or deleted separately in the business logic.

If all are updated every time, you can directly use set to replace. However, most of the arrays remain unchanged and only individual data is modified. The cost of direct replacement is high, so a business of adding, deleting and modifying is maintained.

The original data is meaningful. The new data may be initialized and cannot be directly replaced with new data. The new data may only add or delete ids, but other data content will continue to use the old data, so it can only be maintained on the basis of the old data.

Add, delete, and modify in the store

import Vue from "vue"
import Vuex from "vuex"

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    list: [],
  },
  getters: {},
  mutations: {
    setList(state, list) {
      state.list = list;
    },
    addItem(state, item) {
      state.list.push(item);
    },
    updateItem(state, payload) {
      Vue.set(state.list, payload.index, payload.data);
    },
    deleteItem(state, lt) {
      let newIds = lt.map((item) => item.aid);
      state.list = state.list.filter((item) => newIds.includes(item.aid));
    },
  },
  actions: {}
})

export default store;

Maintain an array in the component and make a judgment

Object array data format

[
  { "aid": "1", "aname": "111", "tobid": "1" }
  { "aid": "2", "aname": "ddd", "tobid": "2" }
]

Judgment in the component

  1. Judgment when creating a new one , just assign the value that.list.length == 0 || that.list == nulldirectlyset
  2. If it is not 0, it means that it has been initialized and assigned, and traverse the current array (the data in this article comes from the backend)
    • id does not exist (the old array does not have it and the new array does), then call addadd
    • If the id exists, it is necessary to judge whether the object is exactly the same, if not, callupdate
  3. Finally delete, the store is directly used to filterfilter out objects that exist in the new array but not in the old array (the logic of delete can exist independently, not together with the update)

Modify and use by yourself: add and delete are required for large updates, and only update is required for partial updates

For example, the old array is [1, 2] and the new array is [2, 3]. After the second step, the old data becomes [1, 2, 3], but [1] needs to be deleted

<template>
  <div class="form-all">
    <el-button @click="getList()">getList</el-button>
    <el-button @click="clearStorage()">clear Local Storage</el-button>
    <div v-for="(item) in list" :key="item.aid">{
   
   { item }}</div>
  </div>
</template>

<script>
import { mapState, mapMutations } from "vuex";

export default {
  name: "demo",
  data() {
    return {
      lit: [],
    };
  },
  components: {},
  computed: {
    ...mapState(["list"]),
  },
  methods: {
    ...mapMutations(["setList", "addItem", "updateItem", "deleteItem"]),
    clearStorage() {
      // localStorage.setItem("list", []);
      localStorage.removeItem('list');  
    },
    getList() {
      console.log(this.list.length);
      let that = this;
      this.axios
        .get('/abc/onetooneAnnote')
        .then((response) => {
          //返回结果
          let lt = response.data;
          this.setStore(lt);
        })
        .catch((error) => {
          console.log(error)
        })
    },
    setStore(lt) {
      let that = this;
      if (that.list.length == 0) {
        //初始化
        this.setList(lt);
      } else {
        let lit = that.list;
        lt.forEach((newItem, i) => {
          const index = lit.findIndex((litem) => litem.aid === newItem.aid);
          if (index == -1) {
            // 添加
            this.addItem(newItem);
          } else {
            const oldItem = lit[index];
            if (JSON.stringify(oldItem) != JSON.stringify(newItem)) {
              // 更新
              let payload = {
                data: newItem,
                index: index,
              }
              this.updateItem(payload);
            }
          }
        })
        //删除
        this.deleteItem(lt);
      }
    },
  },
  mounted() {
  },
  created() {},
  destroyed() {},
  watch: {},
}
</script>

<style scoped>
</style>

<style></style>

Save it to localstorage and set timed deletion

Do not refresh the page, use the value in vuex, refresh the page to get it from localstorage again

custom implementation

  1. Use the method subscribespecified by the listener mutation, and the corresponding method call will be updatedlocalstorage
  2. Implement the function setItemWithExpiry, organize the time as a variable and data into an object, save it , and call this function localStorageat timesubscribe
import Vue from "vue"
import Vuex from "vuex"

Vue.use(Vuex)

// 将数据存储到LocalStorage并设置过期时间(毫秒)
function setItemWithExpiry(key, value, ttl) {
  const item = {
    value: value,
    expiry: new Date().getTime() + ttl,
  };
  localStorage.setItem(key, JSON.stringify(item));
}

const store = new Vuex.Store({
  state: {
    list: JSON.parse(localStorage.getItem("list")).value || [],
  },
  getters: {},
  mutations: {
    setList(state, list) {
      state.list = list;
    },
    addItem(state, item) {
      state.list.push(item);
    },
    updateItem(state, payload) {
      Vue.set(state.list, payload.index, payload.data);
    },
    deleteItem(state, lt) {
      let newIds = lt.map((item) => item.aid);
      state.list = state.list.filter((item) => newIds.includes(item.aid));
    },
  },
  actions: {}
})

// 监听订阅
store.subscribe((mutation, state) => {
  if (['setList', 'addItem', 'updateItem', 'deleteItem'].includes(mutation.type)) {
    // 不设置定时删除
    // localStorage.setItem('list', JSON.stringify(state.list));
    // 使用定时删除
    setItemWithExpiry("list", state.list, 10 * 1000);
  }
});

export default store;

Among them, the value of vuex is obtained. If you want to read directly from localstorage every time, you can use the getters attribute of store

  getters: {
    getList: (state) => {
      return state.list;
    },
  },

used in the component

<div v-for="(item) in getList" :key="item.aid">{
   
   { item }}</div>

import { mapGetters } from "vuex";

  computed: {
    ...mapGetters(['getList']),
  },

Use the storage-timing plugin

Official github address: https://github.com/xxwwp/StorageTiming/blob/main/docs/zh.md

call timing delete

  1. Set the timer, which can App.vuebe set globally in
  2. checkExpiryYou can traverse all of them localstorage, or just focus on a few variables
<template>
  ...
</template>

<script>
export default {
  data() {
    return {
      timer: "",
    }
  },
  components: {},
  methods: {
    getItemWithExpiry(key) {
      const itemStr = localStorage.getItem(key);
      if (!itemStr) {
        return null;
      }
      const item = JSON.parse(itemStr);
      const currentTime = new Date().getTime();
      if (currentTime > item.expiry) {
        // 如果数据已经过期,删除它
        localStorage.removeItem(key);
        return null;
      }
      return item.value;
    },
    // 检查LocalStorage中的数据是否过期
    checkExpiry() {
      this.getItemWithExpiry("list");
      // for (let i = 0; i < localStorage.length; i++) {
      //   const key = localStorage.key(i);
      //   getItemWithExpiry(key);
      // }
    },
    startCheck(){
      let that = this;
      this.timer = setInterval(() => { //开启定时器
        console.log("check localstorage");
        that.checkExpiry()
      }, 1000)
    }
  },
  mounted() {
    this.startCheck();
  },
  beforeDestroy(){
    clearInterval(this.timer)//组件销毁之前清掉timer
  },
  computed: {},
  created() {

  },

}
</script>

<style scoped></style>
<style></style>

final effect

  • initialization
  • Add
  • update and delete
  • View localstorage in Google Chrome (F12 --> Application -->Storage)
  • localstorage timed deletion

Guess you like

Origin blog.csdn.net/qq_23858785/article/details/130375454