There are three types of value transfer communication between components: parent to child, child to parent, and communication between sibling components;
(1)props/$emit
Father to son: props
Pass from child to parent: the parent component passes the event method to the child component. The child component triggers the event through $emit and calls back to the parent component
(2)$eimt $on
This method uses an empty Vue instance as the central event bus (event center) to trigger and listen to events, and cleverly and lightly realizes the communication between any component, including parent-child, brother and cross level.
Specific implementation method:
var Event=new Vue(); Event.$emit(Event name,data); Event.$on(Event name,data => {}); // Suppose there are three sibling components, namely A, B and C. how can C obtain the data of A or B // Components A and B transmit data through event. $emit (event name, data), and component C receives the data transmitted by components A and B through event. $on (event name, data = > {})
(3)Vuex
vuex is a warehouse. There are many objects in the warehouse. The data source is stored in the state. When the component wants to change the data in the state, it must be done through mutation. Mutation stores the operation method of changing the data in the state, and then triggers the method in mutation through the operation stored in actions, which is triggered by $store.dispatch('action name ', data1) in the component. Then commit() triggers the call of mutation to update the state indirectly.
(4)Vuex + localstorage
Vuex is the state manager of vue, and the stored data is responsive. However, it will not be saved. After refreshing, it will return to the initial state. The specific method should copy and save a copy of the data in vuex to localStorage when the data changes. After refreshing, if there is saved data in localStorage, take it out and replace the state in the store.
It should be noted here that in vuex, all the saved states are arrays, while localStorage only supports strings, so JSON conversion is required.
(5)$attrs $listeners
Attribs: contains attribute bindings (except class and style) in the parent scope that are not recognized (and obtained) as props. When a component does not declare any prop, all parent scope bindings (except class and style) will be included here, and internal components can be passed in through v-bind="$attrs" - very useful when creating high-level components.
Listeners: contains v-on event listeners in the parent scope (without. native modifiers). It can pass in internal components through v-on="$listeners" - very useful when creating higher-level components.
(6)provide/inject
provide/inject:vue2.2.0 adds an API to allow an ancestor component to inject a dependency into all its descendants, no matter how deep the component level is, and it will always take effect when the upstream and downstream relationship is established.
To sum up: the ancestor component provides variables through the provider, and then injects variables through the inject in the descendant component.
The provide / inject API mainly solves the communication problem between cross level components. However, its use scenario is that sub components obtain the status of superior components, and a relationship between active provision and dependency injection is established between cross level components.
// A.vue export default { provide: { name: 'nora' } } /**************************************/ // B.vue export default { inject: ['name'], mounted () { console.log(this.name); // nora } }
It should be noted that the provide and inject bindings are not responsive. This is deliberate. However, if you pass in a listener object, its object properties are still responsive - vue official documents
How do provide and inject implement data responsive?
Use the latest API Vue.observable in 2.6 to optimize responsive provide (recommended)
Let's take an example: Sun components D, E and f obtain the color value passed by component A and can realize data responsive change, that is, after the color of component a changes, components D, E and F will change accordingly (the core code is as follows:)
//A component <div> <h1>A assembly</h1> <button @click="() => changeColor()">change color</button> <ChildrenB /> <ChildrenC /> </div> ...... // provide() { // return { // theme: { // color: this.color / / the data bound in this way is not responsive // }/ / that is, after the color of component A changes, components D, E and F will not change // }; // }, // Method 2: use the latest API Vue.observable in 2.6 to optimize the responsive provide provide() { this.theme = Vue.observable({ color: "blue" }); return { theme: this.theme }; }, methods: { changeColor(color) { if (color) { this.theme.color = color; } else { this.theme.color = this.theme.color === "blue" ? "red" : "blue"; } } } /******************************************************************/ // F assembly <template functional> <div class="border2"> <h3 :style="{ color: injections.theme.color }">F assembly</h3> </div> </template> <script> export default { inject: { theme: { //Different values of functional components default: () => ({}) } } }; </script>
(7)$parent / $children and ref
ref: if it is used on an ordinary DOM element, the reference refers to the DOM element; If used on a child component, the reference points to the component instance
$parent / $children: access parent / child instances
It should be noted that these two methods get component instances directly. After use, you can directly call component methods or access data.
$parent: access the parent instance, if the current instance exists.
$children: the direct child component of the current instance. Note that $children does not guarantee order and is not responsive. If you find yourself trying to use $children for data binding, consider using an Array with v-for to generate subcomponents, and using Array as the real source.
The disadvantage of these two methods is that they cannot communicate across levels or brothers.
// component-a subcomponent export default { data () { return { title: 'Vue.js' } }, methods: { sayHello () { window.alert('Hello'); } } } /***********************************/ // Parent component <template> <component-a ref="comA"></component-a> </template> <script> export default { mounted () { const comA = this.$refs.comA; console.log(comA.title); // Vue.js comA.sayHello(); // Popup } } </script>
Original reference: Six communication modes between vue components