淺析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