当组件的数据或者状态发生变化时,可以触发一个自定义事件,供父组件实现一些额外操作。
触发自定义事件一般有两种情况:
- 组件的数据发生变化,需要将这种变化反馈给父组件,例如
- v-model 双向绑定
- Watch 数据的变化并触发事件
- ……
- 由组件内的其他子组件触发的事件,需要回馈给父组件,例如
- 表单输入组件常用的
input
事件和change
事件 - 按钮组件的
click
事件 - ……
- 表单输入组件常用的
触发与回调
在数据或者状态变化的过程中触发一个事件:
this.$emit('myEventName', /* 事件回调参数 */)
this.$emit('eventA')
this.$emit('eventB', 12)
this.$emit('eventC', 12, 13)
在父组件中指定触发事件的回调:
<my-component @my-event-name="changeSomething" />
<component-a @event-a="() => ..." />
<component-b @event-b="x => ..." />
<component-c @event-c="(x, y) => ..." />
定义与验证
文档给出了统一定义与验证自定义事件的地方,但是我似乎没找到这个预留的接口。
统一定义和验证是为了能清晰的看到组件有哪些自定义事件,不写好像也行。
v-model
prop 负责将数据从父组件传递到子组件;事件负责在子组件数据发生改变时触发事件,将变化反馈给父组件,父组件通过回调修改对应数据,即将数据从子组件传回父组件。
v-model 是 prop 与自定义事件的组合,只不过触发事件时执行的回调是固定的:总是将子组件变化后的数据重新赋给传递给子组件 prop 的引用变量。
默认情况下,子组件的modelValue
prop 负责接受 v-model 绑定传递过来的值:
{
props: {
modelValue: String
}
}
此外我们还需要在子组件中某个数据或者状态改变时触发update:modelValue
事件来将modelValue
当前状态反馈给父组件,父组件会自动触发这个事件的回调(即无需我们设置@update:modelValue="..."
)将子组件返回的数据更新到 v-model 绑定的响应式变量。
this.$emit('update:modelValue', someValue)
此外,modelValue
prop 对应的触发事件可以修改为其他,但是似乎没有必要。
带参的 v-model
默认的 v-model 对应的modelValue
prop 和 update:modelValue
event。
通过给 v-model 指定传递参数可以指定其他 prop 和 event:
<my-component v-model:name="nameVar" />
{
props: {
name: String
}
}
// 在某个地方
this.$emit('update:name', ...)
通过指定 v-model 指令的参数,可以实现一个组件多个数据的双向流动。
v-model 修饰符
跟在 v-model 后面以.
开始的部分就是指令修饰符,例如v-model.trim
。例如
- 单行字符串表单输入组件内置了
trim
修饰符,用于移除输入值前后的空白符
v-model 修饰符能够按照其定义对子组件返回的数据进行预处理,然后再由父组件接收。
修饰符本质上只是一个标志位,我们仍然需要在子组件中手动检测是否有该修饰符在触发事件返回数据前进行一些处理。
指定的修饰符存储在 prop 中,其 prop 名称规则如下:
- 默认的 v-model 对应的修饰符集合的 prop 为
modelModifiers
,例如v-model.trim
可以通过modelModifiers.trim
访问到,如果使用了该修饰符,modelModifiers.trim
的值为true
- 带参数的 v-model 例如
v-model:name
对应的修饰符集合是nameModifiers
在检测数据变化时,通过修饰符集合取出修饰符的状态进行判断,然后进行一些数据处理。
修饰符是在 v-model 绑定的事件触发之后才会执行,不触发事件便不会执行修饰功能。比如 v-model 绑定数据时传入了初始数据,但是子组件中触发update:modelValue
事件的数据修改从未发生,那么update:modelValue
事件就不会被触发,修饰符也就不会发生作用,此时 v-model 绑定的数据不会发生任何变化。
评论区