Vue3 中的事件

在 Vue3 中,我们可以通过 v-on 或简写的 @ 来绑定事件。在事件处理程序中,可以使用 $event 访问原生 DOM 事件。

事件绑定

我们可以使用 v-on 或简写的 @ 来绑定事件,例如:

<template>
  <button @click="handleClick">Click me!</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      console.log('button clicked');
    },
  },
};
</script>

在上面的例子中,我们为 <button> 元素绑定了一个 click 事件,并在 handleClick 方法中处理了该事件。

我们也可以使用对象语法绑定多个事件和处理函数:

<template>
  <button @click="handleClick" @mouseover="handleMouseOver">Hover me!</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      console.log('button clicked');
    },
    handleMouseOver() {
      console.log('mouse over button');
    },
  },
};
</script>

在上面的例子中,我们为 <button> 元素绑定了 clickmouseover 两个事件,并分别在 handleClickhandleMouseOver 方法中处理这两个事件。

此外还可以定义变量形式动态绑定事件

image-20230331201658068

事件修饰符

事件修饰符是用来改变事件处理行为的特殊标记。Vue 3.x 支持以下事件修饰符:
(改变的是默认行为~,不是禁用事件,在标签和事件嵌套的时候一定要记得阻止冒泡发生)

  • .stop - 阻止事件继续传播。
  • .prevent - 阻止默认行为。
  • .capture - 将事件处理添加到捕获阶段,而不是冒泡阶段。
  • .self - 只有在事件目标是当前元素本身时触发事件处理函数。
  • .once - 事件将只被处理一次。
  • .passive - 指示事件监听器永远不会调用 event.preventDefault()。这可以提高滚动性能。

例如,你可以使用 .stop 修饰符来阻止事件继续传播,如下所示:

<div @click.stop="doThis"></div>

使用 .prevent 修饰符阻止默认行为:

<form @submit.prevent="onSubmit"></form>

使用 .capture 修饰符将事件处理添加到捕获阶段,如下所示:

<div @click.capture="doThis"></div>

使用 .self 修饰符只有在事件目标是当前元素本身时才会触发事件处理函数:

<div @click.self="doThis"></div>

使用 .once 修饰符让事件只被处理一次:

<div @click.once="doThis"></div>

使用 .passive 修饰符指示事件监听器永远不会调用 event.preventDefault()

<div @touchstart.passive="doThis"></div>

事件对象

在 Vue 中,处理事件时可以使用 $event 访问原始 DOM 事件对象。例如,可以在模板中这样使用:

<button @click="handleClick($event)">Click me</button>

在上面的代码中,@click 是 Vue 的事件绑定语法,handleClick 是定义在 Vue 实例中的事件处理函数,$event 是传递给事件处理函数的原始 DOM 事件对象。

在事件处理函数中,可以通过参数来接收 $event 对象。例如:

methods: {
  handleClick(event) {
    console.log(event.target) // 输出点击的元素
  }
}

在上面的代码中,handleClick 方法接收一个参数 event,它就是传递给事件处理函数的原始 DOM 事件对象。可以通过访问 event 的属性和方法来获取事件的详细信息,例如 target 属性可以获取触发事件的原始 DOM 元素。

总之,使用 $event 来访问原始 DOM 事件对象是 Vue 中非常常用的技巧,可以帮助开发者更方便地处理事件和获取事件信息。

自定义事件

除了原生事件外,Vue 3.x 还支持自定义事件。自定义事件通常用于跨组件通信。你可以使用 vm.$emit 发出自定义事件,如下所示:

// 在组件中发出事件
this.$emit('my-event', data)

// 在组件外监听事件
vm.$on('my-event', handler)

在上面的代码中,my-event 是自定义事件名称,data 是将传递给事件处理程序的数据。

举个例子吧:我们需要在子组件中修改父组件的属性值(后面我们可以使用pina实现组件间的数据共享)

Vue2组件嵌套template示例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://unpkg.com/vue@next"></script>
    <title>Components</title>
