Vue父组件与子组件之间通信

Yukino 309 2021-12-29

一、父组件向子组件传递信息

  1. 利用props(这种比较基础,就不细写了)
// 父组件:
<template>
    <div>
        <child :message="message"></child>
    </div>
</template>
<script>
import child from 'child.js'

export default {
    components: {
        child
    },
    data() {
      return {
        message: 'message'
      }
    }
}
</script>


// 子组件:
<template>
    <div>
        {{ message }}
    </div>
</template>
<script>
export default {
    name: 'child',
    props: {
        message: {
            type: String
        }
    }
}
</script>
  1. 利用refs API
    首先来看看refs是什么,官方给出的描述:一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例,也就是说只要我们给子组件注册ref属性,之后便可以通过refs这个API获得到子组件的DOM元素和Vue组件实例,也就可以调用子组件的方法。
// 父组件:
<template>
    <div>
        <child ref="child"></child>
        <button @click="clear()">Clear</button>
    </div>
</template>
<script>
import child from 'child.js'

export default {
    components: {
        child
    },
    method: {
        clear() {
            this.$refs.clear();
        }
    }
}
</script>

// 子组件:
<template>
    <div>
        {{ message }}
    </div>
</template>
<script>
export default {
    name: 'child',
    data() {
      return {
        message: 'message'
      }
    },
    methods: {
        clear() {
            this.message = '';
        }
    }
}
</script>

二、子组件向父组件传递信息

回想我们在开发中,用element-ui、iview等这类组件时,数据是如何“绑定”到组件上的?v-model。

  1. $emit API
    首先还是来看看官方的说明emit触发当前实例上的事件。附加参数都会传给监听器回调,然后在父组件里使用v-on监听处理这个事件。
    Vue.component('welcome-button', {
      template: `
        <button v-on:click="$emit('welcome')">
          Click me to be welcomed
        </button>
      `
    })
    
    <div id="emit-example-simple">
      <welcome-button v-on:welcome="sayHi"></welcome-button>
    </div>
    
    new Vue({
      el: '#emit-example-simple',
      methods: {
        sayHi: function () {
          alert('Hi!')
        }
      }
    })
    
  2. v-model
    v-model本质上是一个语法糖,它包含一个prop和一个event,默认这个prop是value、event是input,先来看看下面的例子:
    // 子组件
    <template>
        <input :value="value" @input="handleInput" @change="handleChange"/>
    </template>
    
    <script>
    export default {
        name: 'Input',
        props: {
            value: [String, Number],
        },
        methods: {
            handleInput(event) {
                this.$emit('input', event.target.value);
            },
            handleChange(event) {
                this.$emit('input', event.target.value);
            },
        }
    }
    </script>
    
    // 父组件
    <Input v-model="value"/>
    
    <script>
    export default {
        data() {
            return {
                value: ''
            }
            }
        }
    }
    </script>
    

    子组件就是一个简单的input框,使用v-on监听绑定input和change事件(均为原生事件),在其value发生变化时调用this.$emit('input', event.target.value);,告诉父组件“我这里发生了input事件,我的value已经改变了,现在的值是event.target.value”,而在父组件上只要对input事件进行监听和处理即可,v-model其实就是在监听到input事件的时候,将子组件中的value prop赋值给绑定的参数。
    再来看看官方的例子:

    Vue.component('base-checkbox', {
      model: {
        prop: 'checked',
        event: 'change'
      },
      props: {
        checked: Boolean
      },
      template: `
        <input
          type="checkbox"
          v-bind:checked="checked"
          v-on:change="$emit('change', $event.target.checked)"
        >
      `
    })
    
    <base-checkbox v-model="lovingVue"></base-checkbox>
    

    最开始这个lovingVue的值会传给子组件的chekced变量,而当checked的值发生改变之后就会触发input的change事件(这里的change是HTML input原生的事件),进而调用v-on:change绑定的$emit('change', $event.target.checked)将事件传递给父组件,同时把改变后的值一并传过去,所以
    <base-checkbox v-model="lovingVue"></base-checkbox>
    其实就等同于

    <base-checkbox v-bind:checked="lovingVue" v-on:change="changeValue"></base-checkbox>
    
    <script>
    export default {
        data() {
          return {
              lovingVue: true
          }
        },
        methods: {
            changeVlaue(value) {
                this.lovingVue = value;
            }
        }
    }
    </script>
    

# 前端 # Vue