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