</head>

<body>
    <div id="applictation">
        <switcher bcolor="red" radius="20px"  @myclick="switchState1"></switcher>第一个组件的开关状态:{{state1}}
        <!-- <switcher bcolor="blue" radius="5px"></switcher>第二个组件的开关状态:{{state2}} -->
    </div>
    <script>
        const App = {
            data() {
                return {
                    state1: '关'
                }
            },
            methods: {
                parentclick(title) {
                    alert(title + "被点击了")
                },
                switchState1(state){
                    this.state1=state?'开' : '关'
                }
            }
        }
        // 自定义组件
        const switchComponet = {
            data() {
                return {
                    isOpen: false,
                    left: '0px'
                }
            },
            methods: {
                click() {
                    this.isOpen = !this.isOpen;
                    this.left = this.isOpen ? '30px' : '0px';
                    // this.state1 = this.isOpen ? '开' : '关'; // 同步修改state1的值
                    this.$emit('myclick', this.isOpen);
                }
            },
            props: ['bcolor', 'radius'],
            template: `<div :style="{width:'60px',height:'30px', backgroundColor: isOpen ? bcolor : 'gray', borderRadius: radius, position: 'relative' }" @click="click">
    <div :style="{width:'30px',height:'30px', backgroundColor: 'pink', borderRadius: radius, position: 'absolute', left: left}"></div>
  </div>`
        }
        app = Vue.createApp(App);
        // 注册组件
        app.component("switcher", switchComponet);
        app.mount("#applictation");
    </script>
</body>

</html>

Vue3组合式,单组件以及子组件的示例

父组件的模板代码:

<template>
  <div>
    <Switcher :bcolor="red" :radius="20" @myclick="switchState1" />
    第一个组件的开关状态:{{state1}}
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue';
import Switcher from './Switcher.vue'; // 引入Switcher组件

export default defineComponent({
  components: {
    Switcher,
  },

  setup() {
    const state1 = ref('关');

    const switchState1 = (state) => {
      state1.value = state ? '开' : '关';
    };

    return {
      state1,
      switchState1,
    };
  },
});
</script>

Switcher组件的模板代码:

<template>
  <div :style="{width:'60px',height:'30px', backgroundColor: isOpen ? bcolor : 'gray', borderRadius: radius + 'px', position: 'relative' }" @click="switchState">
    <div :style="{width:'30px',height:'30px', backgroundColor: 'pink', borderRadius: radius + 'px', position: 'absolute', left: left}"></div>
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue';

export default defineComponent({
  props: {
    bcolor: {
      type: String,
      default: 'gray',
    },
    radius: {
      type: Number,
      default: 0,
    },
  },

  setup(props, { emit }) {
    const isOpen = ref(false);
    const left = ref('0px');

    const switchState = () => {
      isOpen.value = !isOpen.value;
      left.value = isOpen.value ? '30px' : '0px';
      emit('myclick', isOpen.value);
    };

    return {
      isOpen,
      left,
      switchState,
    };
  },
});
</script>

在上面的代码中,我们将Switcher组件定义在了单独的文件Switcher.vue中,并在父组件中通过import语句引入了该组件。这样可以使组件代码更加清晰、易读、易维护。

在父组件的模板代码中,我们只需要像之前一样使用<Switcher>标签即可,不需要再写template标签了。同时,我们也不需要在父组件的setup()函数中定义Switcher组件的相关逻辑了,因为这些逻辑已经在Switcher.vue组件中定义了。

总体来说,将组件的模板代码和组件定义分离可以使代码更加清晰、易读、易维护,尤其是在开发大型应用时,更加方便管理和组织代码。

总结

在 Vue 3.x 中,事件处理非常简单。你可以通过 v-on 指令添加事件处理程序,并使用对象语法绑定多个事件和处理程序。Vue 3.x 还支持事件修饰符,用于更改事件处理行为。另外,你还可以使用 $event 访问原始 DOM