浅析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) => {};

3、globalProperties(类型:any)

  概述:用于添加到应用程序中任何组件都能使用的全局属性,当与组件内部的属性冲突时,将优先使用组件内部的属性值。较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 选项

1、记录当前组件的通过emit的事件列表,类型:Array|Object,其作用:Vue3.0中使用emit发起事件时会要求当前组件记录emit事件(没有则控制台会抛出警告)。

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中。

3、mitt 对象:
  • all(Map对象):包含了所有订阅的事件名称,及对应的处理方法数组。
  • emit(方法):触发事件,参数为(事件名(方法名),携带的参数),当- 前携带的参数只能为一个,不能为多个。
  • on(方法):创建事件订阅,参数为(事件名,处理方法)。
  • off(方法):取消事件订阅,参数为(事件名,处理方法)。
4、全局事件总成搭建:
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 的新特性

1、在vue3中,vue-router将使用新的方法来创建路由,其中重要的是:createRouter, createWebHashHistory, createWebHistory这三个方法。

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...}
 }); } };

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM