日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

來自公眾號: 前端自習課

鏈接:https://juejin.cn/post/7084536432731095048/

最近入門 Vue3 并完成 3 個項目,遇到問題蠻多的,今天就花點時間整理一下,和大家分享 15 個比較常見的問題,基本都貼出對應文檔地址,還請多看文檔~ 已經完成的 3 個項目基本都是使用 Vue3 (setup- 模式)全家桶開發,因此主要分幾個方面總結:

  • Vue3

  • Vite

  • VueRouter

  • Pinia

  • ElementPlus

一、Vue3 1. Vue2.x 和 Vue3.x 生命周期方法的變化

文檔地址:https://v3.cn.vuejs.org/guide/composition-api-lifecycle-hooks.html

Vue2.x 和 Vue3.x 生命周期方法的變化蠻大的,先看看:

2.x 生命周期 3.x 生命周期 執行時間說明
beforeCreate setup 組件創建前執行
created setup 組件創建后執行
beforeMount onBeforeMount 組件掛載到節點上之前執行
mounted onMounted 組件掛載完成后執行
beforeUpdate onBeforeUpdate 組件更新之前執行
updated onUpdated 組件更新完成之后執行
beforeDestroy onBeforeUnmount 組件卸載之前執行
destroyed onUnmounted 組件卸載完成后執行
errorCaptured Captured 當捕獲一個來自子孫組件的異常時激活鉤子函數

目前 Vue3.x 依然支持 Vue2.x 的生命周期,但不建議混搭使用,前期可以先使用 2.x 的生命周期,后面盡量使用 3.x 的生命周期開發。

由于我使用都是 -srtup模式,所以都是直接使用 Vue3.x 的生命周期函數:

// A.vue

< setup lang="ts">

import { ref, onMounted } from "vue";

let count = ref<number>(0);

onMounted( => {

count.value = 1;

})

</>

每個鉤子的執行時機點,也可以看看文檔:https://v3.cn.vuejs.org/guide/instance.html#生命周期圖示

2. -setup 模式中父組件獲取子組件的數據

文檔地址:https://v3.cn.vuejs.org/api/sfc--setup.html#defineexpose

這里主要介紹父組件如何去獲取子組件內部定義的變量,關于父子組件通信,可以看文檔介紹比較詳細:https://v3.cn.vuejs.org/guide/component-basics.html

我們可以使用 全局編譯器宏的 defineExpose宏,將子組件中需要暴露給父組件獲取的參數,通過 {key: vlaue}方式作為參數即可,父組件通過模版 ref 方式獲取子組件實例,就能獲取到對應值:

// 子組件

< setup>

let name = ref("pingan8787")

defineExpose({ name }); // 顯式暴露的數據,父組件才可以獲取

</>

// 父組件

<Chlid ref="child"></Chlid>

< setup>

let child = ref(null)

child.value.name //獲取子組件中 name 的值為 pingan8787

</>

注意

  • 全局編譯器宏只能在 -setup 模式下使用;

  • -setup 模式下,使用宏時無需 import可以直接使用;

  • -setup 模式一共提供了 4 個宏,包括:defineProps、defineEmits、defineExpose、withDefaults。

3. 為 props 提供默認值

definedProps 文檔:https://v3.cn.vuejs.org/api/sfc--setup.html#defineprops-%E5%92%8C-defineemitswithDefaults 文檔:https://v3.cn.vuejs.org/api/sfc--setup.html#%E4%BB%85%E9%99%90-type-%E7%9A%84%E5%8A%9F%E8%83%BD

前面介紹 -setup 模式提供的 4 個 全局編譯器宏,還沒有詳細介紹,這一節介紹 defineProps和 withDefaults。使用 defineProps宏可以用來定義組件的入參,使用如下:

< setup lang="ts">

let props = defineProps<{

schema: AttrsValueObject;

modelValue: any;

}>;

</>

這里只定義props屬性中的 schema和 modelValue兩個屬性的類型, defineProps的這種聲明的不足之處在于,它沒有提供設置 props 默認值的方式。

其實我們可以通過 withDefaults 這個宏來實現:

< setup lang="ts">

let props = withDefaults(

defineProps<{

schema: AttrsValueObject;

modelValue: any;

}>,

{

schema: [],

modelValue: ''

}

);

</>

withDefaults 輔助函數提供了對默認值的類型檢查,并確保返回的 props 的類型刪除了已聲明默認值的屬性的可選標志。

4. 配置全局自定義參數

文檔地址:https://v3.cn.vuejs.org/guide/migration/global-api.html#vue-prototype-%E6%9B%BF%E6%8D%A2%E4%B8%BA-config-globalproperties

