Daily brick moving, project value transfer is very common behavior, I listed the vUE involved in the use of value transfer scenarios, summarized in VUE must use the form of value transfer.

Components by value

Parent and child components pass values

  • props
/ / parent component < I - a MSG = "angel yan jing ke qin offered figure" > < / I > a / / subcomponents props: [' MSG ']Copy the code
  • on/emit
// Parent <! - custom components used on listening to send the event -- -- > < I - a @ on = "gx" > < / I > a / / subcomponents enclosing $emit (' gx) / / use emit sent from custom event: gxCopy the code
  • $parent/$children
This.$parent gets the parent instance. This.$children gets the child instanceCopy the code
  • ref
<template> <div id="app"> <! < I -a ref="ia" /> <! <p > </p> </div> </template> <script> export default {methods: {rename() {this.$refs.ia // Retrieves custom component instances that can be used to call methods or data on child components. This.$refs.p1 // get the p tag, the normal dom node},},}; </script>Copy the code

Descendant components pass values

  • Provoid/Inject Brother The provoid/ Inject brother must be used together.
  • | provoid object returns an object function.
  • Inject | string array object.
Case 1

Prerequisites: There are four components: A, B, C, and D. A nested B, B nested C, and C nested D. Introduce the A component in app.vue.

// App.vue <template> <div id="app"> <i-a></i-a> </div> </template> <script> import A from "./components/A"; Export default {name: "App", components: {"i-a": a,}, provide: {name: "daqin ",}}; <template> <div class="hello"> A: {{ name }} <div> <i-b></i-b> </div> </div> </template> <script> import B from "./B"; export default { name: "A", inject: ["name"], components: { "i-b": B, }, }; </script>Copy the code

The result of name is then inherited by all descendants.

Case 2

You should note that the name in provide is a dead character. Normally, this value is mostly retrieved from data. To access this, provide must be a function that returns an object.

// app.vue provide() {return {name: this.name}}, data: function () {return {name: "daqin empire ",}; },Copy the code

Case 3

Since they are descendants, for app, A, B, C and D are all descendants, and for A, B, C and D are all descendants… , if provide is used in component A, can its background also get data? The answer: crotch on fire. – Crotch on fire (of course).

}, // b.vue \ c.vue \ d.vue inject: ["name", "wuchenghou"],Copy the code

Case 4

If both parents have the same value, who should I listen to? The answer is: listen to whoever is near you!

// app.vue provide: {shoudu: "Xiyang ",} // a.vue provide: {Wuchenghou:" Shoudu: "Wang Jian ",}, // ABCD component inject: ["name", "wuchenghou", "shoudu"] <! {{shoudu}}</p>Copy the code

Case 5

Inject supports objects in addition to string arrays. As an object, key is the local binding name and value is.

  • Search for the key(string or Symbol) used in the available injection content, or
  • An object of which:
    • fromProperty is the key (string or Symbol) to search for in the available injection content
    • defaultProperty is the value used in the degraded case

Rewrite the inject of component B:

inject: {
    name: "name",
    wuchenghou: {
        from: "wuchenghou",
        default: "--",
    },
    shoudu: "shoudu",
},
Copy the code
Case 6

Have you ever wondered how well provide works when using asynchronous data? Suppose we need to change the value in provide under certain circumstances, is that as expected?

// app.vue <template> < button@click ="rename"> </button> {{this.name}} <hr /> </template> Return {name: shoudu: "shoudu ",}; }, methods: {rename() {this.name = "ying Zong "; }},Copy the code

Then click the “Qin Wang Zheng” button

The name in app.vue has changed, but its descendant gate has not. Provide and Inject binding are not responsive. If a listening object is passed in, the object’s property is still responsive. That is, if you want descendant to respond to asynchronously received values, the value corresponding to key in provide must be a reference type.

// app.vue provide() {return {name: this.name, shoudu: "xianyang ", qin: this.qin,}; }, data: the function () {return {name: "daqin empire," qin: {ge: "qin wang,"},}; }, methods: {rename() {this.name = "ying Zong "; This.qin. Ge = "first emperor ying Zheng "; }, }, // A.vue inject: ["name", "shoudu", "qin"] <! -- Use --> <p> asynchronous data: {{qin.ge}}</p>Copy the code

At this time to pass down the asynchronous data is: Qin Wang Zheng. Click qin Wang Zheng button, dynamic change to: first emperor Ying Zheng.

View the demo

Sibling/sibling components pass values

  • vuex
  • observable
  • EventBus

Sibling/sibling components, which have no direct affiliation, usually use Vuex, EventBus, and Observable to transfer values to such components.

The main focus here is EventBus, also known as EventBus or central EventBus. At the end of the day, Vue uses its own $ON and $emit.

Prerequisites: There are two sibling components A and B, with A common parent component (usually $root or A common parent component).

// App.vue
<template>
    <div id="app">
        <i-a />
        <i-b />
    </div>
</template>
<script>
import A from "./components/A";
import B from "./components/B";
export default {
    name: "App",
    components: {
        "i-a": A,
        "i-b": B,
    },
};
</script>
Copy the code

Create a new Vue instance in main.js to ensure that all components can access it.

// The new instance is mounted on the Vue prototype, Prototype.$bus = new Vue() // a.vue created() {this.$bus.$on("amsg", (msg) => { this.msg = msg; }); }, methods: {setMsg() {// You can also submit A custom event this.$bus.$emit(" BMSG ", "A-> hW: hW "); }}, / / B.v ue created () {/ / custom events to monitor this. $bus. $on (" BMSG ", (MSG) = > {this. MSG = MSG; }); }, methods: {setMsg() {// You can also submit a custom event this.$bus.$emit("amsg", "B-> amSG "); }},Copy the code

Click the corresponding button to pass your information to other components.In fact, this method is not limited to sibling components, as long as any two components have a common parent or sibling component.

Note that when destroying the component, remember to remove the $ON bound event to avoid repeated listening.

BeforeDestroy () {this.$bus.$off(" BMSG ") // this.$bus.$off() Removes all bound events if no event name is specified. }Copy the code

View the demo

Routing by value

Operation URL implementation

  • location
  • ue-route: query
  • vue-route: params
  • After routing
// location location.href = 'https:// $routes. Push ({name: 'xx', query: {MSG: 'xx'}}) // vue-route: {routes: {routes: 'xx'}}) Params this.$routes. Push ({name: 'xx', params: {MSG: 'xx'}}) {path: '/ bw / : name, name:' bw} this. $routes. Push ({name: 'bw, params: {name: "chu overlord"}}) enclosing $routes. Push ({name: 'Bw', params: {name: 'xiang yu '}})Copy the code

Front-end storage implementation

  • localStorage
  • sessionStorage
  • cookie
  • indexedDB

Window by value

This is special, vUE is basically a single page application, rarely open two Windows at the same time, but also need to pass value processing. However, if this thing is embedded in the app, it is another story.

For some special use scenarios, the route jump embedded in app will be intercepted and the location jump will be used uniformly. Without opening a page, a new instance is created, and vuex and other internal things are invalid.

  • LocalStorage updates the value by listening to the storage (ios webView is not aborting the event)
// Mounted () {window.addeventListener ('storage', this.setValfun, false)} methods: { setValFun(e) { if (e.storageArea? .val === '1') { //... Localstorage.removeitem ('val')}}} // B localStorage.setietm ('val', '1')Copy the code
  • The polling function queries the stored value
/ / A component mounted () {enclosing setValFun ()} the methods: {setValFun () {if (getCookie (' val) = = = '1') {/ /... DelCookie (' val)} setTimeout () = > {enclosing setValFun ()}, 1000)}} / / B component setCookie (' val ', '1', '1 d)Copy the code

One day

Minimalist encapsulates Observable

// store/index.js
const store = {
  state: Vue.observable({
    name: ''
  }),
  commit: {
    setName(n) {
        store.state.name = n
    },
  }
}
export default {
  install: function() {
    Vue.prototype.$store = store
  }
}

// main.js
import store from './store'
Vue.use(store)
Copy the code