有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。
许多Vue模式波及应用props
将数据从父组件传递到子组件。但如果咱们须要一个子组件将数据传给它的父组件呢?
应用 emit
,咱们能够触发事件并将数据传递到组件的层次结构中。这对上面几种状况很有用,如:
- 从 input 中收回数据
- 从 modal 自身外部敞开 modal
- 父组件响应子组件
Vue Emit是如何工作的?
当咱们 emit 一个事件时,咱们用一个或多个参数调用一个办法:
- eventName: string - 事件的名称
- values: any - 通过事件传递的参数
上面是一个内联 emit的例子,<button @click="$emit('add', Math.random())">
。emit一个名为add
的事件,并将Math.random()
的值作为参数传递进来。
而后,在父组件应用v-on
或@
指令能够监听咱们的自定义增加事件并接管该参数值。
Child.vue
<template> <button @click="$emit('add', Math.random())"> Add Math.random() </button></template>
在 Parent.vue 中监听:
<script setup>import { ref } from 'vue'const count = ref(0)// 也能够从咱们的模板中调用一个函数 `<ChildComponent @add="add" />// const add = (i) => count.value += i</script><template> <ChildComponent @add="(i) => count += i" /> <p>Count: {{ count }}</p></template>
每次咱们点击按钮,Child.vue
都会 emit 一个 add
事件,并带有一个0到1之间的随机值。 而后,Parent.vue
捕捉到这个事件,并将这个值增加到计数中。
能够传递任意多的参数,监听器也会收到所有的参数:
- Child -
$emit('add', Math.random(), 44, 50)
- Parent -
@add="(i, j, k) => count += i + j + k"
当初,咱们晓得如何在咱们的模板中 emit 内联事件,但在更简单的例子中,如果咱们从SFC的script
中 emit 一个事件会更好。特地是当咱们想在 emit 事件之前执行一些逻辑时,这很有用。
在Vue 3中,咱们有2种不同的办法来做到这一点:
- 选项API -
this.$emit
- 带有
setup()
的组合API -context.emit
- 带有
<script setup>
的组合API -defineEmits()
咱们一个一个来看。
选项API - this.$emit
在 Vue3 中,我人能够抉择应用选项API或组合API。
在选项API中,咱们能够调用this.$emit
来 emit一个自定义事件。
看上面这个例子在 MyTextInput.vue
中,它蕴含一个 label
和 input
。每当 input
扭转时,咱们会 emit 一个事件,并将输出的值转成大写作为参数传递进来。
咱们能够不从模板中调用$emit
,而是调用一个组件办法。在该办法中调用this.$emit
并把咱们的值传给它。
MyTextInput.vue
<script> export default { methods: { handleChange (event) { this.$emit("customChange", event.target.value.toUpperCase()) } } }</script><template> <div> <label>My Custom Input</label> <input type="text" placeholder="Custom input!" @input="handleChange" /> </div></template>
在 Parent.vue 中接管:
<script> export default { methods: { handleChange (event) { this.$emit("customChange", event.target.value.toUpperCase()) } } }</script><template> <div> <label>My Custom Input</label> <input type="text" placeholder="Custom input!" @input="handleChange" /> </div></template>
带有setup()
的组合API - context.emit
在 组合API中,如果应用setup
函数,就不能在用 this
,也就是不能调用this.$emit()
办法了。
相同,能够应用 setup 办法中的第二个参数 context
来拜访 emit
办法。咱们能够用之前应用的事件名称和值调用context.emit
。
MyTextInput.vue
<script> export default { // can use the entire context object setup (props, context) { const handleChange = (event) => { context.emit("customChange", event.target.value) } return { handleChange } }, // or we can destructure it and get `emit` setup (props, { emit }) { const handleChange = (event) => { emit("customChange", event.target.value) } return { handleChange } } }</script><template> <div> <label>My Custom Input</label> <input type="text" placeholder="Custom input!" @input="handleChange" /> </div></template>
在 <script setup>
中的用法
当咱们应用<script setup>
时,咱们无法访问组件实例或 context
上下文参数。那咱们怎么取得 emit
?
在这种状况下,咱们能够应用 defineEmits
:
- 指定组件要 emit 事件
- 为每个事件增加验证信息
- 能够拜访与context.emit雷同的值
在最简略的状况下,defineEmits
是一个字符串数组,每个字符串是一个事件的名称。
MyTextInput.vue
<script setup>const emit = defineEmits(['customChange'])const handleChange = (event) => { emit('customChange', event.target.value.toUpperCase())}</script>
然而,如果咱们传递一个对象,咱们能够为每个事件增加一个验证器函数,咱们能够在外面查看值是否是咱们所须要的格局。
像事件监听器一样,验证器承受咱们传入所有参数。
这与prop validation 相似,如果咱们的验证器返回 false
,会在控制台失去一个正告,这为咱们提供了一些有用的信息。
MyTextInput.vue
<script setup>const emit = defineEmits({ unvalidatedEvent: null, // if we want an event without validation customChange: (s) => { if (s && typeof s === 'string') { return true } else { console.warn(`Invalid submit event payload!`) return false } },})const handleChange = (event) => { // no console warning emit('customChange', event.target.value.toUpperCase())}onMounted(() => { emit('customChange', 1) // not a string, warning!})</script>
最佳实际
应用 emits 定义自定义事件。
如果咱们不应用defineEmits
,咱们依然能够通过export default
中定义emits
选项来跟踪一个组件的自定义事件。
这对保持良好的组件文档很重要,如果咱们试图应用一个没有在 emits 中申明的事件,也会从Vue那里失去谬误。
当在 emits 选项中定义了原生事件 (如 change) 时,将应用组件中的事件代替原生事件侦听器。
<script> export default { emits: ["change"] // or can pass object with validators }</script><template> <div> <label>My Custom Input</label> <input type="text" placeholder="Custom input!" @input='$emit("change", $event.target.value)' /> </div></template>
正确的事件命令
在 vue3 中,与组件和 prop 一样,事件名提供了主动的大小写转换。如果在子组件中触发一个以 camelCase (驼峰式命名) 命名的事件,你将能够在父组件中增加一个 kebab-case (短横线分隔命名) 的监听器。
然而,如果你应用的是Vue 2,事件名称没有主动的大小写转换,因为v-on
指令会主动将你的事件名称转换为小写,所以camelCase命名的事件不可能被监听到。
例如,如果咱们收回了一个名为myEvent
的事件,监听my-event
将无奈工作。
编辑中可能存在的bug没法实时晓得,预先为了解决这些bug,花了大量的工夫进行log 调试,这边顺便给大家举荐一个好用的BUG监控工具 Fundebug。
作者:Noveo 译者:小智 起源:learnvue
原文:https://learnvue.co/tutorals/...
交换
有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。