在 Vue2.x 中我們可以通過 Vue.prototype添加全局屬性 property。但是在 Vue3.x 中需要將 Vue.prototype替換為 config.globalProperties配置:

// Vue2.x

Vue.prototype.$api = axIOS;

Vue.prototype.$eventBus = eventBus;

// Vue3.x

constApp = createApp({})

app.config.globalProperties.$api = axios;

app.config.globalProperties.$eventBus = eventBus;

使用時需要先通過 vue 提供的 getCurrentInstance方法獲取實例對象:

// A.vue

< setup lang="ts">

import { ref, onMounted, getCurrentInstance } from "vue";

onMounted( => {

const instance = <any>getCurrentInstance;

const { $api, $eventBus } = instance.appContext.config.globalProperties;

// do something

})

</>

其中 instance內容輸出如下:

5. v-model 變化

文檔地址:https://v3.cn.vuejs.org/guide/migration/v-model.html

當我們在使用 v-model指令的時候,實際上 v-bind和 v-on組合的簡寫,Vue2.x 和 Vue3.x 又存在差異。

  • Vue2.x

<ChildComponent v-model="pageTitle" />

<!-- 是以下的簡寫: -->

<ChildComponent :value="pageTitle" @input="pageTitle = $event" />

在子組件中,如果要對某一個屬性進行雙向數據綁定,只要通過 this.$emit('update:myPropName', newValue)就能更新其 v-model綁定的值。

  • Vue3.x

<ChildComponent v-model="pageTitle" />

<!-- 是以下的簡寫: -->

<ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle = $event"/>

-setup模式下就不能使用 this.$emit去派發更新事件,畢竟沒有 this,這時候需要使用前面有介紹到的 defineProps、defineEmits 兩個宏來實現:

// 子組件 child.vue

// 文檔:https://v3.cn.vuejs.org/api/sfc--setup.html#defineprops-%E5%92%8C-defineemits

< setup lang="ts">

import { ref, onMounted, watch } from "vue";

const emit = defineEmits(['update:modelValue']); // 定義需要派發的事件名稱

let curValue = ref('');

let props = withDefaults(defineProps<{

modelValue: string;

}>, {

modelValue: '',

})

onMounted( => {

// 先將 v-model 傳入的 modelValue 保存

curValue.value = props.modelValue;

})

watch(curValue, (newVal, oldVal) => {

// 當 curValue 變化,則通過 emit 派發更新

emit('update:modelValue', newVal)

})

</>

<template>

<div></div>

</template>

<style lang="scss" scoped></style>

父組件使用的時候就很簡單:

// 父組件 father.vue

< setup lang="ts">

import { ref, onMounted, watch } from "vue";

let curValue = ref('');

watch(curValue, (newVal, oldVal) => {

console.log('[curValue 發生變化]', newVal)

})

</>

<template>

<Child v-model='curValue'></Child>

</template>

<style lang="scss" scoped></style>

6. 開發環境報錯不好排查

文檔地址:https://v3.cn.vuejs.org/api/application-config.html#errorhandler

Vue3.x 對于一些開發過程中的異常,做了更友好的提示警告,比如下面這個提示:

這樣能夠更清楚的告知異常的出處,可以看出大概是 <ElInput 0=......這邊的問題,但還不夠清楚。這時候就可以添加 Vue3.x 提供的 全局異常處理器,更清晰的 輸出錯誤內容和調用棧信息,代碼如下

// main.ts

app.config.errorHandler = ( err, vm, info) => {

console.log( '[全局異常]', err, vm, info)

}

這時候就能看到輸出內容如下:

一下子就清楚很多。當然,該配置項也可以用來集成錯誤追蹤服務 Sentry 和 Bugsnag。推薦閱讀:Vue3 如何實現全局異常處理?

7. 觀察 ref 的數據不直觀,不方便

當我們在控制臺輸出 ref聲明的變量時。

constcount = ref<numer>( 0);

console.log( '[測試 ref]', count)

會看到控制臺輸出了一個 RefImpl對象:

看起來很不直觀。我們都知道,要獲取和修改 ref聲明的變量的值,需要通過 .value來獲取,所以你也可以:

console.log( '[測試 ref]', count.value);

這里還有另一種方式,就是在控制臺的設置面板中開啟 「 Enable custom formatters」選項。

image.png

image.png

這時候你會發現,控制臺輸出的 ref的格式發生變化了:

更加清晰直觀了。

這個方法是我在《Vue.js 設計與實現》中發現的,但在文檔也沒有找到相關介紹,如果有朋友發現了,歡迎告知~

二、Vite 1. Vite 動態導入的使用問題

文檔地址:https://cn.vitejs.dev/guide/features.html#glob-import

使用 webpack 的同學應該都知道,在 webpack 中可以通過 require.context動態導入文件:

