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

  1. Do not modify the parent’s state data directly in the child
  2. Where should the action (function) of updating the data be defined

1.2 Communication mode between VUE components

  1. props
  2. Custom events
  3. Message subscription and publishing
  4. Global event bus
  5. slot
  6. 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

  1. Declare all props within the component

  2. Method 1: Specify a name only

props: ['name'.'age'.'setName']
Copy the code
  1. Method 2: Specify the name and type
props: {
    name: String.age: Number.setNmae: Function
}
Copy the code
  1. 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:
    1. Data must be passed layer by layer if it is to be passed to non-offspring
    2. Sibling components cannot communicate with each other directly. They must be supported by the parent component

3. Customize events$emitChildren – > 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

  1. This method is only used when a child sends a message (data) to its parent
  2. Problem: Communication between intergenerational or sibling components is not appropriate

3.5 summarize

  1. Applies to: Child component ===> Parent component

  2. 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).

  3. Bind custom events:

    1. First, in the parent component: < demo@yk =”test”/> or

    2. The second way, in the parent component:

<Demo ref="demo"/ >...mounted(){
   this.$refs.xxx.$on('yk'.this.test)
}
Copy the code
  1. To make a custom event fire only once, you can use the once modifier, or the $once method.

  2. Emit custom event: this.$emit(‘yk’, data)

  3. Unbind custom event this.$off(‘yk’)

  4. Native DOM events can also be bound to components, requiring the use of native modifiers.

  5. 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

  1. Advantages: This approach enables communication between any relational components (data)

5.5 Two Important Operations of the Event

  1. Bind event listener (subscribe message)

5.6 summarize

  1. A method of communication between components, applicable to communication between any component.

  2. Use steps:

    1. Install pubsub: NPM I pubsub-js

    2. Import pubsub from ‘pubsub-js’

    3. 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
  1. Publish (‘ XXX ‘, data)

  2. 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