木灵鱼儿
阅读:1646
vue3 emits 自定义事件声明
在vue2的时候,我们的自定义事件是通过this.$emit
进行触发的,并没有统一的某一处属性进行定义,这其实会导致一个问题,当代码量上升一定程度后,后面来维护的人很难快速了解这个组件的自定义事件有哪些。
vue3版本提供了emits
配置,它可以定义当前组件触发的自定义事件有哪些,并且还支持参数校验,如果绑定的事件没有在emits
中显式声明,那么就会作为$attrs
属性挂载到根节点上,这个效果在fragment组件是无效的。
为此vue3放弃了.native
修饰符,一方面是因为emits的存在,可以更加明确的知道该组件支持什么自定义事件,另一方面是因为未声明的事件会默认绑定到根节点上,所以.native已经可有可无了,它的作用本身也是将事件绑定到组件的根节点上而已。
如果不想让未声明的事件会默认绑定到根节点上,可以给组件配置inheritAttrs: false
,关闭继承属性,这个功能在vue2中也存在,就不细说了。关键字:透传
普通用法
子组件
<template>
<button @click="onClick">aaa</button>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
emits: ["click"],
setup(props, { emit }) {
function onClick() {
emit("click", "test");
}
return {
onClick,
};
},
});
</script>
父组件
<template>
<div>
<test @click="onClick" />
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import test from "./components/test.vue";
export default defineComponent({
setup() {
function onClick(val: string) {
console.log(val);
}
return {
onClick,
};
},
components: {
test,
},
});
</script>
使用上出来emit是通过setup参数获取之外,其他并没有什么不同。
注意
如果子组件没有在emits
中声明click事件,那么当我们点击btn按钮的时候,click会触发两次,所以一定要注意,自定义事件一定要在emits
中声明。
这两次事件分别是由:
- emit触发
- 子组件根元素的click事件
而且我们不推荐emits中使用原生事件的名称,建议是自己编一个事件名,比如:myClick
当然,这个触发两次在vue2中并不会出现。
参数校验
从官方的类型定义上看
interface ComponentOptions {
emits?: ArrayEmitsOptions | ObjectEmitsOptions
}
type ArrayEmitsOptions = string[]
type ObjectEmitsOptions = { [key: string]: EmitValidator | null }
type EmitValidator = (...args: unknown[]) => boolean
使用数组,那么事件名全都是string类型,如果使用键值对,那么就可以声明一个校验函数,来进行参数校验,这个校验函数接的参就是我们emit
触发时传的参,当我们校验后返回一个布尔值,如果不return布尔值,那么默认是undefined
,转为布尔值就是false,所以这个需要注意。
目前这个参数校验并不会阻断我们的事件触发,当校验函数返回的是false的时候,也仅仅是在控制台输出一段警告,我们也可以自己手动打印一个警告,虽然官方推荐使用,但是好似没有太大的功能性提升,如果能阻断事件,我觉得会是一个很好的功能,但是目前没有这么做。
所以,目前数组形式的emits是常见的做法。
<template>
<button @click="onClick">aaa</button>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
emits: {
click: (val: string) => {
if (val !== "test") {
return false;
}
return true;
},
},
setup(props, { emit }) {
function onClick() {
emit("click", "test");
}
return {
onClick,
};
},
});
</script>
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
相关推荐
vue-router4 新增功能
动态路由这个其实在3版也有,不过3版原来使用的api是addRoutes,这个api顾名思义,就是可以传入一个路由数组来进行注册,后来被废弃,现在3版和4版统一采用addRouteapi。addRoute一次只能添加一个路由,但是有两种用法:添加一条新路由router.addRoute({ path: "/about", name: "About", component: () => import("../views/About.vue"), })给已存在的路由注册一个子路由,父路由必须有name属性route...
vue-router4 一些常见配置的改动
创建路由实例方式改变3版本的时候是通过new的方式创建路由实例,4版本是改用了createRouter的方式:import { createRouter } from 'vue-router' const router = createRouter({ // ... })路由模式配置改变3版本路由模式是由mode属性控制,值为字符串,现在通过import引入不同函数来创建不同的路由模式:"history"改为createWebHistory()"hash"改为createWebHashHistory()"abstract"...
vue3 filter过滤器
vue3直接移除了filter过滤器,官方推荐,如果要使用过滤器可以使用computed计算属性和method函数来代替。如果使用了全局过滤器,官方也提供了一个属性来进行迁移修复,但是也只推荐用于迁移。const app = createApp(App) //给当前app的全局属性上挂载一个过滤器对象 app.config.globalProperties.$filters = { currencyUSD(value) { return '$' + value } }使用的时候:<template> <h1>Bank Account Bala...
vue3 keyCode修饰符
vue2我们在监听按键事件的时候,是可以通过在事件后面加上按键码来实现监听某一个按键的。<input @keyup.13="submit" />甚至我们还可以使用按钮别名alias的方式调用<input @keyup.enter="submit" />还可以全局自定义别名,通过Vue.config.keyCodes属性。Vue.config.keyCodes = { f1: 112 }随着ECMAScript的标准推荐,官方已经不推荐使用keyCode键码了,这个功能在js的官方定义上是一个已弃用的状态,最新的标准是使用...
vue3 取消$on、$off、$once
在vue2的时候,我们可以通过$on、$off、$once、$emit来实现一个事件总线EventBus,但是vue3的时候,又换了一套逻辑思想。官方不鼓励使用EventBus在组件之间进行通信,虽然短期内确实是非常简单的解决方案,但是从长远来看,它总是很难维护的,所以官方更加推荐使用其他方式:父子组件之间可以通过Props和自定义事件来进行沟通,如果是兄弟组件,可以通过父级组件来沟通使用Provide / inject方式来跨层级沟通,比如与插槽的内容组件。Provide / inject也可以用于跨层级沟通,以避免props,emit事件层级过深的问题通过使用插槽的形式来避免层级沟通...
vue3 transition、watch、挂载api的变化
transition动画的变化就是vue3调整了一下动画类名,原来vue2是:.v-enter{ opacity: 0; } .v-leave{ opacity: 1; }这两个在vue3中改为:.v-enter-from{ opacity: 0; } .v-leave-to{ opacity: 1; }其相关属性也对应发生了变化:leave-class被重命名为 leave-from-class(可以写成 leaveFromClass在渲染函数或 JSX 中)enter-class被重命名为 enter-from-class(可以写成 enterFromClass在...
vue3 自定义指令
vue3将自定义指令的生命钩子函数全部改为与组件的生命钩子函数相同,原来vue2时,自定义指令的生命钩子是一套完全不同的,但是也正因为如此,它的钩子函数有点晦涩难懂,这次统一了我觉得是一件非常好的事情,让我们的记忆力压力减轻了很多,也方便了我们的理解。vue3写法:const myDirective = { // 在绑定元素的 attribute 前 // 或事件监听器应用前调用 created(el, binding, vnode, prevVnode) { // 下面会介绍各个参数的细节 }, // 在元素被插入到 DOM 前调用 beforeMoun...
vue3 异步组件
书接上文,我们的函数式组件在vue3里只能声明一个函数再通过h函数组合处理,然后导出使用,你会发现这个组件是一个函数类型。然后我再去看一下vue2时,我们的异步组件引入方式:const asyncModal = () => import('./Modal.vue')你会发现除了异步组件也是一个函数类型,这就尴尬了,怎么区分呢?vue3提供了一个defineAsyncComponent函数用于区分异步组件。import { defineAsyncComponent } from 'vue' const asyncModal = defineAsyncComponent(() =>...
vue3 函数式组件 functional
由于vue3对dom的渲染做了优化,优化了diff算法,在vue2时不管元素是否参与更新,都会被重新创建,vue3则针对不参与更新的元素,打上一个静态标记,此时这个元素只会创建一次,后续的渲染更新则不会重新创建。于是函数式组件在vue3中性能的提升可以忽略不计,于是functional组件的声明被移除,不在支持:template中不能再写上functional来表示函数式组件vue组件中的{ functional: true }选项也被删除但是,这也并不意味着无法创建函数式组件了,vue3也有提供创建的方式,但是需要引入h函数。创建一个js组件:_test.js_import { h }...