// https://webpack.js.org/guides/dependency-management/

require.context( './test', false, /.test.js$/);

在 Vite 中,我們可以使用這兩個方法來動態導入文件:

  • import.meta.glob

該方法匹配到的文件默認是 懶加載,通過 動態導入實現,構建時會 分離獨立的 chunk,是 異步導入,返回的是 Promise,需要做異步操作,使用方式如下:

constComponents = import.meta.glob( '../components/**/*.vue');

// 轉譯后:

constComponents = {

'./components/a.vue': => import( './components/a.vue'),

'./components/b.vue': => import( './components/b.vue')

}

  • import.meta.globEager

該方法是 直接導入所有模塊,并且是 同步導入,返回結果直接通過 for...in循環就可以操作,使用方式如下:

constComponents = import.meta.globEager( '../components/**/*.vue');

// 轉譯后:

import* as__glob__0_0 from'./components/a.vue'

import* as__glob__0_1 from'./components/b.vue'

constmodules = {

'./components/a.vue': __glob__0_0,

'./components/b.vue': __glob__0_1

}

如果僅僅使用異步導入 Vue3 組件,也可以直接使用 Vue3 defineAsyncComponent API 來加載:

// https://v3.cn.vuejs.org/api/global-api.html#defineasynccomponent

import{ defineAsyncComponent } from'vue'

constAsyncComp = defineAsyncComponent( =>

import( './components/AsyncComponent.vue')

)

app.component( 'async-component', AsyncComp)

2. Vite 配置 alias 類型別名

文檔地址:https://cn.vitejs.dev/config/#resolve-alias

當項目比較復雜的時候,經常需要配置 alias 路徑別名來簡化一些代碼:

importHome from'@/views/Home.vue'

在 Vite 中配置也很簡單,只需要在 vite.config.ts的 resolve.alias中配置即可:

// vite.config.ts

exportdefaultdefineConfig({

base: './',

resolve: {

alias: {

"@": path.join(__dirname, "./src")

},

}

// 省略其他配置

})

如果使用的是 Type 時,編輯器會提示路徑不存在的警告??,這時候可以在 tsconfig.json中添加 compilerOptions.paths的配置:

{

"compilerOptions": {

"paths": {

"@/*": [ "./src/*"]

}

}

}

3. Vite 配置全局 scss

文檔地址:https://cn.vitejs.dev/config/#css-preprocessoroptions

當我們需要使用 scss 配置的主題變量(如 $primary)、mixin方法(如 @mixin lines)等時,如:

< setup lang="ts">

</>

<template>

<div class="container"></div>

</template>

<style scoped lang="scss">

.container{

color: $primary;

@include lines;

}

</style>

我們可以將 scss 主題配置文件,配置在 vite.config.ts的 css.preprocessorOptions.scss.additionalData中:

// vite.config.ts

exportdefaultdefineConfig({

base: './',

css: {

preprocessorOptions: {

// 添加公共樣式

scss: {

additionalData: '@import "./src/style/style.scss";'

}

}

},

plugins: [vue]

// 省略其他配置

})

如果不想使用 scss 配置文件,也可以直接寫成 scss 代碼:

exportdefaultdefineConfig({

css: {

preprocessorOptions: {

scss: {

additionalData: '$primary: #993300'

}

}

}

})

三、VueRouter 1. -setup 模式下獲取路由參數

文檔地址:https://router.vuejs.org/zh/guide/advanced/composition-api.html

由于在 -setup模式下,沒有 this可以使用,就不能直接通過 this.$router或 this.$route來獲取路由參數和跳轉路由。當我們需要獲取路由參數時,就可以使用 vue-router提供的 useRoute方法來獲取,使用如下:

// A.vue

< setup lang="ts">

import { ref, onMounted } from 'vue';

import router from "@/router";

import { useRoute } from 'vue-router'

let detailId = ref<string>('');

onMounted( => {

const route = useRoute;

detailId.value = route.params.id as string; // 獲取參數

})

</>

如果要做路由跳轉,就可以使用 useRouter方法的返回值去跳轉:

constrouter = useRouter;

router.push({

name: 'search',

query: { /**/},

})

四、Pinia 1. store 解構的變量修改后沒有更新

文檔地址:https://pinia.vuejs.org/core-concepts/#using-the-store

當我們解構出 store 的變量后,再修改 store 上該變量的值,視圖沒有更新:

// A.vue

< setup lang="ts">

import componentStore from "@/store/component";

const componentStoreObj = componentStore;

let { name } = componentStoreObj;

const changeName = => {

componentStoreObj.name = 'hello pingan8787';

}

</>

<template>

<span @click="changeName">{{name}}</span>

</template>

