A: hi! ~ Hello everyone, I am YK bacteria 🐷, a microsystem front-end ✨, love to think, love to summarize, love to record, love to share 🏹, welcome to follow me 😘 ~ [wechat account: Yk2012Yk2012, wechat public account: ykyk2012]
“This is the 26th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”
Today we will focus on the way components communicate in Vue
1. Start
1.1 Communication Principles between Components
- Do not modify the parent’s state data directly in the child
- Where should the action (function) of updating the data be defined
1.2 Communication mode between VUE components
- props
- Custom events
- Message subscription and publishing
- Global event bus
- slot
- Vuex [more later]
2. Props parent — > child
Used to pass data from a parent to a child
2.1 Using component Labels
When the tag attribute is passed in
<my-component name='yk' :age='3' :set-name='setName'></my-component>
Copy the code
2.2 When defining MyComponent
-
Declare all props within the component
-
Method 1: Specify a name only
props: ['name'.'age'.'setName']
Copy the code
- Method 2: Specify the name and type
props: {
name: String.age: Number.setNmae: Function
}
Copy the code
- Method 3 [full version] : Specify name/type/necessity/default
props: {
name: {type: String.required: true.default:xxx},
}
Copy the code
2.3 pay attention to
- This is used when a parent passes data to a child
- All tag properties become properties of the component object and can be referenced directly by the template page
- Question:
- Data must be passed layer by layer if it is to be passed to non-offspring
- Sibling components cannot communicate with each other directly. They must be supported by the parent component
3. Customize events$emit
Children – > father
3.1 Binding Event listening
// Mode 1: Bind using V-ON
@delete_todo="deleteTodo"
$on();
this.$refs.xxx.$on('delete_todo'.function (todo) {
this.deleteTodo(todo)
})
Copy the code
3.2 Triggering Events
// Trigger event (only received in parent component)
this.$emit(eventName, data)
Copy the code
3.3 the sample
Previously the binding event listened for the parent component to pass to the child component
<TodoHeader :addTodo="addTodo" />
Copy the code
become
<TodoHeader @addTodo="addTodo" />
Copy the code
Or it
<TodoHeader ref="header" />
Copy the code
mounted(){// Execute code asynchronously
// Bind addTodo event listener
// this.$on('addTodo', this. AddTodo
this.$refs.header.$on('addTodo'.this.addTodo)
}
Copy the code
The child component fires the event
this.addTodo(todo); // Code in demo2
Copy the code
become
this.$emit('addTodo', todo)
Copy the code
3.4 pay attention to
- This method is only used when a child sends a message (data) to its parent
- Problem: Communication between intergenerational or sibling components is not appropriate
3.5 summarize
-
Applies to: Child component ===> Parent component
-
Usage scenario: A is the parent component and B is the child component. If B wants to send data to A, it needs to bind custom events to B in A (the event callback is in A).
-
Bind custom events:
-
First, in the parent component: < demo@yk =”test”/> or
-
The second way, in the parent component:
-
<Demo ref="demo"/ >...mounted(){
this.$refs.xxx.$on('yk'.this.test)
}
Copy the code
-
To make a custom event fire only once, you can use the once modifier, or the $once method.
-
Emit custom event: this.$emit(‘yk’, data)
-
Unbind custom event this.$off(‘yk’)
-
Native DOM events can also be bound to components, requiring the use of native modifiers.
-
Note: when using this.$refs.xxx.$on(‘yk’, callback) to bind custom events, either the callback is configured in Methods or the arrow function is used, otherwise the this pointer will fail!
4. EventBus.$emit
.$on
Define an event-bus.js
import Vue from 'vue'
const eventBus = new Vue()
export default eventBus
Copy the code
Import in the required components
import eventBus from './event-bus'
Copy the code
Dispatches to eventBus during events and carries data
eventBus.$emit('addItem'.this.title)
Copy the code
Receive data in the component that needs it
mounted() {
eventBus.$on('addItem'.this.handleAddTitle)
}
Copy the code
Using the data
methods: {
handleAddTitle(title){
console.log(title)
}
}
Copy the code
Unbind event listener
beforeDestroy(){
eventBus.$off('addItem'.this.handleAddTitle)
}
Copy the code
5. Message subscription and publication (PubSubJS library)
5.1 Subscribing Messages
PubSub.subscribe('msg'.function(msg, data){})
Copy the code
5.2 Releasing Messages
PubSub.publish('msg', data)
Copy the code
5.3 the sample
Subscribe message (bind event listener)
import PubSub from 'pubsub-js'
export default {
mounted () {
// Subscribe message (deleteTodo)
PubSub.subscribe('deleteTodo'.(msg, index) = > {
this.deleteTodo(index)
})
}
}
Copy the code
Publish a message (trigger event)
// this.deleteTodo(this.index)
// Publish the message (deleteTodo)
PubSub.publish('deleteTodo'.this.index)
Copy the code
5.4 pay attention to
- Advantages: This approach enables communication between any relational components (data)
5.5 Two Important Operations of the Event
- Bind event listener (subscribe message)
5.6 summarize
-
A method of communication between components, applicable to communication between any component.
-
Use steps:
-
Install pubsub: NPM I pubsub-js
-
Import pubsub from ‘pubsub-js’
-
Receive data: If component A wants to receive data, it subscribes to the message in component A, and the subscribed callback remains in component A itself.
-
methods(){
demo(data){... }}...mounted() {
this.pid = pubsub.subscribe('xxx'.this.demo) // Subscribe to the message
}
Copy the code
-
Publish (‘ XXX ‘, data)
-
It is best to unsubscribe with pubsub. unsubscribe(PID) in the beforeDestroy hook.
<template>
<div class="school">
<h2>School Name: {{name}}</h2>
<h2>School Address: {{address}}</h2>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name:'School'.data() {
return {
name:Silicon Valley.address:'Beijing',}},mounted() {
// console.log('School',this)
/ * this. $bus. $on (' hello ', (data) = > {the console. The log (' I am a School components, has received the data, data)}) * /
this.pubId = pubsub.subscribe('hello'.(msgName,data) = >{
console.log(this)
// console.log(' Hello message was posted, hello callback executed ',msgName,data)})},beforeDestroy() {
// this.$bus.$off('hello')
pubsub.unsubscribe(this.pubId)
},
}
</script>
<style scoped>
.school{
background-color: skyblue;
padding: 5px;
}
</style>
Copy the code
<template>
<div class="student">
<h2>Student name: {{name}}</h2>
<h2>Gender: {{sex}}</h2>
<button @click="sendStudentName">Give the student name to the School component</button>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name:'Student'.data() {
return {
name:'Joe'.sex:'male',}},mounted() {
// console.log('Student',this.x)
},
methods: {
sendStudentName(){
// this.$bus.$emit('hello',this.name)
pubsub.publish('hello'.Awesome!)}}}</script>
<style lang="less" scoped>
.student{
background-color: pink;
padding: 5px;
margin-top: 30px;
}
</style>
Copy the code
6. Communication between components 4: slot
6.1 understand
This method is used when a parent component passes label data to a child component
6.2 Child Component: child.vue
<template>
<div>
<slot name="xxx">Uncertain label structure 1</slot>
<div>Component determines the label structure</div>
<slot name="yyy">Uncertain label structure 2</slot>
</div>
</template>
Copy the code
6.3 Parent Component: parent.vue
<child>
<div slot="xxx">Structure of the label corresponding to XXX</div>
<div slot="yyy">Yyyy Indicates the label structure</div>
</child>
Copy the code
Let’s review slots
anonymousslot
A placeholder is defined inside the child component, which can be used by the parent component to insert anything into the component label to replace the content in the child component slot
A namedslot
You can distribute multiple contents by giving a name to the slot element
Example subcomponent template definitions
<template>
<div class="container">
<div class="header">
<slot name="header"></slot>
</div>
<div class="main">
<slot></slot>
</div>
<div class="footer">
<slot name="footer"></slot>
</div>
</div>
</template>
Copy the code
Parent component use
<child-component>
<h2 slot="header">The title</h2>
<p>content</p>
<p>More and more</p>
<div slot="footer">At the bottom of the</div>
</child-component>
Copy the code
Finally equivalent to
<div class="container">
<div class="header">
<h2>The title</h2>
</div>
<div class="main">
<p>content</p>
<p>More and more</p>
</div>
<div class="footer">
<div>At the bottom of the</div>
</div>
</div>
Copy the code
The slot here is obsolete and must be wrapped with the template tag instead of v-slot, which can be shortened to #
<child-component>
<template v-slot:header>
<h2>The title</h2>
</template>
<p>content</p>
<p>More and more</p>
<template #footer>
<div slot="footer">At the bottom of the</div>
</template>
</child-component>
Copy the code
Scope slot
The child component’s data is tagged to the parent component
<template>
<h1>
<slot :user="user">
{{ user.name }}
</slot>
</h1>
</template>
<script>
export default {
data() {
return {
user: {
name: 'YK'.age: 18}}}}</script>
Copy the code
The parent component receives the data and uses it
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.age }}
</template>
</current-user>
Copy the code
Object structure assignment is more concise
<current-user>
<template v-slot:default="{ user }">
{{ user.age }}
</template>
</current-user>
Copy the code
Finally, welcome to my column and make friends with YK bacteria