浅析Vue3相关基础知识:Vue3应用配置、重写的v-model、emits 选项、getCurrentInstance()获取实例、采用mitt实现全局通讯、vue-router的新特性
一、Vue3.x 应用配置
config:包含Vue应用程序全局配置的对象,在挂载应用之前配置相应的属性。
const app = Vue.createApp({});
app.config = {...};
1、devtools(类型:Boolean,默认:true)
概述:配置是否允许开启vue-devtools检查,一般在开发环境中是true,生产环境中为false。
用法:app.config.devtools = true;
2、errorHandler(类型:Function,参数err:错误内容,vm:对应的实例,info:Vue特定的错误信息,如某个生命周期中出现的错误)
概述:为组件在实例化或渲染过程中捕获到的错误进行处理的方法。
用法:app.config.errorHandler = (err, vm, info) => {};
概述:用于添加到应用程序中任何组件都能使用的全局属性,当与组件内部的属性冲突时,将优先使用组件内部的属性值。较Vue2.x:可代替Vue2中的Vue.prototype。
用法:
// Vue 2.x
Vue.prototype.name = '***';
// Vue 3.x
app.config.globalProperties.name = '***';
4、isCustomElement(类型:(tag: string) => boolean)
概述:用于来识别Vue之外的自定义元素(如,三方web组件api),如果组件或元素符合这个条件,则组件不会被实例化,Vue也不会对组件或元素发出警告信息。
用法:app.config.isCustomElement = tag => tag.startsWith('ion');
二、重写的 v-model
在Vue2.x中,我们使用的v-model只能双向绑定一个值,在某些需求面前显的力不从心。但是在Vue3.x中已经可以实现啦!
1、在Vue2.x中,v-model进行数据双向绑定(语法糖)的原理,且不能绑定多个值
<my-components v-model="msg"></my-components>
// 等价于
<my-components :value="msg" @input="value=$event"></my-components>
// myComponents组件中接收绑定数据和触发数据改变
props: { msg: String }; // 获取数据
this.$emit("input", 'newVal'); // 触发事件并传值
2、Vue3.x重写了v-model的实现方式,以适用用绑定多个 v-model —— 单个 / 多个 数据实现数据双向绑定
<my-components v-model:msg="msg" v-model:name="name"></my-components>
// 等价于
<my-components :msg="msg" @update:msg="value=$event" :name="name" @update:name="name=$event"></my-components>
// myComponents组件中接收绑定数据和触发数据改变
props: { msg: String, name: String }; // 获取数据
setup(props, { emit }) {
emit('update:msg', 'newValue'); // 触发事件并传值
emit('update:name', 'newValue'); // 触发事件并传值
};
三、emits 选项
2、用途:用于记录当前组件emit的事件,当为对象时,则可以验证传入的值是否有效。
3、如何使用
setup(prop, { emit }) {
const changeOne = val => {
emit('on-changeOne', val);
};
const changeTwo = val => {
emit('on-changeTwo', val);
};
}
// 用法一:数组用法
export default {
emits:['on-changeOne', 'on-changeTwo'],
setup() {...}
}
// 用法二:对象用法,当emits为对象时,可以验证事件中的参数是否有效
export default {
emits:{
click: null,
'on-changeOne': payload => {
if(...) {
return true; // 验证通过
}
console.warn('验证失败!')
return false; // 验证失败,控制台打印vue警告及“验证失败!”警告
},
'on-changeTwo': payload => {...}
},
setup() {...}
}
// 当验证函数中没有返回值return时,默认返回true
4、emits无论是数组或者对象用法最终都会将事件给传递出去,数组或对象的使用只是为了记录实例中的emit事件,或者是验证事件中的参数。
四、getCurrentInstance()获取实例
1、一个很重要的方法,获取当前组件的实例、上下文来操作router和vuex等。由vue提供,按需引入:import { getCurrentInstance} from 'vue';
import { getCurrentInstance } from 'vue';
// 获取当前组件实例
const instance = getCurrentInstance();
// 获取当前组件的上下文,下面两种方式都能获取到组件的上下文。
const { ctx } = getCurrentInstance(); // 方式一,这种方式只能在开发环境下使用,生产环境下的ctx将访问不到
const { proxy } = getCurrentInstance(); // 方式二,此方法在开发环境以及生产环境下都能放到组件上下文对象(推荐)
// ctx 中包含了组件中由ref和reactive创建的响应式数据对象,以及以下对象及方法;
proxy.$attrs
proxy.$data
proxy.$el
proxy.$emit
proxy.$forceUpdate
proxy.$nextTick
proxy.$options
proxy.$parent
proxy.$props
proxy.$refs
proxy.$root
proxy.$slots
proxy.$watch
五、mitt 实现全局通讯
1、由于Vue3.x中删除了 on 和 off ,因此不能借助于一个单独的Vue实例来实现全局事件的发布和订阅与取消订阅(也就是跨组件通讯)。
2、mitt 是一个三方库,npm安装:npm install -D mitt,我们以同样使用插件的方式将mitt集成到Vue中。
- all(Map对象):包含了所有订阅的事件名称,及对应的处理方法数组。
- emit(方法):触发事件,参数为(事件名(方法名),携带的参数),当- 前携带的参数只能为一个,不能为多个。
- on(方法):创建事件订阅,参数为(事件名,处理方法)。
- off(方法):取消事件订阅,参数为(事件名,处理方法)。
import _ from 'lodash';
import mitt from 'mitt';
export default {
install(Vue, options) {
const _emitter = mitt();
// 全局发布(在Vue全局方法中自定义$pub发布方法)
// 这里做了$pub方法能够携带多个参数的处理,方便我们再业务中触发事件时带多个参数
Vue.config.globalProperties.$pub = (...args) => {
_emitter.emit(_.head(args), args.slice(1));
};
// 全局订阅(在Vue全局方法中自定义$sub订阅方法)
Vue.config.globalProperties.$sub = function (event, callback) {
Reflect.apply(_emitter.on, _emitter, _.toArray(arguments));
};
// 取消订阅
Vue.config.globalProperties.$unsub = function (event, callback) {
Reflect.apply(_emitter.off, _emitter, _.toArray(arguments));
};
}
};
5、组件实例中使用:
// 全局事件发布
<template>
<div class="child">
<button @click="pubHandler">发起事件</button>
</div>
</template>
<script>
import { onMounted, getCurrentInstance } from 'vue';
export default {
setup(props, context) {
const { proxy } = getCurrentInstance();
const pubHandler = () => {
proxy.$pub('foo', 1, 2, 3);
};
return {
pubHandler
};
}
};
</script>
// 全局事件订阅/取消订阅
<template>
<div class="child">
<button @click="unsubHandler">注销事件</button>
</div>
</template>
<script>
import { getCurrentInstance, onMounted } from 'vue';
export default {
setup(props, context) {
const { proxy } = getCurrentInstance();
const watchHandler = ([a, b, c] = args) => {
console.log('组件件监听触发!');
};
onMounted(() => {
proxy.$sub('foo', watchHandler);
});
const unsubHandler = () => {
proxy.$unsub('foo', watchHandler);
};
return {
unsubHandler
};
}
};
</script>
六、vue-router 的新特性
2、创建路由
// router.js
import { createRouter, createWebHashHistory, createWebHistory } from "vue-router";
const routes = [...];
const router = createRouter({
// 区别于vue2的mode,vue3中将使用history属性来决定采用哪种路由模式
history: createWebHashHistory(), // 默认为Hash模式,可设置createWebHistory模式
// 区别于vue2的base,vue3中的基础路由路径将作为createWebHashHistory或者createWebHistory的唯一参数配置到路由中。
routes
});
export default router;
// main.js
import router from './routes';
const app = createApp(App);
// 注册路由
app.use(router);
3、在组件中使用路由,查看路由。
// vue-router库当中暴露了 useRouter 和 useRoute 两个方法供组件使用,还暴露有其他方法。
import { useRouter, useRoute } from 'vue-router';
import { onMounted, getCurrentInstance } from 'vue';
export default {
setup() {
const { proxy } = getCurrentInstance();
const router = useRouter();
const route = useRoute();
onMounted(() => {
console.log(proxy.$router === router) // true
console.log(route) // {path, params, query...}
});
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律