首页 > 技术分享 > Vue
收藏

Vue自定义事件,$emit使用方法

11/29 22:12
大潇博客 原创文章,转载请标明出处

自定义事件

在封装组件时,为了让组件的使用者可以监听到组件内状态的变化,此时需要用到组件的自定义事件。

比如这样的情况:

  • 通过子组件中声明的事件,触发父组件的事件
  • 通过子组件中声明的事件,改变父组件传递的属性值

上面这些场景,需要父组件和子组件之间进行通讯,即:子组件通过抛出事件通知父组件。这就用到组件的自定义事件:一种组件间通信的方式,适用于:子组件 ==> 父组件

一个子组件可以抛出很多事件,属性可以一层接一层向下传递,事件可以一层接一层向上抛


自定义事件的3个使用步骤

① 封装组件时 — 声明自定义事件

② 封装组件时 — 触发自定义事件

③ 使用组件时 — 监听自定义事件


声明自定义事件

组件内封装的自定义事件,必须事先在 emits 节点中声明,才能有效抛出事件,有两种实现方式:

方式一:直接使用 $emit 抛出事件

<!-- 子组件:必须在 emits 节点中声明自定义事件 -->

<template>

<div> {{count}} </div>

<!-- $emit 是 vue 的内置函数,它可有 1~n 个参数:第一个为必须,表示抛出的事件名称(父组件接收使用);第二个之后均表示事件的参数 -->

<div @click="$emit('change',123)">子组件抛出事件</div>

</template>

<script>

export default{

name: 'MyCounter',

data() { return { count: 1 } },

emits: ['change'], //必须声明自定义事件,抛出事件才有效

}

<script>

方式二:先触发子组件 methods 中的方法,在方法内通过 this.$emit('自定义事件名称', 可选参数),向父组件抛出自定义事件

<template>

<div> {{count}} </div>

<!-- 先触发 methods 中的方法,在方法内抛出自定义事件 -->

<button @click="add">数字+1</button>

</template>

<script>

export default{

name: 'MyCounter',

data() { return { count: 1 } },

emits: ['change'], //必须声明自定义事件,抛出事件才有效

methods: {

add() {

this.count++

this.$emit("change"); //抛出自定义事件

}

}

}

<script>


监听(使用)自定义事件

在使用自定义组件时,父组件需要注册自定义事件,可以通过 v-on 的形式监听自定义事件,格式为:@自定义事件名称,比如上面的案例中,抛出了 change 事件,使用就是:@change

<!-- 父组件:监听子组件内的 change 自定义事件 -->

<MyCounter @change="getmsg"></MyCounter>

<script>

export default{

getmsg(){

console.log("监听到了组件自定义事件")

}

}

</script>


自定义事件传参

在调用 this.$emit() 方法触发自定义事件时,可以通过第 2 个参数(以及之后的所有参数)为自定义事件传参

<!-- 子组件:定义自定义事件 -->

<script>

export default{

name: 'MyCounter',

data() { return { count: 1 } },

emits: ['change'], //声明自定义事件

methods: {

add() {

this.count++

this.$emit("change", this.count, '第二个参数', '第三个参数'); //触发自定义事件,并传递参数

}

}

}

<script>

向外传递的数据,可以通过事件处理函数的形参直接接收到

<!-- 父组件:监听子组件的自定义事件 -->

<MyCounter @change="getmsg"></MyCounter>

<script>

export default{

methods: {

// 接收子组件传递的形参

getmsg(arguments1, arguments2, arguments3){

console.log("监听到了组件自定义事件")

console.log(arguments1, arguments2, arguments3)

}

}

}

</script>


通过自定义事件修改组件中参数的值

vue 提供了 v-model 这个双向数据绑定的指令,它可以对表单元素进行数据绑定,快速渲染和获取表单元素的值。

当需要维护组件内外数据的同步时,同样可以在组件标签上使用 v-model 指令

注意:emits 中有两个参数,第一个是“update:属性名”,第二个时要修改的值


通过案例说明

比如:点击子组件中的按钮,改变父组件中的值

① 在子组件中,通过 props 接收父组件传递的参数,再通过 emits 抛出自定义事件,emits 中有两个参数,第一个是“update:属性名”,第二个时要修改的值

<!-- 子组件:ChildData.vue -->

<template>

<div>子组件:{{ name }}</div>

<button @click="update">修改</button>

</template>

<script>

export default {

name: 'ChildData ',

//通过 props 属性接收传父组件传递的值

props: ['name'],

//在 emits 中声明自定义事件,事件名称中必须有一个固定前缀"update:",要更新哪个属性,就把属性名写到 update 后面

emits: ['update:name'],

methods: {

update() {

this.$emit("update:name", "Lucy") //触发 update 事件时,携带的参数用于修改父组件中对应参数的值

}

}

}

</script>

② 父组件通过 v-model 绑定参数,并监听参数的变化,当点击子组件中的按钮时,触发自定义事件,name 的值被修改

<!-- 父组件:ParentData.vue -->

<template>

<div>父组件:{{ name }}</div>

<!-- 使用子组件,通过 v-model 绑定参数 -->

<ChildData v-model:name="name" />

</template>

<script>

import ChildData from 'ChildData .vue';

export default {

name: 'ParentData',

components: {

ChildData

}

data() {

return {

name: 'Tom'  //父组件传递的参数

}

}

}

</script>


通过自定义事件,实事传递 input 中的值

<!-- 父组件 -->

<template>

<div class="main">

<div>{{ nm }}</div>

<!-- 父组件中通过v-model绑定value值 -->

<input-data title="名称" name="name" placeholder="请输入名称" v-model:value="nm"></input-data>

</div>

</template>

<script>

import InputData from "./InputData.vue";

export default {

name: 'BodyMain',

components: {

InputData

},

data() {

return {

nm: 'test',

}

}

}

</script>

触发自定义事件,父组件中通过 v-model 绑定的值发生改变,实现子组件向父组件传值

<!-- 子组件 -->

<template>

<div>

<span>{{title}}:</span>

<input type="text" :name="name" :placeholder="placeholder" :value="value || ''" @keyup="change" />

</div>

</template>

<script>

export default {

name: 'InputData',

props: {

title: {

type: String,

required: true,

default: ''

},

name: {

type: String,

required: true,

default: ''

},

placeholder: {

type: String,

required: false,

default: ''

},

value: {

type: String,

required: false

}

},

emits: ['update:value'], //在emits中声明自定义事件,事件名称中必须有一个固定前缀"update:",要更新哪个属性,就把属性名写到update后面

methods: {

change(e) {

this.$emit('update:value', e.target.value) //将value绑定的值改为input输入的值,由于父组件中通过v-model绑定value,所以值也会实时变化

}

}

}

</script>


打赏

阅读排行

大家都在搜

博客维护不易,感谢你的肯定
扫码打赏,建议金额1-10元
  • 15601023311