前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Vue 3 自定义事件

Vue 3 自定义事件

作者头像
公众号---人生代码
发布2020-11-03 16:54:58
发布2020-11-03 16:54:58
1.4K00
代码可运行
举报
文章被收录于专栏:人生代码人生代码
运行总次数:0
代码可运行

自定义事件

除了系统自带的原生 DOM 自带的事件之外,有时候我们需要用到这些自带的事件之外,我们就必须要自定义事件了。

事件名

不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称。举个例子,如果触发一个 camelCase 名字的事件,我们还是接着昨天的项目继续往下写,在 TestCom.vue 使用 button 按钮点击事件分发一个 click-event 事件,不同于组件和 prop,事件名不会被用作一个 JavaScript 变量名或 property 名,所以就没有理由使用 camelCase 或 PascalCase 了。并且 v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 @myEvent 将会变成 @myevent——导致 myEvent 不可能被监听到。

代码语言:javascript
代码运行次数:0
复制
<template>
  <div class="test-com-wrap">
    {{ title }}
    <button @click="click">按钮</button>
  </div>
</template>
<script>
export default {
  name: "TestCom",
  props: {
    title: {
      type: String,
      default: "",
    },
  },
  created() {
    console.log(this.$attrs)
  },
  methods: {
    click(e) {
      this.$emit('click-event', e)
    }
  }
};
</script>

然后我们在 TemplateM.vue 来接收这个事件:

代码语言:javascript
代码运行次数:0
复制
<template>
  <div class="template-m-wrap">
    <test-com
      title="这个是组件"
      data-status="active"
      @click-event="clickEvent"
    ></test-com>
  </div>
</template>
<script>
import TestCom from "./TestCom";
export default {
  name: "TemplateM",
  components: {
    TestCom,
  },
  data() {
    return {};
  },
  methods: {
    clickEvent(e) {
      console.log("e===>", e.target)
    }
  },
};
</script>

查看浏览效果:

定义自定义事件

继续上面的代码,可以通过 emits 选项在组件上定义已经发出的事件:

代码语言:javascript
代码运行次数:0
复制
<template>
  <div class="test-com-wrap">
    {{ title }}
    <button @click="click">按钮</button>
  </div>
</template>
<script>
export default {
  name: "TestCom",
  props: {
    title: {
      type: String,
      default: "",
    },
  },
  emits: ['click-event'],
  created() {
    console.log(this.$attrs)
  },
  methods: {
    click(e) {
      this.$emit('click-event', e)
    }
  }
};
</script>

验证抛出的事件

与 prop 类型验证类似,如果使用对象语法而不是数组语法定义发出的事件,则可以验证它。

要添加验证,将为事件分配一个函数,该函数接收传递给 $emit 调用的参数,并返回一个布尔值以指示事件是否有效,在 main.js 写下如下代码:

代码语言:javascript
代码运行次数:0
复制
import { createApp } from 'vue/dist/vue.esm-bundler.js'
import App from './App.vue'
import router from './router'
import store from './store'
let app = createApp(App)
app.use(store).use(router).mount('#app')
app.component('custom-form', {
  template: `<div>
    <input v-model="email" type="text" placeholder="输入邮箱"/>
    <input v-model="password" type="password" placeholder="输入密码"/>
    <button @click="submitForm({email, password})">提交</button>
  </div>`,
  data() {
    return {
      email: '',
      password: ''
    }
  },
  emits: {
    // 没有验证
    click: null,

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

TemplateM.vue 写下代码:

代码语言:javascript
代码运行次数:0
复制
<template>
  <div class="template-m-wrap">
    <custom-form @submit="submit"></custom-form>
  </div>
</template>
<script>
export default {
  name: "TemplateM",
  components: {
    
  },
  data() {
    return {};
  },
  methods: {
    submit(options) {
      console.log(options)
    }
  },
};
</script>

我们查看效果如下:

v-model 参数

在本例中,子组件将需要一个 foo prop 并发出 update:foo 要同步的事件,还是在 main.js

代码语言:javascript
代码运行次数:0
复制
import { createApp } from 'vue/dist/vue.esm-bundler.js'
import App from './App.vue'
import router from './router'
import store from './store'
let app = createApp(App)
app.use(store).use(router).mount('#app')
app.component('my-component', {
  props: {
    foo: String
  },
  template: `
    <input 
      type="text"
      :value="foo"
      @input="$emit('update:foo', $event.target.value)">
  `
})

默认情况下,组件上的 v-model 使用 modelValue 作为 prop 和 update:modelValue 作为事件。我们可以通过向 v-model 传递参数来修改这些名称:

代码语言:javascript
代码运行次数:0
复制
<template>
  <div class="template-m-wrap">
    <my-component v-model:foo="bar"></my-component>
  </div>
</template>
<script>
export default {
  name: "TemplateM",
  components: {
    
  },
  data() {
    return {
      bar: 'dsdsdd'
    };
  },
  methods: {
    submit(options) {
      console.log(options)
    }
  },
};
</script>

查看效果如下:

多个 v-model 绑定

通过利用以特定 prop 和事件为目标的能力,正如我们之前在 v-model 参数中所学的那样,我们现在可以在单个组件实例上创建多个 v-model 绑定。

每个 v-model 将同步到不同的 prop,而不需要在组件中添加额外的选项:

代码语言:javascript
代码运行次数:0
复制
import { createApp } from 'vue/dist/vue.esm-bundler.js'
import App from './App.vue'
import router from './router'
import store from './store'
let app = createApp(App)
app.use(store).use(router).mount('#app')
app.component('user-name', {
  props: {
    firstName: String,
    lastName: String
  },
  template: `
    <input 
      type="text"
      :value="firstName"
      @input="$emit('update:firstName', $event.target.value)">

    <input
      type="text"
      :value="lastName"
      @input="$emit('update:lastName', $event.target.value)">
  `
})

TemplateM.vue :

代码语言:javascript
代码运行次数:0
复制
<template>
  <div class="template-m-wrap">
    <user-name
      v-model:first-name="firstName"
      v-model:last-name="lastName"
    ></user-name>
  </div>
</template>
<script>
export default {
  name: "TemplateM",
  components: {
    
  },
  data() {
    return {
      firstName: 'dsdsdd',
      lastName: 'Ken'
    };
  },
  methods: {
    submit(options) {
      console.log(options)
    }
  },
};
</script>

效果如下:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CryptoCode 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 自定义事件
    • 事件名
    • 定义自定义事件
    • 验证抛出的事件
    • v-model 参数
    • 多个 v-model 绑定
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档