vue.js 组件事件

225 阅读1分钟

**staging-cn.vuejs.org/guide/compo…

触发与监听事件

在组件的模板表达式中,可以直接使用 $emit 方法触发自定义事件,父组件可以通过 v-on (缩写为 @) 来监听事件.

//子组件,传参
<button @click="$emit('someEvent',1)">click me</button>
//父组件,接收参数
<MyComponent @some-event="callback" />

function callback(n){
    console.log(n)
}

声明触发的事件

组件要触发的事件可以显式地通过defineEmits() 宏来声明: 在<template>中使用 <template>中使用的 $emit 方法不能在组件的 <script setup> 部分中使用,但 defineEmits() 会返回一个相同作用的函数供我们使用.

<script setup>:
    <script setup>
        const emit = defineEmits(['inFocus', 'submit'])

        function buttonClick() {
            emit('submit')
        }
    </script>
    

该 defineEmits() 宏不能在子函数中使用,他必须直接放置在 <script setup> 中。

setup函数:

显式地使用了 setup 函数而不是 <script setup>,则事件需要通过 emits 选项来定义,emit 函数也被暴露在 setup() 的上下文对象上:

export default {
  emits: ['inFocus', 'submit'],
  setup(props, ctx) {//或者可以直接在参数中将emit解构出来
    function buttonClick() {        
        ctx.emit('submit')
    }
  }
}

事件校验

和对 prop 添加类型校验的方式类似,所有触发的事件也可以使用对象形式来描述。

要为事件添加校验,那么事件可以被赋值为一个函数,接受的参数就是抛出事件时传入 emit 的内容,返回一个布尔值来表明事件是否合法。

<script setup>
const emit = defineEmits({
  // 没有校验
  click: null,

  // 校验 submit 事件
  submit: ({ email, password }) => {
    if (email && password) {
      return true
    } else {
      console.warn('Invalid submit event payload!')
      return false
    }
  }
})

function submitForm(email, password) {
  emit('submit', { email, password })
}
</script>

配合 v-model 使用

自定义事件可以用来创建对应 v-model 的自定义输入。

<input v-model="searchText" />

//等同于

<input
  :value="searchText"
  @input="searchText = $event.target.value"
/>

当使用在一个组件上时。

<CustomInput
  :modelValue="searchText"
  @update:modelValue="newValue => searchText = newValue"
/>

为了使组件能像这样工作,内部的 <input> 组件必须:

  • 绑定 value attribute 到 modelValue prop
  • 输入新的值时在 input 元素上触发 update:modelValue 事件
<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>

<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

另一种在组件内实现 v-model 的方式是使用一个可写的 computed property,给出 getter 和 setter。get 方法需返回 modelValue property 而 set 方法需触发相应的事件:

<script setup>
import { computed } from 'vue'

const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const value = computed({
  get() {
    return props.modelValue
  },
  set(value) {
    emit('update:modelValue', value)
  }
})
</script>

<template>
  <input v-model="value" />
</template>

v-model 的参数

默认情况下,v-model 在组件上都是使用 modelValue 作为 prop,以 update:modelValue 作为对应的事件。我们可以通过给 v-model 指定一个参数来更改这些名字:

<MyComponent v-model:title="bookTitle" />


<script setup>
defineProps(['title'])
defineEmits(['update:title'])
</script>

<template>
  <input
    type="text"
    :value="title"
    @input="$emit('update:title', $event.target.value)"
  />
</template>

处理 v-model 修饰符