Vue implements communication between components

Keywords: Vue

I met such a requirement in the project. To change the data under data in one component, let's see how to implement it.

In this tutorial, it is mainly implemented through props/$emit. There are many other methods, as well as vuex, which can be implemented. Let's summarize later.

1. Nesting of components

There are two horizontal components in the project KitRecords.vue And KitDrawer.vue , which are contained in the parent component ResearchContent.vue Next, we need to pass KitRecords.vue Components to change KitDrawer.vue Component's drawerShowFlag property value

ResearchContent.vue The contents are as follows:

<template>
  <main>
    <section
      class="research-content"
      :class="drawerShowFlag ? 'research-content__small' : ''"
    >
      <!-- Here is KitRecords.vue assembly -->
      <router-view></router-view>
    </section>

    <!-- Here is KitDrawer.vue assembly -->
    <kit-drawer v-if="$route.name === 'KitRecords'">
      <kit-preview
        :research-id="researchBase.id"
        :title="researchBase.name"
      ></kit-preview>
    </kit-drawer>
  </main>
</template>

Component is vue.js One of the most powerful functions, and the scope of component instances is independent of each other, which means that the data between different components cannot reference each other. In order to realize the direct communication of components, the data of the child component needs to be passed to the parent component first, and then to another child component by the parent component.

2. The child component passes $emit to the parent component

First in subcomponent KitRecords.vue To call a method and implement $emit

There are two parameters, the first is the method in the parent component, and the second is the parameter passed to the method

KitRecords.vue The contents are as follows:

<template>
  <header>
    <el-button @click="drawerShowFlag">{{ title }}</el-button> // Bind a click event
  </header>
</template>
<script>
export default {
  data() {
    return {
      title:"Click to expand the sidebar"
    }
  },
  methods:{
    /**
      * @description: Call parent component ResearchContent.vue  showDrawer method in
      */
    changeTitle() {
      this.$emit("titleChanged","Pass value from child to parent");// The second parameter can be selected
    }
  }
}
</script>

In parent component ResearchContent.vue You can listen to events through v-on or @

ResearchContent.vue The contents are as follows:

<template>
  <main>
    <section
      class="research-content"
      :class="drawerShowFlag ? 'research-content__small' : ''"
    >
      <!-- Here is KitRecords.vue assembly -->
        <!-- monitor showDrawer event -->
      <router-view @showDrawer="showDrawer"></router-view>
    </section>

    <!-- Here is KitDrawer.vue assembly -->
    <kit-drawer v-if="$route.name === 'KitRecords'">
      <kit-preview
        :research-id="researchBase.id"
        :title="researchBase.name"
      ></kit-preview>
    </kit-drawer>
  </main>
</template>
<script>
export default {
  data() {
    return {
      drawerShow: false,
    }
  },
  methods:{
    /**
      * @description: This method is called by the subcomponent
      */
    showDrawer(e) {
      this.drawerShow = true;
    }
  }
}
</script>

3. The child component receives the value of the parent component through props

In parent component ResearchContent.vue Through v-bind to the subcomponent KitDrawer.vue Pass parameters

ResearchContent.vue The contents are as follows:

<template>
  <main>
    <section
      class="research-content"
      :class="drawerShowFlag ? 'research-content__small' : ''"
    >
      <!-- Here is KitRecords.vue assembly -->
        <!-- monitor showDrawer event -->
      <router-view @showDrawer="showDrawer"></router-view>
    </section>

    <!-- Here is KitDrawer.vue assembly -->
      <!-- adopt v-bind To subcomponent KitDrawer Pass parameters -->
    <kit-drawer v-if="$route.name === 'KitRecords'" :drawerShow="drawerShow">
      <kit-preview
        :research-id="researchBase.id"
        :title="researchBase.name"
      ></kit-preview>
    </kit-drawer>
  </main>
</template>
<script>
export default {
  data() {
    return {
      drawerShow: false,
    }
  },
  methods:{
    /**
      * @description: This method is called by the subcomponent
      */
    showDrawer(e) {
      this.drawerShow = true;
    }
  }
}
</script>

In subcomponent KitDrawer.vue Receive parameters through props in

KitDrawer.vue The contents are as follows:

<template>
	<!--Omitted here-->
</template>
<script>
export default {
  props: {
    drawerShow: { // Parameters defined in the parent component
      type: Boolean, // Here is the type of receive parameter
      default: false, // This field seems useless
    },
  },
  data() {
    return {
      drawerShowFlag: false
    };
  },
  watch: {
    'drawerShow': function (val) {
      // Listening for properties in props
      this.drawerShowFlag = val;
    }
  },
  methods: {
      // Omitted here
  },
};
</script>

Here's a question. After props receives the parameters, it tries to use the drawerShowFlag= this.drawerShow Assign a value to the data in data. It is found that it is not possible. Then, we can operate by listening to events. In Vue, we can listen through calculated and watch. Here, I use watch to monitor the changes of props properties. If the props changes (i.e. the parameters passed by the parent component are received), we will assign the props to the drawerShowFlag to get the parameters passed by the component.

4. What to pay attention to

In this project KitRecords.vue Component already in router.js The route is registered in, but KitDrawer.vue There is no registration, so you need to import the component in the parent component and add it to components.

ResearchContent.vue The contents are as follows:

<template>
  <main>
    <section
      class="research-content"
      :class="drawerShowFlag ? 'research-content__small' : ''"
    >
      <!-- Here is KitRecords.vue assembly -->
        <!-- monitor showDrawer event -->
      <router-view @showDrawer="showDrawer"></router-view>
    </section>

    <!-- Here is KitDrawer.vue assembly -->
      <!-- adopt v-bind To subcomponent KitDrawer Pass parameters -->
    <kit-drawer v-if="$route.name === 'KitRecords'" :drawerShow="drawerShow">
      <kit-preview
        :research-id="researchBase.id"
        :title="researchBase.name"
      ></kit-preview>
    </kit-drawer>
  </main>
</template>
<script>
// Import required subcomponents
import KitDrawer from './records/KitDrawer.vue';
import KitPreview from './plan/KitPreview.vue';

export default {
  name: 'research-content',
  components: {
    // Add components to components
    KitPreview,
    KitDrawer,
  },
  data() {
    return {
      drawerShow: false,
    }
  },
  methods:{
    /**
      * @description: This method is called by the subcomponent
      */
    showDrawer(e) {
      this.drawerShow = true;
    }
  }
}
</script>

5. References

I think this article is very comprehensive and worth collecting

Six ways of communication between vue components (complete version)

Posted by les48 on Fri, 19 Jun 2020 22:08:04 -0700