Component development as the core idea of Vue framework, in the actual project development, developers are mainly through the form of component development. Each component instance of Vue has an independent function scope to realize data communication and shared state between components, and to master the communication mode of various components can help us to be more efficient in the process of development. The following shows how all Vue components communicate with each other.
Component communication mode
Props and $emit
The props property is the most commonly used property that a parent component transmits to a child component. The value transmitted through the props property is the spatial address of the transmitted property. When the parent component changes this property, the child component automatically changes too. Props can be arrays or objects, and objects allow you to configure advanced options.
// Props: ['size'.'myMessage'] // Object syntax props: {property: {typeDefault: any, // Specify the default value required: Boolean, // Define whether micro mandatory validator: Function, // Customize the validation Function}}Copy the code
The $emit attribute is the most common attribute that a child component passes to a parent component to fire an event on the current instance, with additional arguments passed to the listener callback.
// Vue.component('magic-eight-ball', {
data: function () {
return {
possibleAdvice: ['Yes'.'No'.'Maybe']
}
},
methods: {
giveAdvice: function () {
var randomAdviceIndex = Math.floor(Math.random() * this.possibleAdvice.length)
this.$emit('give-advice', this.possibleAdvice[randomAdviceIndex])
}
},
template: `
<button v-on:click="giveAdvice">
Click me forAdvice </button> '}) // Parent <template> <div id="emit-example-argument">
<magic-eight-ball v-on:give-advice="showAdvice"><magic-eight-ball>
</div>
</template>
<script>
new Vue({
el: '#emit-example-argument',
methods: {
showAdvice: function (advice) {
alert(advice)
}
}
})
</script>
Copy the code
v-model
It is well known that v-model is used for bidirectional data binding of input field value values in templates, but in components v-model is equivalent to
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
Copy the code
In order for it to work, the <input> inside this component must:
Bind its value feature to a prop named Value that throws a new value through a custom input event when its input event is raised
// Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"> '}) parent <custom-input V-model ="searchText"></custom-input>
Copy the code
refs
By adding a REF attribute to the child component, and then accessing the child component instance through that attribute.
// Parent component <home ref="home"/>
mounted(){
console.log(this.$refs.home) // To get the child component instance, you can directly manipulate data and methods}Copy the code
.sync
Used to exist at [email protected] as a two-way binding, meaning that a child component could modify the value in its parent; The one at [email protected] was killed for violating the design of a single data stream; The.sync modifier was reintroduced in [email protected]+ and above.
// Parent component <home :title.sync="title"/> // will be expanded to <home :title= when compiled"title" @update:title="val => title = val"/> // subcomponents // so subcomponents can pass$emitTrigger the update method changemounted(){
this.$emit("update:title".'This is the new title')}Copy the code
$attrs and $listeners
$attrs contains feature bindings (except class and style) that are not recognized (and retrieved) as prop in the parent scope. When a component does not declare any prop, all parent-scoped bindings (except class and style) are included, and internal components can be passed in via V-bind =”$attrs” — useful when creating higher-level components.
The $Listeners contain V-ON event listeners in the parent scope (without the.native modifier). Internal components can be passed in via V-on =”$Listeners “– useful for creating higher-level components.
// component A Vue.component('A', { template: ` <div> <p>this is parent component! </p> <B :messagec="messagec" :message="message" v-on:getCData="getCData" v-on:getChildData="getChildData(message)"></B>
</div>
`,
data() {
return {
message: 'hello',
messagec: 'hello c'}}, methods: {// Execute the event getChildData(val) {console.log(' This is data from B:${val}`); }, // Execute the event getCData(val) {console.log(' This is data from the C component:${val}`); }}}); // component B Vue.component('B', {
template: `
<div>
<input type="text" v-model="mymessage" @input="passData(mymessage)"> <! C component can directly trigger getCData because B component calls C component with V-on binding$listenersProperties - > <! -- Bind via v-bind$attrs<C v-bind= <C v-bind= <C v-bind= <C v-bind= <C v-bind="$attrs" v-on="$listeners"></C> </div> ', /** * get props: {* message: {**type: String,
* default: ' '
* }
* }
*
*/
props: ['message'].data() {return{mymessage: this.message}}, methods: {passData(val){// Trigger the event this in the parent component.$emit('getChildData', val) } } }); // component C Vue.component('C', {
template: `
<div>
<input type="text" v-model="$attrs.messagec" @input="passCData($attrs.messagec)"> </div> ', methods: {passCData(val) {// Trigger the event this in parent component A.$emit('getCData',val)
}
}
});
var app=new Vue({
el:'#app',
template: `
<div>
<A />
</div>
`
});
Copy the code
$the parent and children
$parent: indicates the parent instance to which the $parent attribute refers. This.$parent.
The $children attribute points to an array of immediate children of the current instance. Note that $children does not guarantee order and is not reactive.
Tip: These two properties are not recommended for component reuse.
// Define the parent component Vue.component('parent', { template: ` <div> <p>this is parent component! </p> <button @click="changeChildValue">test</button>
<child />
</div>
`,
data() {
return {
message: 'hello'
}
},
methods: {
changeChildValue(){
this.$children[0].mymessage = 'hello'; }}}); // Define the child component Vue.component('child', {
template:`
<div>
<input type="text" v-model="mymessage" @change="changeValue" />
</div>
`,
data() {
return {
mymessage: this.$parent.message
}
},
methods: {
changeValue(){
this.$parent.message = this.mymessage; // Change the value of the parent component}},}); const app = new Vue({ el:'#app',
template: `
<div>
<parent />
</div>
`
});
Copy the code
Central EventBus EventBus
When communication between sibling components is needed and the project scale is not large, we can use the central EventBus EventBus to achieve this.
EventBus creates a Vue EventBus object and emits events via bus.$on.
// component A Vue.component('A', { template: ` <div> <p>this is A component! </p> <inputtype="text" v-model="mymessage" @input="passData(mymessage)">
</div>
`,
data() {
return {
mymessage: 'hello brother1'
}
},
methods: {
passData(val) {
//触发全局事件globalEvent
this.$EventBus.$emit('globalEvent', val) } } }); // component B Vue.component('B', { template:` <div> <p>this is B component! < / p > < p > component A passed data: {{brothermessage}} < / p > < / div > `,data() {
return {
mymessage: 'hello brother2',
brothermessage: ' '}},mounted() {// bind the globalEvent globalEvent this.$EventBus.$on('globalEvent', (val) => { this.brothermessage = val; }); }}); Const EventBus = new Vue(); // Assign the central event bus to vue. prototype so that all components can access vue. prototype.$EventBus = EventBus;
const app = new Vue({
el: '#app',
template: `
<div>
<A />
<B />
</div>
`
});
Copy the code
Dojo.provide and inject
This pair of options needs to be used together to allow an ancestor component to inject a dependency into all of its descendants, regardless of how deep the component hierarchy is, and remain in effect as long as the upstream and downstream relationship is established.
The provide option should be an object or a function that returns an object. This object contains properties that can be injected into its descendants.
The Inject option should be an array or an object
Tip: Provide and Inject binding are not responsive. This is intentional. However, if you pass in a listening object, the object’s properties are still responsive.
// The parent component is provided'foo'
var Provider = {
provide: {
foo: 'bar'} / /... } // Child component injection'foo'
var Child = {
inject: ['foo'].created () {
console.log(this.foo) // => "bar"
}
// ...
}
Copy the code
$boradcast and $dispatch
This, too, came in pairs, but it was only provided in Vue1.0, and Vue2.0 was scrapped, without further ado, and went straight to code.
// The main logical processing method of the broadcast methodfunction broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
const name = child.$options.componentName;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else{ broadcast.apply(child, [componentName, eventName].concat(params)); }}); }exportDefault {methods: {// Define dispatch method Dispatch (componentName, eventName, Params) {let parent = this.$parent;
let name = parent.$options.componentName;
while(parent && (! name || name ! == componentName)) { parent = parent.$parent;
if (parent) {
name = parent.$options.componentName; }}if (parent) {
parent.$emit.apply(parent, [eventName].concat(params)); Broadcast (componentName, eventName, Params) {broadcast.call(this, componentName, eventName, params); }}};Copy the code
Broadcast triggers events to a specific parent component, dispatch triggers events to a specific child component, and is essentially an ON/EMIT wrapper, which is useful in some basic components.
Vuex status management
Vuex is a status management tool that enables centralized management of project status. The implementation of The tool borrows patterns and concepts from Flux, Redux, and The Elm Architecture. Unlike other patterns, Vuex is a state management library designed specifically for vue.js to leverage the fine-grained data response mechanism of vue.js for efficient state updates. For more information about Vuex, see the documentation on the website
Vue-router Indicates the route transmission parameter
When we need to transfer parameters across routing addresses, we can use vue-Router to officially provide us with our parameter transmission scheme to achieve component communication. Please refer to the official document for details
Vue.observable
2.6.0 New Usage: Make an object responsive. It is used internally by Vue to process objects returned by the data function; The returned object can be used directly in rendering functions and computed properties, and will trigger an update when changes occur; It can also serve as a minimal cross-component state store for simple scenarios. The communication principle is to implement a simple VUex by vuue. Observable
// File path - /store/store.js import Vue from'vue'
export const store = Vue.observable({ count: 0 })
export const mutations = {
setCount (Count) {store.count = Count}} // use <template> <div> <labelfor="bookNum"> </label> < button@click ="setCount(count+1)">+</button>
<span>{{count}}</span>
<button @click="setCount(count-1)">-</button>
</div>
</template>
<script>
import { store, mutations } from '.. /store/store'Vue2.6 added API Observableexport default {
name: 'Add',
computed: {
count () {
return store.count
}
},
methods: {
setCount: mutations.setCount
}
}
</script>
Copy the code
conclusion
The above is the detailed scheme description of Vue component communication, covering almost all communication schemes from Vue1.0 to Vue2.6. Vuue. Observable will be replaced by Reative API in Vue3.0. Check out the Vue Composition API for more updates, as well as component communication via the browser’s local store.