Communication between parent and child components in vue (code demonstration and explanation)

1. Communication between parent and child components

Child components cannot reference the data of the parent component or the root instance of Vue.

However, in development, some data does need to be passed from the upper layer to the lower layer:

  • For example, in a page, we request a lot of data from the server.
  • Part of the data is not displayed by the large components of our entire page, but by the following sub-components.
  • At this time, the child component is not allowed to send a network request again, but the big component (parent component) is directly passed to the small component (child component).

How to communicate between parent and child components?

  • Father to son: by propstransmitting data to the sub-assembly
  • Parent child transmission: by $emitsending the event to the parent component
    Insert picture description here

2. From Father to Son

2.1 Use props

In the subassembly, using propsdata received from the need to declare to the parent component. Where the parent component uses the child component, use the v-bind method to pass the data to the child component.

There are two ways of props value:

  • Method 1: String array, the string in the array is the name when passed.
  • Method 2: Object, the object can be set to the type when it is delivered, or it can be set to the default value.

Borrow the picture of teacher coderwhy to show the specific usage of props in detail:

Insert picture description here

2.2 Code demonstration

You can copy the code directly to your computer for testing

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>6</title>
</head>
<body>

<div id="app">
  <cpn1></cpn1>
</div>

<template id="cpn1">
  <div>
    <h2>{
   
   {title}}</h2>
    <h2>我是父组件的内容</h2>
    <h2>-----------------</h2>
    <!-- 父组件传递数据给子组件 -->
    <!-- 使用v-bind语法才会将后边的 title 当做变量去父组件的data中寻找,
    如果没有使用 v-bind,title 就会当做字符串传递给 ctitle -->
    <cpn2 :ctitle="title" :cmovies="movies"></cpn2>
  </div>
</template>

<template id="cpn2">
  <div>
    <h2>{
   
   {ctitle}}</h2>
    <ul>
      <li v-for="item in cmovies">{
   
   {item}}</li>
    </ul>
  </div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

  // cpn1 是父组件,父组件中有 title 和 movies 数据
  // cpn2 是子组件,在子组件中定义 props ,
  // props中声明两个属性:ctitle 和 cmovies ,用来接收父组件传递的数据并使用

  Vue.component('cpn1', {
     
     
    template: '#cpn1',
    data() {
     
     
      return {
     
     
        title: '我是标题',
        movies: ['电影1', '电影2', '电影3']
      }
    },
    components: {
     
     
      cpn2: {
     
     
        template: '#cpn2',
        // props: ['ctitle', 'cmovies']
        props: {
     
     
          // ctitle:String,//对数据做一些类型限制
          // cmovies:Array
          ctitle: {
     
     
            type: String, //进行类型限制
            default: '我是默认值',//当父组件没有给子组件传递数据时,就会使用默认值
          },
          cmovies: {
     
     
            type: Array,
            //类型是对象和数组时,默认值必须是一个函数
            default(){
     
     
              return []
            }
          }
        }
      }
    }
  })

  let vm = new Vue({
     
     
    el: "#app",
    data: {
     
     }
  });
</script>

</body>
</html>

The result is shown in the figure:
Insert picture description here


3. Son to Father

3.1 Use $emit

When the child component needs to pass data to the parent component, it is necessary to use custom events.

The flow of custom events:

  • In sub-assemblies by $emit()triggering events.
  • In the parent component by v-onto monitor sub-component events. V-on can be used not only to monitor DOM events, but also to customize events between components.

3.2 Code demonstration

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>8</title>
</head>
<body>

<!--父组件模板-->
<div id="app">
 <!--  此处不是浏览器产生的事件对象,是我们自定义的事件。当不加括号时,会默认传递子组件通过 $emit 发射事件时添加的数据-->
  <cpn @item-click="cpnClick"></cpn>
</div>

<!--子组件模板-->
<template id="cpn">
  <div>
    <!-- 在子组件中的按钮,同时监听点击事件 -->
    <button v-for="item in categories" @click="btnClick(item)">{
   
   {item.name}}</button>
  </div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
  let cpn = {
     
     
    template: '#cpn',
    data(){
     
     
      return {
     
     
        categories:[
          {
     
     id:'1',name:'手机'},
          {
     
     id:'2',name:'电脑'},
          {
     
     id:'3',name:'书籍'},
          {
     
     id:'4',name:'家电'},
        ],
        data:'data',
        str:'str'
      }
    },
    methods:{
     
     
      btnClick(item){
     
     
        console.log(item);
        //子组件向父组件传递事件,第一个参数是自定义事件名,后边的参数是数据
        this.$emit('item-click',item,'hello')
      }
    }
  }
  let vm = new Vue({
     
     
    el: "#app",
    data: {
     
     },
    components: {
     
     
      cpn
    },
    methods:{
     
     
      cpnClick(data,str){
     
     
        console.log('----',data,str);
      }
    }

  });
</script>

</body>
</html>

Insert picture description here


4. Matters needing attention

Avoid directly modifying the data in props through subcomponents , which will cause errors.

Reason: The data source in the props of the child component is the parent component, that is, when the related data in the parent component changes, the data in the child component props will also change. If we also modify the data in props in the subcomponent at this time, it is equivalent to one data can be modified in two places, which is not good.

<div id="app">
  <cpn :number="num"></cpn>
</div>

<template id="cpn">
  <div>
    <h2>子组件props中的:{
   
   {number}}</h2>
    <!-- 我们通过 v-model 来尝试修改在子组件的 props 中声明的 number   -->
    <input type="text" v-model="number">
  </div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

  let cpn = {
     
     
    template: '#cpn',
    props: {
     
     
      number: Number,
    }
  }

  let vm = new Vue({
     
     
    el: "#app",
    data: {
     
     
      num: 1,
    },
    components: {
     
     
      cpn
    }
  });
</script>

Insert picture description here
The code above will report an error. To avoid an error information presentation directly modify the data in the props, but can be data or computing properties to achieve the same effect in place of FIG.

We slightly modify the above code, add a data to the sub-component, and at the same time change v-model to bind the data in data

<div id="app">
  <cpn :number="num"></cpn>
</div>

<template id="cpn">
  <div>
    <h2>子组件props中的:{
   
   {number}}</h2>
    <!-- 我们通过 v-model 绑定到 data 中 dataNumber  -->
    <input type="text" v-model="dataNumber">
  </div>
</template>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>

  let cpn = {
     
     
    template: '#cpn',
    //加一个 data,数据来源是 props 中的数据
    data(){
     
     
      return {
     
     
        dataNumber:this.number
      }
    },
    props: {
     
     
      number: Number,
    }
  }

  let vm = new Vue({
     
     
    el: "#app",
    data: {
     
     
      num: 1,
    },
    components: {
     
     
      cpn
    }
  });
</script>

Guess you like

Origin blog.csdn.net/weixin_43974265/article/details/112632738
Recommended