這時候點擊按鈕觸發 changeName事件后,視圖上的 name并沒有變化。這是因為 store 是個 reactive 對象,當進行解構后,會破壞它的響應性。所以我們不能直接進行解構。這種情況就可以使用 Pinia 提供 storeToRefs工具方法,使用起來也很簡單,只需要將需要解構的對象通過 storeToRefs方法包裹,其他邏輯不變:

// A.vue

< setup lang="ts">

import componentStore from "@/store/component";

import { storeToRefs } from 'pinia';

const componentStoreObj = componentStore;

let { name } = storeToRefs(componentStoreObj); // 使用 storeToRefs 包裹

const changeName = => {

componentStoreObj.name = 'hello pingan8787';

}

</>

<template>

<span @click="changeName">{{name}}</span>

</template>

這樣再修改其值,變更馬上更新視圖了。

2. Pinia 修改數據狀態的方式

按照官網給的方案,目前有三種方式修改:

  1. 通過 store.屬性名賦值修改單筆數據的狀態;

這個方法就是前面一節使用的:

constchangeName = => {

componentStoreObj.name = 'hello pingan8787';

}

  1. 通過 $patch方法修改多筆數據的狀態;

文檔地址:https://pinia.vuejs.org/api/interfaces/pinia._StoreWithState.html#patch

當我們需要同時修改多筆數據的狀態時,如果還是按照上面方法,可能要這么寫:

constchangeName = => {

componentStoreObj.name = 'hello pingan8787'

componentStoreObj.age = '18'

componentStoreObj.addr = 'xiamen'

}

上面這么寫也沒什么問題,但是 Pinia 官網已經說明,使用 $patch的效率會更高,性能更好,所以在修改多筆數據時,更推薦使用 $patch,使用方式也很簡單:

constchangeName = => {

// 參數類型1:對象

componentStoreObj.$patch({

name: 'hello pingan8787',

age: '18',

addr: 'xiamen',

})

// 參數類型2:方法,該方法接收 store 中的 state 作為參數

componentStoreObj.$patch( state=> {

state.name = 'hello pingan8787';

state.age = '18';

state.addr = 'xiamen';

})

}

  1. 通過 action方法修改多筆數據的狀態;

也可以在 store 中定義 actions 的一個方法來更新:

// store.ts

import{ defineStore } from'pinia';

exportdefaultdefineStore({

id: 'testStore',

state: => {

return{

name: 'pingan8787',

age: '10',

addr: 'fujian'

}

},

actions: {

updateState{

this.name = 'hello pingan8787';

this.age = '18';

this.addr = 'xiamen';

}

}

})

使用時:

constchangeName = => {

componentStoreObj.updateState;

}

這三種方式都能更新 Pinia 中 store 的數據狀態。

五、Element Plus 1. element-plus 打包時 @charset 警告

項目新安裝的 element-plus 在開發階段都是正常,沒有提示任何警告,但是在打包過程中,控制臺輸出下面警告內容:

在官方 issues 中查閱很久:https://github.com/element-plus/element-plus/issues/3219。

嘗試在 vite.config.ts中配置 charset: false,結果也是無效:

// vite.config.ts

exportdefaultdefineConfig({

css: {

preprocessorOptions: {

scss: {

charset: false// 無效

}

}

}

})

最后在官方的 issues 中找到處理方法:

// vite.config.ts

// https://blog.csdn.NET/u010059669/article/details/121808645

css: {

postcss: {

plugins: [

// 移除打包element時的@charset警告

{

postcssPlugin: 'internal:charset-removal',

AtRule: {

charset: ( atRule) => {

if(atRule.name === 'charset') {

atRule.remove;

}

}

}

}

],

},

}

2. 中文語言包配置

文檔地址:https://element-plus.gitee.io/zh-CN/guide/i18n.html#%E5%85%A8%E5%B1%80%E9%85%8D%E7%BD%AE

默認 elemnt-plus 的組件是英文狀態:

我們可以通過引入中文語言包,并添加到 ElementPlus 配置中來切換成中文:

// main.ts

// ... 省略其他

importElementPlus from'element-plus';

import'element-plus/dist/index.css';

importlocale from'element-plus/lib/locale/lang/zh-cn'; // element-plus 中文語言包

app.use(ElementPlus, { locale }); // 配置中文語言包

這時候就能看到 ElementPlus 里面組件的文本變成中文了。

總結

以上是我最近從入門到實戰 Vue3 全家桶的 3 個項目后總結避坑經驗,其實很多都是文檔中有介紹的,只是剛開始不熟悉。也希望大伙多看看文檔咯~

Vue3 -setup 模式確實越寫越香。

本文內容如果有問題,歡迎大家一起評論討論。

--- EOF ---

分享到:
標簽:Vue3
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定