The actual scene

Components A, B, and C all rely on the data of the same interface, and the interface needs to be adjusted every time A, B, and C are loaded. Obviously, that would satisfy the need, but! There are the following problems:

  • Repeated requests
  • Code redundancy, with each component/page having to write a process for getting, assigning, and binding data
  • Not a lazy person

The solution

Option 1 local cache + fetch judgment

Recommended Index: ⭐⭐

Check whether there is a local cache array inside the component. Yes, take it and use it; No, make a request and cache it.

Cons: Redundancy! Redundant!

/ / component A
created() {
    // Check whether there is a local cache
    if (window.localStorage.getItem('key') {
        this.data = JSON.parse(window.localStorage.getItem('key'))}else {
        // No cache, request initiated
        fetch()
            .then(res= > {
                this.data = res.data
                // Set the cache
                window.localStorage.setItem('key'.JSON.stringify(res.data))
            })
    }
}

/ / component B
created() {
    // Copy and paste the same as component A
}
Copy the code

Get the state of + vuex (vue.Observable)

Recommended index: ⭐

(Vue2.6 Observable maintains a JS data source if vuex is too heavy.) (Vue2.6 Observable maintains a JS data source if Vuex is too heavy)

Disadvantages: Poor performance, too many requests may affect page loading; You can’t load data when you need it; The timeliness of data is poor

Introduce state directly into the component

/ / component A
computed: {
    listA: () = > this.$store.state.listA,
    listB: () = > this.$store.state.listB,
}
Copy the code

Related store preparation work

// main.js entry file
this.$store.dispatch('fetchA')
this.$store.dispatch('fetchB')
this.$store.dispatch('fetchC')

// state.js
const store = new Vuex.Store({
  state: {
    listA: [].listB: [].listC: []},... })// mutation.js
updateA(state, payload) {
    state.listA = payload
},
updateB(state, payload) {
    state.listB = payload
}

// action.js
fetchA({ commit }) {
    setTimeout(() = > {
        commit('updateA'[1.2.3])},1000)}fetchB({ commit }) {
    setTimeout(() = > {
        commit('updateB'[4.5.6])},1000)}Copy the code

Scheme 3 VuEX + getter and setter

The first two solutions both meet the requirements, but are not elegant in some scenarios, such as code redundancy, poor performance, etc. What if we could get a variable asynchronously if it is null, or return it directly and update it automatically if it depends on it?

There it is, it is Object.defineProperty

Recommended Index: ⭐⭐

If there is no data in the first get, the data will be returned asynchronously. If there is no data in the first get, the data will be returned asynchronously.

Example: Here is the complete code. You can see that when the display component is clicked, the console sends a log of Request B for 1s, and it switches the display multiple times and does not send any more requests

Note: only describe the general idea, some places are not precise and please forgive me

The key code

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const state = {
  listA: [].listB: []}const requestMap = {
  listA: (state) = > {
    setTimeout(() = > {
      state.listA = [1.2.3.4.5.6.7.8.9]},3000)},listB: (state) = > {
    setTimeout(() = > {
      console.log('request B')
      state.listB = [1.2.3.4.5.6.7.8.9]},1000)}}Object.keys(state).forEach(key= > {
  // Handling vUE initialization get results in premature execution of the function
  let vueInitCount = 0
  const defaultValue = state[key]
  // Avoid circular calls, when the listA is actually returned __listA
  // set listA to __listA
  const privateKey = ` __${key}`
  Object.defineProperty(state, key, {
    get () {
      if (vueInitCount < 2) {
        vueInitCount++
        return defaultValue
      }
      if (!this[privateKey] || (Array.isArray(this[privateKey]) && this[privateKey].length === 0)) {
        const fun = requestMap[key]
        if (fun) {
          fun(state)
        }
      }
      return this[privateKey] || defaultValue
    },
    set (val) {
      this[privateKey] = val
    }
  })
})

export default new Vuex.Store({
  state,
})
Copy the code

Template code

// app.vue
<template>
  <div id="app">
    <HelloWorld v-if="show" msg="Welcome to Your Vue.js App"/>
    <div @click="showCom">According to</div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      show: false}},methods: {
    showCom () {
        this.show = !this.show
    }
  },
}
</script>
Copy the code

Component code

// helloworld.vue
<template>
  <div class="hello">
    <h1>I'm the other component</h1>
    <div>{{listA}}</div>
    <div>{{listB}}</div>
  </div>
</template>
<script>
export default {
  computed: {
    listA () {
      return this.$store.state.listA
    },
    listB () {
      return this.$store.state.listB
    }
  }
}
</script>
Copy the code

Attached with reference to vUE part of the code

Above, is the entire content of this article, wrong/not rigorous place also please forgive