網(wǎng)站開發(fā)有那些費用推廣互聯(lián)網(wǎng)推廣
目錄
問:uni-app 組件庫的解決方案?(xx 分鐘)
必答?
加分?
深入?
再深入?
參考鏈接?
問:在 uni-app 中,如何進行全局狀態(tài)管理?請介紹一下你對 Vuex 和 Pinia 的了解。?
必答?
加分?
參考鏈接?
問:uni-app 中的組件和 Vue.js 中的組件有什么區(qū)別??
必答?
加分?
深入?
參考鏈接?
問:請介紹一下 uni-app 的網(wǎng)絡(luò)請求庫 uni.request 與 axios 相比,它有哪些優(yōu)缺點??
必答?
加分?
參考鏈接?
問:為什么用 VSCode 開發(fā) uni-app 項目而不使用 Hbuilder??
必答?
加分?
參考鏈接?
問:如何在 uni-app 中實現(xiàn)自定義導航欄??
必答?
加分?
深入?
參考鏈接?
問:如何在 uni-app 項目中進行代碼優(yōu)化或性能優(yōu)化??
必答?
加分?
深入?
再深入-防抖和節(jié)流?
參考鏈接
?uni-app 中,如何實現(xiàn)下拉刷新和上拉加載更多功能??
必答-下拉刷新?
必答-分頁加載?
如何在 uni-app 中處理表單元素??
必答?
加分-表單校驗?
參考鏈接?
問:請談談你在使用 uni-app 過程中遇到的問題,以及如何解決它們。?
必答?
參考鏈接?
問:請簡述代碼規(guī)范在團隊協(xié)作中的重要性??
必答?
深入?
問:請介紹 uni-app 中的條件編譯和平臺差異化處理??
必答?
加分?
問:uni-app 組件庫的解決方案?(xx 分鐘)
必答?
(總)我們項目使用的是?uni-ui
?組件庫,這是官方出品的組件庫,有官方的技術(shù)支持和持續(xù)維護并且 uni-ui 組件庫比較相對精簡,組件自動按需導入,有利于減小項目體積。
(分)兩個核心步驟是:
- 安裝?
@dcloudio/uni-ui
(組件庫) 和?scss
。 - 在?
pages.json
?文件中配置?easycom
?規(guī)則,實現(xiàn)?uni-ui
?組件的自動導入和注冊。
加分?
雖然?uni-ui
官方并沒有類型聲明文件,但我們在項目中還配置了?uni-ui
?的?TS
?組件類型支持,可以校驗組件的屬性,類型更安全,書寫時也有代碼提示。
實現(xiàn)類型支持其實也就多了兩個步驟:
- 安裝?
@uni-helper/uni-ui-type
?第三方類型聲明文件。 - 再配置?
tsconfig.json
,將類型聲明文件添加到?types
?數(shù)組就可以了。
深入?
TIP
準備充分的同學,可以自己融入加分回答中,或者引導面試官往自己準備的方向提問。
其實?uni-app
?和?uni-ui
?目前還沒有 TS 官方支持,所以默認情況下組件是沒有類型校驗的,如果自己手寫組件類型聲明效率太低了?;谶@個問題,我們團隊做過一些充分的調(diào)研,uni-helper
?雖然是非官方組織,但這個第三方組織是 uni-app 生態(tài)類型聲明文件做的非常好,更新頻率也非常及時。其實在我們開發(fā)的過程中遇到些小問題,我們在?github?倉庫提的?issue?也有及時解決。最后,我們也保持關(guān)注官方文檔和更新,確保項目的穩(wěn)定性和兼容性。
再深入?
-
? 問: 為什么項目中使用?
uni-ui
?而不選擇?uview-ui
。 -
🙋?♂? 答: 我們團隊主要是考慮以下三點做出的選擇:
uni-ui
?是官方出品的組件庫,有官方的技術(shù)支持和持續(xù)維護(最重要)。uni-ui
?比較相對精簡,有利于減小項目體積。uview-ui
?暫不支持?Vue3
?開發(fā),稍微落后。
當然?uview-ui
?組件庫也不錯,是目前?uni-app
?插件市場下載量最高的第三方 Vue2 組件庫,社區(qū)中也有熱心的小伙伴為?uview-ui
?做了 Vue3 版,但目前可能作者太忙了,處于沒更新狀態(tài),不穩(wěn)定,所以綜合考慮,我們選擇官方維護的?uni-ui
。
參考鏈接?
- uni-ui 組件庫
- uview-ui 組件庫
- vk-uview-ui 組件庫-不更新
- uni-helper 組織
- uni-ui-types 類型聲明
- uni-helper 組織的 VS Code 插件-下載量 14k
- uView,有計劃支持 vue3.0 嗎?
類似問題
- 如何在 uni-app 中引入和使用第三方組件庫?
- 請介紹幾個常用的 uni-app 組件庫,以及它們的特點和使用場景?
- 組件庫的 TS 類型怎么處理?
問:在 uni-app 中,如何進行全局狀態(tài)管理?請介紹一下你對 Vuex 和 Pinia 的了解。?
必答?
(總)我們項目使用的是 Pinia 進行全局狀態(tài)管理,Vuex 或 Pinia 都是官方提供的狀態(tài)管理庫。
(分)我先說一下我對 VueX 的了解: Vuex 采用單一狀態(tài)樹的概念,將全局狀態(tài)集中管理,方便追蹤狀態(tài)變化。Vuex 主要包含以下幾個核心概念:
- State:用于存儲全局狀態(tài)。
- Getter:用于從 State 中派生出一些狀態(tài),例如計算屬性。
- Mutation:用于同步修改 State,嚴格遵循單向數(shù)據(jù)流。
- Action:用于異步操作,可以包含異步 API 請求、異步提交 Mutation 等。
我對 Pinia 的了解是 Pinia 可以理解為就是?Vuex5,是一個輕量級的、兼容 Vue 3 和 Vue 2 的狀態(tài)管理庫。Pinia 和 VueX 主要區(qū)別是廢棄了經(jīng)常被認為是極其冗余的 mutation,Pinia 主要包含以下幾個核心概念:
- Store:用于存儲全局狀態(tài)和處理狀態(tài)變化的方法,類似于 Vuex 的 State、Getter 和 Action 的集合。
- 可以創(chuàng)建和使用多個 Store 實例,每個 Store 都有自己獨立的狀態(tài)和方法。
(總)所以我們項目最終選擇的是 Pinia 進行全局狀態(tài)管理。
加分?
(總)其實我們的項目還配置了 pinia 的持久化存儲方案。
(分)我們用到了?pinia-plugin-persistedstate?插件實現(xiàn)持久化,周下載量?61k,但是這個插件默認使用?localStorage?實現(xiàn)持久化,小程序端不兼容,所以必須修改一下配置,替換為?uni-app
?支持多端的持久化 API,也就是?uni.setStorageSync()
?和?uni.getStorageSync()
。
(總)持久化存儲配置完成后,就會自動將用戶數(shù)據(jù)保存在客戶端,即使用戶關(guān)閉了小程序,數(shù)據(jù)依然可以保留。
配置參考
// stores/modules/member.ts
export const useMemberStore = defineStore('member',() => {//…省略},{// 配置持久化persist: {// 調(diào)整為兼容多端的APIstorage: {setItem(key, value) {uni.setStorageSync(key, value) },getItem(key) {return uni.getStorageSync(key) },},},},
)
?
參考鏈接?
- Vuex 官方文檔
- Pinia 官方文檔
- Pinia 對比 Vuex 3.x/4.x 官方說明
- pinia-plugin-persistedstate 插件的 storage 配置
類似問題
- 在 uni-app 中如何實現(xiàn)全局狀態(tài)管理?
- 在 uni-app 中如何實現(xiàn)持久化存儲?
問:uni-app 中的組件和 Vue.js 中的組件有什么區(qū)別??
必答?
(總)uni-app 是基于 Vue.js 構(gòu)建的跨平臺開發(fā)框架,因此?uni-app 中的組件與 Vue.js 中的組件在很多方面是相似的。然而,由于 uni-app 需要支持多個平臺,包括微信小程序、App 端和 H5 端,所以在某些方面會有一些差異。
(分)根據(jù)自身理解,選其中幾點回答即可:
以下是 uni-app 中的組件與 Vue.js 中的組件的一些主要區(qū)別:
-
跨平臺:Vue.js 主要用于開發(fā)網(wǎng)頁應用,而 uni-app 可以讓你用同一套代碼開發(fā)微信小程序、App、H5 等多個平臺的應用。
-
基礎(chǔ)組件:uni-app 提供了一套與 Vue.js 不同的基礎(chǔ)組件。這些組件是為了適應不同平臺的 UI 要求而設(shè)計的,它們在微信小程序、App 端和 H5 端上有統(tǒng)一的表現(xiàn)。在使用這些組件時,需要注意它們在不同平臺之間的差異,封裝自定義組件的時候更推薦?
<view>
、<text>
?等基礎(chǔ)組件,而非?<div>
、<span>
。 -
生命周期:雖然 uni-app 和 Vue.js 的組件都有生命周期鉤子,但是 uni-app 為了適應不同平臺而引入了一些額外的生命周期鉤子,例如?
onLaunch
、onShow
?和?onHide
。 -
樣式差異:某些 CSS 選擇器不受支持如?
*
?通配符選擇器。此外,uni-app 支持一種叫做?rpx
?的相對單位,它可以自動適應不同屏幕尺寸。 -
條件編譯:由于 uni-app 支持多個平臺,所以提供了條件編譯功能。開發(fā)者可以通過條件編譯在特定平臺上使用平臺特有的 API 或組件,從而實現(xiàn)平臺相關(guān)的功能。
(總)總的來說,uni-app 和 Vue.js 的組件在很多方面是相似的,但是由于 uni-app 需要支持多個平臺,所以在一些細節(jié)上會有所區(qū)別,平時開發(fā)時要注意平臺相關(guān)的組件、生命周期、樣式的差異。
加分?
可以展開 uni-app 生命周期,分為三部分:
- 應用生命周期:與?小程序?應用的生命周期一致(onLaunch、onShow、onHide 等)
- 頁面生命周期:與?小程序?頁面的生命周期一致(onLoad、onUnload、onShow 等)
- 組件生命周期:與?Vue.js?組件的生命周期一致(mounted、created 等)
我們的購物車頁面需要借助?onShow?生命周期鉤子獲取最新的購物車列表數(shù)據(jù),因為在商品詳情頁中進行添加購物車操作。添加成功后,打開購物車頁面應展示最新的購物車數(shù)據(jù)。因此,每次?購物車頁面 onShow?時,都應獲取最新的購物車列表數(shù)據(jù)。收貨地址列表頁同理。
深入?
(總)小程序是一個獨立的應用平臺,有自己的一套生命周期,如 onLaunch、onShow、onHide,在 uni-app 項目還支持 Vue 的生命周期鉤子。
(分)
-
onLaunch
?生命周期鉤子在 App.vue 根組件中就類似?created
?或?mounted
?鉤子。 -
Vue.js
?本身并沒有提供?onShow
?和?onHide
?生命周期鉤子,但是可以通過監(jiān)聽頁面的?visibilitychange
?事件來模擬實現(xiàn)這兩個鉤子。從而在一定程度上模擬 onShow 和 onHide 的行為。
(總)我們的 uni-app 項目主要是做小程序端,所以我們的頁面組件優(yōu)先使用小程序的生命周期鉤子,也就是 onShow、onHide 這些,普通組件就用 Vue 生命周期鉤子。
參考代碼
mounted() {document.addEventListener('visibilitychange', this.handleVisibilityChange);
},
beforeDestroy() {document.removeEventListener('visibilitychange', this.handleVisibilityChange);
},
methods: {handleVisibilityChange() {if (document.hidden) {this.onHide();} else {this.onShow();}},onShow() {console.log('頁面顯示');},onHide() {console.log('頁面隱藏');}
}
這樣,當頁面變?yōu)殡[藏狀態(tài)時,onHide?方法會被調(diào)用;當頁面重新顯示時,onShow?方法會被調(diào)用。
注意,在組件銷毀時,要記得移除?visibilitychange?事件監(jiān)聽,以避免內(nèi)存泄漏。
參考鏈接?
- uni-app 應用生命周期
- uni-app 頁面生命周期
- uni-app 組件生命周期
- WebAPI - visibilitychange 事件
類似問題
- uni-app 與 Vue 區(qū)別?
- 在 uni-app 中實現(xiàn)自定義組件,有什么區(qū)別嗎?
- 在 uni-app 中如何處理 CSS 樣式的差異?
- 請介紹 uni-app 的生命周期函數(shù),以及它們在不同平臺下的差異。
- 談談 uni-app 組件的生命周期,以及它們與 Vue.js 組件生命周期的異同。
- 如何實現(xiàn) uni-app 中的跨平臺開發(fā)?請談談 uni-app 的條件編譯。
?
問:請介紹一下 uni-app 的網(wǎng)絡(luò)請求庫 uni.request 與 axios 相比,它有哪些優(yōu)缺點??
必答?
(總)uni-app 的?uni.request
?是一個用于發(fā)起網(wǎng)絡(luò)請求的 API。它是 uni-app 框架內(nèi)置的網(wǎng)絡(luò)請求庫,兼容多端(包括小程序、App、H5 等),無需額外安裝。使用?uni.request
?可以發(fā)起 GET、POST、PUT、DELETE 等 HTTP 請求。
(分)與 axios 相比,uni.request
?的優(yōu)缺點如下:
優(yōu)點:
- 內(nèi)置于 uni-app 框架,不需要額外安裝和引入第三方庫。
- 兼容多端,可以方便地在不同平臺上使用。
缺點:
- 功能相對于 axios 較為簡單,缺少一些高級功能,例如攔截器需要自己實現(xiàn)。
- 錯誤處理不如 axios 完善。axios 可以輕松區(qū)分網(wǎng)絡(luò)錯誤和業(yè)務錯誤,而在?
uni.request
?中需要手動判斷狀態(tài)碼。
(總)其實在我們的項目中也借鑒 axios 的思想,基于?uni.request
?封裝了自己的網(wǎng)絡(luò)請求庫,可以用于處理常見的請求場景。
加分?
(總)我們自己實現(xiàn)了一個基于 uni-app 的網(wǎng)絡(luò)請求庫。通過添加攔截器,實現(xiàn)了對請求前處理和請求后的處理,提高了代碼的復用性。
(分)具體來說,代碼實現(xiàn)了以下功能:
- 添加攔截器:攔截?
request
?請求和?uploadFile
?文件上傳。 - 非?
http
?開頭的請求 URL 自動拼接基礎(chǔ)地址?baseURL
。 - 如果存在 token,則將其添加到請求頭?
Authorization
。 - 封裝了一個?
http
?函數(shù),該函數(shù)返回一個 Promise 對象,支持泛型,方便處理返回數(shù)據(jù)的類型。 - 當請求成功時(狀態(tài)碼為 2xx),執(zhí)行?
resolve()
?表示成功,并提取核心數(shù)據(jù)res.data
。 - 當請求失敗時:
- 如果狀態(tài)碼為 401,則清除用戶信息并跳轉(zhuǎn)到登錄頁面。
- 如果是其他錯誤,則根據(jù)后端錯誤信息進行提示。
- 如果是網(wǎng)絡(luò)錯誤,則提示用戶更換網(wǎng)絡(luò)。
(總)我們借鑒 axios 的思想,基于?uni.request
?封裝了自己的網(wǎng)絡(luò)請求庫,可以用于處理常見的請求場景。
參考代碼
import { useMemberStore } from '@/stores'// 服務器基地址
const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net'// 添加攔截器
const httpInterceptor = {// 攔截前觸發(fā)invoke(options: UniApp.RequestOptions) {// 1. 非 http 開頭需拼接地址if (!options.url.startsWith('http')) {options.url = baseURL + options.url}// 2. 請求超時, 默認 60soptions.timeout = 10000// 3. 添加小程序端請求頭標識options.header = {...options.header,'source-client': 'miniapp',}// 4. 添加 token 請求頭標識const memberStore = useMemberStore()const token = memberStore.profile?.tokenif (token) {options.header.Authorization = token}},
}// 添加攔截器
uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)type Data<T> = {code: stringmsg: stringresult: T
}
// 2.2 添加類型,支持泛型
export const http = <T>(options: UniApp.RequestOptions) => {// 1. 返回 Promise 對象return new Promise<Data<T>>((resolve, reject) => {uni.request({...options,// 響應成功success(res) {// 狀態(tài)碼 2xx, axios 就是這樣設(shè)計的if (res.statusCode >= 200 && res.statusCode < 300) {// 2.1 提取核心數(shù)據(jù) res.dataresolve(res.data as Data<T>)} else if (res.statusCode === 401) {// 401錯誤 -> 清理用戶信息,跳轉(zhuǎn)到登錄頁const memberStore = useMemberStore()memberStore.clearProfile()uni.navigateTo({ url: '/pages/login/login' })reject(res)} else {// 其他錯誤 -> 根據(jù)后端錯誤信息輕提示uni.showToast({icon: 'none',title: (res.data as Data<T>).msg || '請求錯誤',})reject(res)}},// 響應失敗fail(err) {uni.showToast({icon: 'none',title: '網(wǎng)絡(luò)錯誤,換個網(wǎng)絡(luò)試試',})reject(err)},})})
}
?
參考鏈接?
uni.request 網(wǎng)絡(luò)請求
uni.uploadFile 上傳文件
uni.addInterceptor 攔截器
拓展閱讀 - uni 攔截器其他用法
問:為什么用 VSCode 開發(fā) uni-app 項目而不使用 Hbuilder??
必答?
(總)其實 Hbuilder 我也有使用,不過最終體驗下來還是選擇了?VS Code
?。
(分)我主要是有 2 個出發(fā)點考慮:
- 熟悉度:VSCode 是我最熟悉并習慣使用的代碼編輯器,常用的代碼片段,快捷鍵,可以我的開發(fā)效率。
- 插件生態(tài):我針對 uni-app 項目安裝了對應的插件,代碼提示,快速新建頁面并注冊路由,鼠標懸停查文檔,這些功能我都在 VSCode 找到對應的插件,非常好用。
(總)其實還是我自己不想換開發(fā)工具,也不是刻意去比較兩者誰好誰壞,哪一個編輯器自己用起來更習慣,能提高效率就用哪個。
溫馨提示:Hbuilder 編輯器對 TS 的類型支持還不夠完善,就好比 image 組件的 mode 取值寫錯了,之前用 Hbuilder 的時候校驗不出來,而 VSCode 可以校驗出錯誤,期待 Hbuilder 的進步。(如果面試官特別喜歡用 Hbuilder 就不建議提這個,尊重每個人的喜好)
加分?
如果面試官對 VS Code 的配置感興趣,可以繼續(xù)展開如何配置:
(總)用 VS Code 開發(fā) uni-app 進行 3 步配置就可以了,也可以給面試官您分享一下:
(分)
-
安裝 uni-app 插件
- uni-create-view?:快速創(chuàng)建 uni-app 頁面
- uni-helper?:uni-app 代碼提示
- uniapp 小程序擴展?:鼠標懸停查文檔
-
JSON 注釋報錯問題,設(shè)置文件關(guān)聯(lián)即可,把?
manifest.json
?和?pages.json
?設(shè)置為?jsonc
-
針對 TS 項目增加 TS 類型校驗
- 安裝類型聲明文件?
pnpm i -D miniprogram-api-typings @uni-helper/uni-app-types
- 配置?
tsconfig.json
- 安裝類型聲明文件?
(總) HBuilder 也有它的優(yōu)點,針對 uni-app 開發(fā)的專屬功能、內(nèi)置的調(diào)試工具,如果要打包和調(diào)試 App 端還要用到 Hbuilder 工具。選擇哪一個編輯器寫代碼取決于開發(fā)者的個人喜好和項目需求。
參考鏈接?
- uni-helper 插件
- uni-create-view 插件
- VSCode 開發(fā) uni-app 教程-Vue2 版
?
問:如何在 uni-app 中實現(xiàn)自定義導航欄??
必答?
我們項目的首頁,訂單詳情頁,個人信息頁,等頁面都用到了自定義導航欄,核心步驟如下:
- 隱藏默認導航欄:在?
pages.json
?文件中按需設(shè)置?navigationStyle
?為?"custom"
?。 - 按設(shè)計稿要求編寫自定義導航欄的結(jié)構(gòu)、樣式和腳本。
- 封裝左上角返回按鈕,通過?
getCurrentPages
?獲取路由棧,如果路由棧數(shù)組長度只有 1,通過?switchTab?返回首頁,其他情況應該是用?navigateBack?返回上一頁。 - 最后,還可以根據(jù)需要抽離封裝成一個通用的組件,預留標題插槽等,方便復用。
如果自定義導航欄要求不高,其實也可以直接用 uni-ui 的?uni-nav-bar?,或者從?插件市場?中下載與項目要求接近的插件,再進行二次開發(fā)適配自己的項目。
加分?
我們項目中的自定義導航欄其實還做了安全區(qū)的樣式適配,通過?uni.getSystemInfoSync()
?獲取頂部到安全區(qū)的距離,在模板中綁定行內(nèi)樣式,避免劉海屏或前置攝像頭遮擋導航欄標題或 logo 等重要內(nèi)容。
如果左側(cè)按鈕要對齊右側(cè)的膠囊,還可以通過?wx.getMenuButtonBoundingClientRect?獲取膠囊信息實現(xiàn)對齊。
參考代碼
// src/pages.json
{"path": "pages/index/index","style": {"navigationStyle": "custom" // 隱藏默認導航}
}
?
<!-- CustomNavbar.vue -->
<script setup lang="ts">
// 獲取頁面棧
const pages = getCurrentPages()
// 獲取屏幕邊界到安全區(qū)域距離
const { safeAreaInsets } = uni.getSystemInfoSync()
</script><template><!-- 頂部安全區(qū)占位 --><view class="navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"><view class="wrap"><navigatorv-if="pages.length > 1"open-type="navigateBack"class="back icon-left"></navigator><navigator v-else url="/pages/index/index" open-type="switchTab" class="back icon-home"></navigator><view class="title"><!-- 插槽 --><slot>導航欄標題</slot></view></view></view>
</template>
深入?
其實我們項目的訂單詳情頁(或者某個頁),給自定義導航欄加了滾動驅(qū)動動畫,增強用戶視覺效果:
scroll-view
?滾動容器設(shè)置一個?id
,用于綁定動畫效果和滾動容器偏移量。- 獲取當前頁面實例,因為這個功能目前只有微信小程序端支持,H5 端不支持,還需要寫條件編譯。
- onReady 綁定生命周期鉤子中,通過 animate 設(shè)置動畫配置,并通過?
id
?綁定滾動容器,設(shè)置觸發(fā)偏移量等信息。
\
<script setup lang="ts">
// 獲取屏幕邊界到安全區(qū)域距離
const { safeAreaInsets } = uni.getSystemInfoSync()
// 獲取頁面棧
const pages = getCurrentPages()// #ifdef MP-WEIXIN
// 獲取當前頁面實例,數(shù)組最后一項
const pageInstance = pages.at(-1) as any// 頁面渲染完畢,綁定動畫效果
onReady(() => {// 動畫效果,導航欄背景色pageInstance.animate('.navbar',[{ backgroundColor: 'transparent' }, { backgroundColor: '#f8f8f8' }],1000,{scrollSource: '#scroller',timeRange: 1000,startScrollOffset: 0,endScrollOffset: 50,},)
})
// #endif
</script><template><!-- 自定義導航欄: 默認透明不可見, scroll-view 滾動到 50 時展示 --><view class="navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"><view class="wrap"><navigatorv-if="pages.length > 1"open-type="navigateBack"class="back icon-left"></navigator><navigator v-else url="/pages/index/index" open-type="switchTab" class="back icon-home"></navigator><view class="title">訂單詳情</view></view></view><scroll-view class="viewport" scroll-y enable-back-to-top id="scroller">...滾動容器</scroll-view>
</template>
參考鏈接?
- uni-nav-bar 自定義導航欄
- 插件市場 自定義導航欄
- 獲取系統(tǒng)信息
- 滾動驅(qū)動的動畫
問:如何在 uni-app 項目中進行代碼優(yōu)化或性能優(yōu)化??
必答?
(總)其實代碼優(yōu)化和性能優(yōu)化是一個持續(xù)進行的過程,我們的項目主要是做了以下的優(yōu)化:
(分)根據(jù)自身理解,選其中幾點回答即可,大部分其實在項目中都有體現(xiàn):
- 頁面加載優(yōu)化:
- 按需加載:使用圖片懶加載,只在需要時加載(商品圖片添加 lazy-load 屬性即可)。
- 分包加載:項目模塊拆分為多個包,按需加載對應的包,降低初始加載時間。(項目的分包,分包頁面的圖片等資源也可放到分包的文件夾中,減少主包資源體積)
- 代碼優(yōu)化:
- 代碼分層:按功能模塊化代碼,提高代碼可讀性和可維護性(goods.ts、home.ts 等劃分)。
- 使用枚舉:枚舉提供了一種更有意義的命名方式,使代碼更具可讀性,類型也更安全 。
- 條件編譯:在處理多端的時候,按條件編譯平臺所需代碼,減少冗余。(登錄界面等)
- 類型安全:為組件 TS 提供了靜態(tài)類型檢查,有助于在編譯階段發(fā)現(xiàn)潛在的類型錯誤。這可以減少運行時錯誤,提高代碼的可靠性。(安裝 uni-app-types、uni-ui-types)
- 數(shù)據(jù)處理優(yōu)化:
- 數(shù)據(jù)獲取:僅獲取和處理需要的數(shù)據(jù),避免不必要的數(shù)據(jù)處理,分頁時設(shè)計合理的頁容量,減少一次性渲染的節(jié)點數(shù)量。 (如:訂單列表的容量為 5,因為訂單信息較多,實際情況是屏幕大概能放 3 個)
- 數(shù)據(jù)緩存:緩存獲取的數(shù)據(jù),減少不必要的數(shù)據(jù)請求(配置持久化存儲)。
- 優(yōu)化數(shù)據(jù)更新:在 uni-app 中,定義在 data/ref 里面的數(shù)據(jù)每次變化時都會通知視圖層重新渲染頁面。所以如果不是視圖所需要的變量,可以不定義在 data/ref 中,可定義普通變量,以避免造成資源浪費。(如分頁的參數(shù),僅用于發(fā)送請求和判斷條件,不用于界面渲染,沒有用 ref 定義這份變化的數(shù)據(jù))
- 組件化開發(fā):
- 組件復用:對于通用功能,將其封裝為組件,提高代碼復用性。(猜你喜歡組件,輪播圖組件)
- 優(yōu)化資源文件:
- 減少本地圖片:除了 tabBar 圖片,logo 等重要的圖片,其他圖片進可能使用 CND 圖片。
- 壓縮圖片:避免使用大圖,對圖片進行壓縮,減少圖片文件大小。(素材已壓縮尺寸,在線壓縮圖片)
- 網(wǎng)絡(luò)環(huán)境適配:獲取設(shè)備的網(wǎng)絡(luò)類型,可以在應用中根據(jù)網(wǎng)絡(luò)環(huán)境做出相應調(diào)整,如在較慢的網(wǎng)絡(luò)環(huán)境下降低圖片質(zhì)量、限制大文件下載等。
- 使用 CDN 加速:
- 將靜態(tài)資源文件放在 CDN 上,加速資源文件的加載速度。(公司已購買,由運維管理,項目商品圖都已開啟 CDN 加速)
- 頁面渲染優(yōu)化:
- 使用條件渲染語句(如?
wx:if
)合理控制組件渲染:減少不必要的組件渲染。(空購物車,訂單狀態(tài)等,v-if 可以減少 DOM 樹的大小,從而減少重繪成本,而 v-show 通過 CSS 來控制顯示,適用于頻繁切換的場景。) - 避免不必要的組件重繪:減少不必要的數(shù)據(jù)變動,避免組件頻繁重繪。(v-for 的 key 值有助于 Vue 識別和復用已存在的元素,減少重繪次數(shù)。v-if、v-show 的合理使用也是減少重繪成本)
- 骨架屏提升用戶體驗:使用戶感知到數(shù)據(jù)正在加載,降低用戶等待時的焦慮感,避免頁面白屏閃爍。(微信開發(fā)者工具自動生成,項目首頁和部分請求數(shù)據(jù)量較大的頁面記得添加骨架屏)
- 避免視圖層和邏輯層頻繁進行通訊:減少?
scroll-view
?組件的?scroll
?事件監(jiān)聽,注意 onPageScroll 的使用。(項目中沒有使用 scroll 和 onPageScroll,如果一定要使用可以添加防抖?減少視圖層頻繁渲染,防抖和節(jié)流函數(shù) lodash 都有現(xiàn)成的) - 多使用組件自帶動畫,css 動畫,而不是通過 js 的定時器操作界面做動畫(swiper 滑動動畫是自帶的,訂單列表頁 Tabs 的滑塊使用了 css 動畫,滾動驅(qū)動的動畫是小程序自帶的并非手動監(jiān)聽 scroll 事件)
- 使用條件渲染語句(如?
- 優(yōu)化網(wǎng)絡(luò)請求:
- 使用請求攔截和響應攔截:對請求和響應進行攔截處理,提高請求效率。(http.ts 的封裝)
(總)總的來說,性能優(yōu)化是一個持續(xù)進行的過程,通過不斷地優(yōu)化和調(diào)整,提高項目的性能和用戶體驗。
加分?
理論上越多越好,按照自己的理解情況回答,回答時可提及項目中的業(yè)務場景適當展開。
深入?
如何在 uni-app 項目中使用使用防抖或節(jié)流函數(shù)。
- 安裝 lodash 工具庫?
pnpm i lodash
,在 TS 項目中安裝類型聲明文件?pnpm i -D @types/lodash
。 - 導入?
debounce
?防抖函數(shù)。 - 用?
debounce
?函數(shù)包裹原事件函數(shù)并設(shè)置合理的延遲時間(結(jié)合真機調(diào)試取合適毫秒值)。
參考代碼
組合式 API 寫法:
<script setup lang="ts">
import { throttle } from 'lodash'
import { ref } from 'vue'// 響應式數(shù)據(jù)
const scrollTop = ref(0)// 普通的事件函數(shù)
const onScroll2 = (ev: UniHelper.ScrollViewOnScrollEvent) => {// 🔴觸發(fā)頻率非常高,視圖層頻繁渲染scrollTop.value = ev.detail.scrollTop
}// 添加節(jié)流的事件函數(shù)
const onScroll = throttle((ev: UniHelper.ScrollViewOnScrollEvent) => {// 🟢在 100 秒內(nèi)最多執(zhí)行一次函數(shù),更新視圖層scrollTop.value = ev.detail.scrollTop
}, 100)
</script><template><!-- 滾動容器 --><scroll-view scroll-y @scroll="onScroll"><!-- 打印坐標 --><view style="position: fixed; top: 100rpx; left: 50rpx; background-color: pink">scrollTop:{{ scrollTop }}</view><view style="height: 5000rpx"> 內(nèi)容 </view></scroll-view>
</template>
選項式 API 寫法:
<script lang="ts">
import { debounce } from 'lodash'
import { defineComponent } from 'vue'export default defineComponent({data() {return {scrollTop: 0,debouncedScroll: null as any,}},created() {// 防抖的處理函數(shù),🟢適當延遲 50 毫秒后,再更新視圖層this.debouncedScroll = debounce(this.onScroll, 50)},unmounted() {// 最好是在組件卸載時,清除掉防抖計時器this.debouncedScroll.cancel()},methods: {// 普通的事件處理函數(shù)onScroll(ev: UniHelper.ScrollViewOnScrollEvent) {this.scrollTop = ev.detail.scrollTop},},
})
</script><template><!-- 滾動容器 --><scroll-view scroll-y @scroll="debouncedScroll"><!-- 打印坐標 --><view style="position: fixed; top: 100rpx; left: 50rpx; background-color: pink">scrollTop:{{ scrollTop }}</view><view style="height: 5000rpx"> 內(nèi)容 </view></scroll-view>
</template>
再深入-防抖和節(jié)流?
(總) 防抖(debounce)和節(jié)流(throttle)函數(shù)在處理高頻觸發(fā)事件時都非常實用。
debounce(防抖)函數(shù):該函數(shù)會從上一次被調(diào)用后,延遲?wait
?毫秒后調(diào)用func
?函數(shù)。
throttle (節(jié)流)函數(shù):在?wait
?秒內(nèi)最多執(zhí)行?func
?一次的函數(shù)。
根據(jù)自身理解,選其中幾點回答即可:
(分 1)防抖(debounce)函數(shù)在以下應用場景中非常實用:
- 輸入框?qū)崟r搜索:當用戶在輸入框中輸入時,可以使用防抖函數(shù)來延遲觸發(fā)搜索請求。這樣可以減少服務器請求次數(shù),提高性能。
- 按鈕點擊:在一些場景下,如表單提交、購物車結(jié)算等,為避免用戶頻繁點擊按鈕導致重復提交數(shù)據(jù),可以使用防抖函數(shù)控制按鈕點擊事件的觸發(fā)。
- 滾動事件:在處理滾動事件時,可以使用防抖函數(shù)來限制事件處理函數(shù)的執(zhí)行頻率。例如,當用戶滾動頁面時,可以使用防抖函數(shù)來延遲加載圖片或觸發(fā)其他與滾動相關(guān)的操作。
- 用戶操作監(jiān)聽:在實時監(jiān)控用戶操作(如鼠標移動、點擊等)的場景中,可以使用防抖函數(shù)來減少事件處理函數(shù)的執(zhí)行次數(shù),降低系統(tǒng)資源消耗。
(分 2)節(jié)流(throttle)函數(shù)在以下應用場景中非常實用:
- 滾動加載:在無限滾動列表或頁面滾動加載數(shù)據(jù)的場景中,可以使用節(jié)流函數(shù)控制滾動事件處理函數(shù)的執(zhí)行頻率,以減輕服務器壓力和提高性能。(組件庫一般有實現(xiàn))
- 頁面滾動時的動畫效果:當用戶滾動頁面時,可以使用節(jié)流函數(shù)來控制動畫效果的觸發(fā)頻率,以保持流暢的動畫表現(xiàn),避免性能抖動。(微信小程序的滾動驅(qū)動動畫內(nèi)部實現(xiàn))
- 實時監(jiān)控鼠標移動:在需要實時監(jiān)控鼠標移動的場景中,可以使用節(jié)流函數(shù)限制事件處理函數(shù)的執(zhí)行頻率,降低系統(tǒng)資源消耗。
- 瀏覽器窗口大小調(diào)整:當用戶調(diào)整瀏覽器窗口大小時,可以使用節(jié)流函數(shù)來限制與窗口大小相關(guān)的布局調(diào)整或重繪的執(zhí)行頻率,提高頁面性能。
- 實時數(shù)據(jù)采集:在需要實時采集用戶行為數(shù)據(jù)的場景中,可以使用節(jié)流函數(shù)來控制數(shù)據(jù)發(fā)送頻率,減輕服務器壓力。
(總)雖然防抖和節(jié)流的應用場景看似有所重疊,但它們的工作原理和應用場景有所不同:
- 工作原理:
防抖(debounce):當事件觸發(fā)后,防抖函數(shù)會等待一定時間(設(shè)定的延遲時間),如果在這段時間內(nèi)事件沒有再次觸發(fā),則執(zhí)行事件處理函數(shù)。如果在這段時間內(nèi)事件再次觸發(fā),那么重新開始等待延遲時間。簡單來說,防抖就是讓事件處理函數(shù)在事件觸發(fā)后的一段時間內(nèi)不執(zhí)行,只有當事件停止觸發(fā)一段時間后,才會執(zhí)行。
節(jié)流(throttle):節(jié)流函數(shù)會在一定時間間隔內(nèi)執(zhí)行事件處理函數(shù),即使在這段時間內(nèi)事件多次觸發(fā),也只會執(zhí)行一次事件處理函數(shù)。簡言之,節(jié)流就是讓事件處理函數(shù)以固定的頻率執(zhí)行。
- 應用場景:
它們在不同的場景下有各自的優(yōu)勢:
防抖適用于需要等待一段時間后才執(zhí)行的場景,如:搜索框輸入實時搜索、按鈕點擊避免重復提交等。這些場景中,只關(guān)心事件觸發(fā)的最后一次,而不關(guān)心事件在中間的過程。
節(jié)流適用于需要以一定頻率執(zhí)行的場景,如:滾動加載、窗口大小調(diào)整、鼠標移動監(jiān)控等。這些場景中,關(guān)心事件在整個過程中的表現(xiàn),而不僅僅是最后一次觸發(fā)。
總結(jié):防抖關(guān)注事件觸發(fā)后的延遲執(zhí)行,節(jié)流關(guān)注事件在整個過程中以固定頻率執(zhí)行。在選擇使用防抖或節(jié)流時,需要根據(jù)具體的應用場景和需求來決定。
參考鏈接
- uni-app 優(yōu)化建議-官方整理
- 智能 WebP, PNG 和 JPEG 壓縮
- 防抖的事件處理器 - Vue 官方文檔
- 創(chuàng)建一個防抖 ref - Vue 官方文檔
- lodash 防抖 debounce 函數(shù)用法
- lodash 節(jié)流 throttle 函數(shù)用法
類似問題
- 請談談如何在 uni-app 中實現(xiàn)頁面的按需加載?
- 請談談防抖和節(jié)流的理解和應用場景?
?uni-app 中,如何實現(xiàn)下拉刷新和上拉加載更多功能??
參考首頁的下拉刷新,猜你喜歡組件和熱門推薦頁的上拉加載分頁。
必答-下拉刷新?
我們是通過?scroll-view
?組件 實現(xiàn)的下拉刷新,步驟如下:
- 啟用下拉刷新: 添加?
refresher-enabled
?屬性。 - 下拉刷新事件:綁定?
@refresherrefresh
?事件。 - 添加 下拉刷新狀態(tài) 標記: 添加?
refresher-triggered
?屬性,用于關(guān)閉動畫的。 - 下拉刷新事件內(nèi)部:主要是重新獲取數(shù)據(jù),當數(shù)據(jù)獲取成功后,主動關(guān)閉下拉刷新動畫。注意在多個請求的情況下,需要用?
Promise.all()
?等所有請求都結(jié)束了,再關(guān)閉動畫
<script setup lang="ts">
// 當前下拉刷新狀態(tài)
const isTriggered = ref(false)
// 自定義下拉刷新被觸發(fā)
const onRefresherrefresh = async () => {// 開始動畫isTriggered.value = true// 加載數(shù)據(jù)await Promise.all([getHomeBannerData(), getHomeCategoryData(), getHomeHotData()])// 關(guān)閉動畫isTriggered.value = false
}
</script><template><!-- 滾動容器 --><scroll-viewrefresher-enabled@refresherrefresh="onRefresherrefresh":refresher-triggered="isTriggered"scroll-y>....</scroll-view>
</template>
?
必答-分頁加載?
上拉加載更多其實就是分頁加載,主要步驟如下。
- 定義?
pageParams
?對象,存儲分頁參數(shù),包括頁碼?page
?和每頁數(shù)據(jù)量?pageSize
。 - 定義?
finish
?響應式引用,表示是否已加載完所有數(shù)據(jù)。 - 滾動觸底事件:給?
scroll-view
?組件綁定?@scrolltolower
?事件。 - 在事件內(nèi)部需要判斷是否已加載完所有數(shù)據(jù),沒有結(jié)束就繼續(xù)發(fā)送請求,同時頁碼要累加,獲取的數(shù)據(jù)要追加到原數(shù)組后,如果分頁已結(jié)束,就更新?
finish
?標記,并提醒用戶。
<script setup lang="ts">
// 分頁參數(shù)
const pageParams: Required<PageParams> = {page: 1,pageSize: 10,
}
// 猜你喜歡的列表
const guessList = ref<GuessItem[]>([])
// 已結(jié)束標記
const finish = ref(false)
// 獲取猜你喜歡數(shù)據(jù)
const getHomeGoodsGuessLikeData = async () => {// 退出分頁判斷if (finish.value === true) {return uni.showToast({ icon: 'none', title: '沒有更多數(shù)據(jù)~' })}const res = await getHomeGoodsGuessLikeAPI(pageParams)// 數(shù)組追加guessList.value.push(...res.result.items)// 分頁條件if (pageParams.page < res.result.pages) {// 頁碼累加pageParams.page++} else {finish.value = true}
}
// 重置數(shù)據(jù)
const resetData = () => {pageParams.page = 1guessList.value = []finish.value = false
}
// 組件掛載完畢
onMounted(() => {getHomeGoodsGuessLikeData()
})
</script><template><!-- 滾動容器 --><scroll-view @scrolltolower="onScrolltolower" scroll-y><!-- 猜你喜歡列表 --><view class="guess"><navigatorclass="guess-item"v-for="item in guessList":key="item.id":url="`/pages/goods/goods?id=${item.id}`"><image class="image" mode="aspectFill" :src="item.picture"></image><view class="name"> {{ item.name }} </view><view class="price"><text class="small">¥</text><text>{{ item.price }}</text></view></navigator></view><view class="loading-text">{{ finish ? '沒有更多數(shù)據(jù)~' : '正在加載...' }}</view></scroll-view>
</template>
如何在 uni-app 中處理表單元素??
必答?
在我們項目的個人信息頁,收貨地址表單頁等頁面都涉及到表單數(shù)據(jù)的收集。
(總)在 uni-app 中使用的是?<input>
、<radio>
?、<checkbox>
?和?<picker>
?等組件,能兼容不同平臺。
(分)
input
?支持?v-model
?雙向綁定,收集數(shù)據(jù)比較便利。<radio>
?、<checkbox>
?和?<picker>
?等不支持?v-model
?指令,可以使用?:value
?和?@change
?代替?v-model
?來實現(xiàn)類似的效果。
(總)?小程序端的表單組件具有一些特有的屬性,外觀和功能都有些差異,如?input
?組件的?type
?屬性支持的值與網(wǎng)頁端有所不同。例如,小程序端的?input
?組件有一個?idcard
?類型,而網(wǎng)頁端沒有。所以不要完全憑借網(wǎng)頁端的經(jīng)驗處理小程序的表單,盡管部分表單組件的名稱和網(wǎng)頁端同名,也要應該要查閱 uni-app 組件部分的文檔了解差異。
參考代碼
<script setup lang="ts">
import { ref } from 'vue'const switchValue = ref(false)const onSwitchChange = (ev: UniHelper.SwitchOnChangeEvent) => {switchValue.value = ev.detail.value
}
</script><template><view><switch :value="switchValue" @change="onSwitchChange" /></view>
</template>
(總)在這個例子中,我們使用?ref
?函數(shù)創(chuàng)建了一個名為?switchValue
?的響應式引用,并使用?:value
?將?switchValue
?的值傳遞給?<switch>
?組件。我們還定義了一個名為?onSwitchChange
?的函數(shù),它在開關(guān)狀態(tài)發(fā)生變化時被?@change
?事件監(jiān)聽器調(diào)用,從而根據(jù)事件對象中的?detail.value
?更新?switchValue
?的值。
加分-表單校驗?
項目中我們還通過?uni-forms
?實現(xiàn)了表單的校驗。
以下是使用 uni-forms 實現(xiàn)表單校驗的具體步驟:
- 創(chuàng)建表單數(shù)據(jù)和驗證規(guī)則:使用?
ref
?函數(shù)創(chuàng)建表單數(shù)據(jù)對象?form
?和驗證規(guī)則對象?rules
。 - 設(shè)置 ·uni-forms 屬性:在?
<uni-forms>
?組件上設(shè)置?:model
?和?:rules
?屬性,分別綁定到?form
?和?rules
。 - 使用 uni-form-item 組件和 input 組件構(gòu)建表單:為每個表單項創(chuàng)建一個?
<uni-form-item>
?組件,并設(shè)置?name
?屬性。在表單項內(nèi)部使用?<input>?
組件,并使用?v-model
?指令進行雙向數(shù)據(jù)綁定。 - 創(chuàng)建表單引用:使用?
ref
?函數(shù)創(chuàng)建一個名為?formRef
?的引用,將其設(shè)置為?<uni-forms>
?組件的?ref
?屬性。 - 創(chuàng)建表單提交處理函數(shù):定義一個名為?
onSubmit
?的函數(shù),在此函數(shù)內(nèi)部使用?formRef.value.validate()
?方法進行表單驗證。根據(jù)驗證結(jié)果執(zhí)行相應的邏輯(例如,提交表單或顯示錯誤提示)。 - 添加提交按鈕:在模板中添加一個提交按鈕,為其設(shè)置?
@tap
?事件監(jiān)聽器,綁定到?onSubmit
?函數(shù)。
<script setup lang="ts">
import { ref } from 'vue'const form = ref({username: '',password: '',
})const rules: UniHelper.UniFormsRules = {username: {rules: [{ required: true, errorMessage: '用戶名不能為空' }],},password: {rules: [{ required: true, errorMessage: '密碼不能為空' }],},
}const formRef = ref<UniHelper.UniFormsInstance>()const onSubmit = async () => {try {const result = await formRef.value?.validate!()console.log('校驗通過,提交數(shù)據(jù):', result)} catch (error) {console.log('校驗未通過:', error)}
}
</script><template><view><uni-forms :model="form" :rules="rules" ref="formRef"><uni-forms-item label="用戶名:" name="username"><input v-model="form.username" placeholder="請輸入用戶名" /></uni-forms-item><uni-forms-item label="密碼:" name="password"><input password v-model="form.password" placeholder="請輸入密碼" /></uni-forms-item><view><button @tap="onSubmit">提交</button></view></uni-forms></view>
</template>
參考鏈接?
普通 form 表單
uni-forms 表單校驗
類似問題
- 在 uni-app 中,如何處理不同平臺下的表單處理差異?
?
問:請談談你在使用 uni-app 過程中遇到的問題,以及如何解決它們。?
必答?
(總)在遇到問題時,我一般都是參考官方文檔、社區(qū)資源和其他開發(fā)者的經(jīng)驗。
(分)根據(jù)自身理解,選其中幾點回答即可:
- vue 語法支持問題:uni-app 在發(fā)布到 H5 時支持所有 vue 的語法;發(fā)布到 App 和小程序時,由于平臺限制,無法實現(xiàn)全部 vue 語法。相比 Web 平臺, Vue.js 在 uni-app 中使用差異主要集中在兩個方面:
- 新增:uni-app 除了支持 Vue 實例的組件生命周期,還擁有應用生命周期及頁面的生命周期。
- 受限:相比 Web 平臺,在小程序和 App 端部分功能支持不完善,具體見兼容性列表。
- 如:微信小程序端不支持自定義指令 directive,可通過封裝工具函數(shù)實現(xiàn),參考方案。
- 跨平臺兼容性問題: 由于 uni-app 需要適配多個平臺,開發(fā)過程中可能會遇到不同平臺的兼容性問題。在遇到此類問題時,可以參考官方文檔和社區(qū)資源,了解不同平臺的特性和限制,然后針對性地解決問題。如果必要,可以使用條件編譯,在不同平臺下執(zhí)行不同的代碼。
- 如 H5 端不支持 微信登錄,滾動驅(qū)動的動畫等功能。
- 性能問題: 在 uni-app 開發(fā)過程中,可能會遇到頁面性能問題,如加載速度慢等。為了解決這些問題,可以嘗試以下方法:
- 減少本地圖片資源,壓縮圖片,避免使用大圖;(素材中已優(yōu)化,在線壓圖工具)
- 減少不必要的計算和渲染;
- 使用分包加載,按需加載頁面和資源;
- 插件兼容性問題: 當使用第三方插件或庫時,可能會遇到兼容性問題。在這種情況下,可以嘗試以下方法:
- 查找針對 uni-app 的插件版本;(如 SKU 組件要篩選支持 Vue3 版的,axios 不支持小程序端則自行封裝)
- 修改插件配置,以適應 uni-app 的環(huán)境;(如 Pinia 持久化存儲方案需要改默認配置)
- 尋找替代方案,如使用 uni-app 官方提供的 API 或組件。(如 組件庫使用官方的 uni-ui)
- 更新和維護問題: 隨著項目的發(fā)展,可能需要更新和維護代碼。為了降低維護成本,可以:
- 保持代碼的模塊化和組件化;(一直都有保持)
- 遵循良好的編碼規(guī)范;(一直都有保持)
- 編寫文檔,記錄項目結(jié)構(gòu)和功能。(一直都保持,如:封裝函數(shù)寫 JSDoc 注釋)
(總)其實 uni-app 官方文檔記錄了大量的跨平臺兼容性問題和解決方案,uni-app 插件市場有大量插件,同時 uni-app 社區(qū)也有其他開發(fā)者分享的經(jīng)驗,也可以在 uni-app 社區(qū)提問題,以找到合適的解決方案。最后,保持良好的編碼規(guī)范和項目結(jié)構(gòu),可以降低維護成本,提高開發(fā)效率。
參考鏈接?
- uni-app H5 正常但小程序異常的可能性
- uni-app 區(qū)別于傳統(tǒng) web 開發(fā)的注意
- uni-app 跨端兼容
- uni-app 常見問題-官方整理
- uni-app 優(yōu)化建議-官方整理
- uni-app 路由攔截方法使用
- 智能 WebP, PNG 和 JPEG 壓縮
問:請簡述代碼規(guī)范在團隊協(xié)作中的重要性??
必答?
(總)我們團隊是使用 ESLint、Prettier 和 Husky 來確保代碼質(zhì)量和一致性:
(分)根據(jù)自身理解,選其中幾點回答即可:
- 保持代碼一致性:代碼規(guī)范可以確保團隊成員遵循相同的編碼風格和約定。這可以提高代碼的可讀性,使團隊成員更容易理解和維護彼此的代碼。
- 提高代碼質(zhì)量:通過強制執(zhí)行一些最佳實踐,ESLint 可以幫助開發(fā)者避免常見的錯誤和潛在的風險。這有助于提高代碼的質(zhì)量,減少維護成本。
- 自動化格式化:Prettier 可以自動格式化代碼,保持代碼整潔,減輕開發(fā)者在調(diào)整代碼格式時的負擔。它可以幫助開發(fā)者專注于編寫功能代碼,而無需擔心代碼風格的問題。
- 預提交檢查:Husky 可以在代碼提交到版本控制系統(tǒng)(如 Git)之前執(zhí)行一些預定義的任務,如運行 ESLint 和 Prettier 檢查。這有助于確保僅提交符合規(guī)范的代碼,從而減少代碼審查和后期修復的成本。
- 更好的協(xié)作:通過遵循相同的代碼規(guī)范和工具,團隊成員之間的協(xié)作變得更加順暢。這有助于提高開發(fā)效率,降低溝通成本。
- 提高開發(fā)效率:使用這些工具可以自動處理一些繁瑣的任務(如格式化、檢查錯誤等),從而使開發(fā)者可以專注于編寫高質(zhì)量的功能代碼,提高開發(fā)效率。
(總)總之,通過遵循統(tǒng)一的規(guī)范,團隊可以更高效地開發(fā)和維護項目。
深入?
可以談談在 uni-app 項目中是如何應用 ESLint、Prettier 和 Husky 的,以及你遇到的一些挑戰(zhàn)和解決方法。
(總)這些配置是由團隊負責人制定,當然也可以由你自己配置,在小兔鮮兒的項目中已全部配置。
(分)具體步驟可以如下:
- 首先,我們需要安裝 ESLint、Prettier 和 Husky 作為項目的開發(fā)依賴。
- 接下來,配置 ESLint。在項目根目錄下創(chuàng)建一個 .eslintrc.js 或 .eslintrc.json 配置文件,并定義相應的規(guī)則。可以根據(jù)項目需求,選擇使用 Vue 官方推薦的規(guī)則或者自定義規(guī)則。同時,我們需要在項目的 package.json 文件中的 "scripts" 部分添加一個用于執(zhí)行 ESLint 檢查的腳本,例如:
"lint": "eslint --ext .js,.vue,.ts --fix"
。 - 接著,配置 Prettier。創(chuàng)建一個 .prettierrc.js 或 .prettierrc.json 配置文件,在其中定義代碼格式化規(guī)則。同時,可以在 .eslintrc.js 或 .eslintrc.json 文件中添加一些與 Prettier 相關(guān)的配置,以確保 ESLint 與 Prettier 能夠協(xié)同工作。
- 然后,配置 Husky。在項目中定義 Git 鉤子。例如,在 pre-commit 鉤子中執(zhí)行 ESLint 和 Prettier 檢查以確保提交的代碼符合規(guī)范。
- 最后,為了確保團隊成員能夠在各種編輯器中保持一致的代碼風格,建議在項目中添加一個 .editorconfig 文件,定義編輯器相關(guān)的通用配置。
在應用這些工具時,其實也遇到了的一些挑戰(zhàn):
- 在使用 uni. 全局變量的時候報錯,針對 uni-app 項目設(shè)置全局變量,如:getCurrentPages、uni、wx、UniHelper。
- ESLint、Prettier 和編輯器之間可能存在沖突。為了解決這個問題,可以在 .eslintrc.js 或 .eslintrc.json 文件中添加與 Prettier 相關(guān)的配置,并確保編輯器插件正確地應用了這些配置。
- 部分 ESLint 規(guī)則可能與項目需求不符。在這種情況下,可以根據(jù)項目實際情況,自定義規(guī)則或禁用部分不適用的規(guī)則。
- 當使用第三方庫或組件時,可能會遇到與 ESLint 規(guī)則沖突的問題??梢栽?.eslintignore 文件中排除這些文件,或者在特定文件中禁用特定規(guī)則。
通過克服這些挑戰(zhàn),我們可以在 uni-app 項目中順利地應用 ESLint、Prettier 和 Husky,確保代碼質(zhì)量和團隊協(xié)作的高效性。
參考配置
?
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')module.exports = {root: true,extends: ['plugin:vue/vue3-essential','eslint:recommended','@vue/eslint-config-typescript','@vue/eslint-config-prettier', // 遇到的挑戰(zhàn)2: ESLint、Prettier 存在沖突],// 遇到的挑戰(zhàn)1: 小程序全局變量globals: {uni: true,wx: true,WechatMiniprogram: true,getCurrentPages: true,UniApp: true,UniHelper: true,},parserOptions: {ecmaVersion: 'latest',},rules: {// 遇到的挑戰(zhàn)2: ESLint、Prettier 存在沖突'prettier/prettier': ['warn',{singleQuote: true,semi: false,printWidth: 100,trailingComma: 'all',endOfLine: 'auto',},],// 遇到的挑戰(zhàn)3: 部分 ESLint 規(guī)則與項目需求不符'vue/multi-word-component-names': ['off'],'vue/no-setup-props-destructure': ['off'],'vue/no-deprecated-html-element-is': ['off'],'@typescript-eslint/no-unused-vars': ['off'],},
}
問:請介紹 uni-app 中的條件編譯和平臺差異化處理??
必答?
(總)在 uni-app 開發(fā)過程中,由于需要適配多個平臺,可能會遇到不同平臺之間的差異和兼容性問題。為了解決這些問題,uni-app 提供了條件編譯和平臺差異化處理功能。
(分)
- 條件編譯(常見):,條件編譯是在編譯階段根據(jù)預設(shè)條件對代碼進行不同分支的編譯。在 uni-app 中,可以通過條件編譯實現(xiàn)針對不同平臺編譯不同的代碼。 通過在代碼中添加特定的注釋來實現(xiàn)條件編譯。例如:
// #ifdef H5
console.log('這段代碼只編譯到H5端')
// #endif// #ifdef MP-WEIXIN
console.log('這段代碼只編譯到微信小程序端')
// #endif
- 平臺差異化處理:?平臺差異化處理是在運行時根據(jù)當前平臺執(zhí)行不同的代碼邏輯。在 uni-app 中,可以通過?
const { osName } = uni.getSystemInfoSync()
?來判斷當前平臺,然后編寫針對不同平臺的代碼邏輯。例如:
// 獲取系統(tǒng)名稱
const { osName } = uni.getSystemInfoSync()
if (osName === 'ios') {console.log('ios平臺執(zhí)行的邏輯')
} else if (osName === 'android') {console.log('android平臺執(zhí)行的邏輯')
}
總結(jié): 條件編譯和平臺差異化處理是 uni-app 為解決多平臺兼容性問題提供的兩種方法。條件編譯更加常見,在編譯階段根據(jù)預設(shè)條件對代碼進行不同分支的編譯,而平臺差異化處理是在運行時根據(jù)當前平臺執(zhí)行不同的代碼邏輯。根據(jù)項目需求和場景,可以靈活選擇使用這兩種方法。
加分?
條件編譯在 uni-app 中有很多應用場景,主要用于處理不同平臺間的差異和兼容性問題。以下是一些常見的應用場景:
- 登錄功能差異:不同平臺可能有不同的登錄方式和 API。例如,微信小程序可以使用微信登錄,而 H5 平臺可能需要使用其他登錄方式,如手機號+驗證碼。這種情況下,可以使用條件編譯為不同平臺提供適當?shù)牡卿泴崿F(xiàn)。
// #ifdef MP-WEIXIN
// 微信小程序登錄
const { code } = wx.login()
// #endif// #ifdef H5
// H5平臺登錄,如手機號+驗證碼
// ...
// #endif
- API 差異:不同平臺可能存在 API 差異,有的 API 在某些平臺上可能不可用。在這種情況下,可以使用條件編譯來處理平臺差異。
// #ifdef H5
navigator.geolocation.getCurrentPosition((position) => {// H5獲取地理位置
})
// #endif// #ifdef MP-WEIXIN
wx.getLocation({type: 'wgs84',success(res) {// 微信小程序獲取地理位置},
})
// #endif
- UI 組件差異:不同平臺的 UI 組件可能存在差異,例如 導航欄、底部標簽欄,微信小程序的
picker
組件和 H5 平臺的select
元素。可以使用條件編譯針對不同平臺提供不同的 UI 組件。 -
<template><!-- #ifdef H5 --><select><option value="option1">Option 1</option><option value="option2">Option 2</option></select><!-- #endif --><!-- #ifdef MP-WEIXIN --><picker><view>Option 1</view><view>Option 2</view></picker><!-- #endif --> </template>
- 資源路徑差異:有時,不同平臺對資源路徑的處理方式不同,可以使用條件編譯為不同平臺提供適當?shù)馁Y源路徑。
<template><!-- #ifdef H5 --><img data-fancybox="gallery" src="/static/img/logo.png" /><!-- #endif --><!-- #ifdef MP-WEIXIN --><image src="/static/img/logo-weixin.png" /><!-- #endif -->
</template>
總之,條件編譯在 uni-app 開發(fā)過程中具有廣泛的應用場景,主要用于解決不同平臺間的差異和兼容性問題。根據(jù)具體需求,可以靈活運用條件編譯來實現(xiàn)適配不同平臺的功能和表現(xiàn)。
類似問題
問:如何在 uni-app 的組件中實現(xiàn)跨平臺邏輯?
問:如果區(qū)分 ios 端和 android 端執(zhí)行不同的業(yè)務?