一、創建uniapp項目
1. 項目架構
2. 初始化項目
3. pages.json 和 tabBar 案例
4. uni-app和原生小程序開發區別
5. 用命令行創建uni-app項目
官網鏈接:https://uniapp.dcloud.net.cn/quickstart-cli.html#創建uni-app
6. 用vscode開發uni-app
在uni-app中只有manifest.json和pages.json這兩個json文件允許寫注釋,按如下添加后,這兩個文件的注釋就不報錯了
7. 拉取項目模板
小兔鮮兒
這里填入appid
項目模板中已配置好了下面的第8、第9點
8. 額外:項目基礎配置統一代碼風格
- 安裝
eslint
+prettier
pnpm i -D eslint prettier eslint-plugin-vue @vue/eslint-config-prettier @vue/eslint-config-typescript @rushstack/eslint-patch @vue/tsconfig
- 新建
.eslintrc.cjs
文件,添加以下eslint
配置
/* 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',],// 小程序全局變量globals: {uni: true,wx: true,WechatMiniprogram: true,getCurrentPages: true,getApp: true,UniApp: true,UniHelper: true,App: true,Page: true,Component: true,AnyObject: true,},parserOptions: {ecmaVersion: 'latest',},rules: {'prettier/prettier': ['warn',{singleQuote: true,semi: false,printWidth: 100,trailingComma: 'all',endOfLine: 'auto',},],'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'],},
}
- 配置
package.json
{"script": {// ... 省略 ..."lint": "eslint . --ext .vue,.js,.ts --fix --ignore-path .gitignore"}
}
- 運行
pnpm lint
::: tip 溫馨提示
到此,你已完成 eslint
+ prettier
的配置。
:::
9. 額外:Git 工作流規范
- 安裝并初始化
husky
::: code-group
pnpm dlx husky-init
npx husky-init
:::
- 安裝
lint-staged
pnpm i -D lint-staged
- 配置
package.json
{"script": {// ... 省略 ...},"lint-staged": {"*.{vue,ts,js}": ["eslint --fix"]}
}
- 修改
.husky/pre-commit
文件
npm test // [!code --]
npm run lint-staged // [!code ++]
::: tip 溫馨提示
到此,你已完成 husky
+ lint-staged
的配置。
:::
二、基礎架構
1. 引入uni-ui
ts類型如果之前已經配置過了則忽略
2. 小程序端 Pinia 持久化
配置示例
3. 請求封裝
1. 添加請求和上傳文件攔截器
2. 封裝promise請求函數
http.ts 添加 http 請求函數及類型
import { useMemberStore } from '@/stores'const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net'// 攔截器
const httpInterceptor = {// 攔截前觸發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}console.log(24, options)},
}
uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)/*** 請求函數* @param UniApp.RequestOptions* @returns Promise* 1. 返回 Promise 對象* 2. 獲取數據成功* 2.1 提取核心數據 res.data* 2.2 添加類型,支持泛型* 3. 獲取數據失敗* 3.1 401錯誤 -> 清理用戶信息,跳轉到登錄頁* 3.2 其他錯誤 -> 根據后端錯誤信息輕提示* 3.3 網絡錯誤 -> 提示用戶換網絡*/
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) {// 狀態碼 2xx, axios 就是這樣設計的if (res.statusCode >= 200 && res.statusCode < 300) {// 2.1 提取核心數據 res.dataresolve(res.data as Data<T>)} else if (res.statusCode === 401) {// 401錯誤 -> 清理用戶信息,跳轉到登錄頁const memberStore = useMemberStore()memberStore.clearProfile()uni.navigateTo({ url: '/pages/login/login' })reject(res)} else {// 其他錯誤 -> 根據后端錯誤信息輕提示uni.showToast({icon: 'none',title: (res.data as Data<T>).msg || '請求錯誤',})reject(res)}},// 響應失敗fail(err) {uni.showToast({icon: 'none',title: '網絡錯誤,換個網絡試試',})reject(err)},})})
}
三、項目首頁
1. 自定義導航
樣式適配-預留安全區域
2. 通用輪播圖組件
通用組件自動導入
配置自動導入
添加組件類型聲明:目前添加組件聲明后沒效果
輪播圖指示點:非空斷言
輪播圖接口數據類型
頁面加載的生命周期onLoad需要從@dcloudio/uni-app中引入
3. 首頁分類組件
4. 首頁熱門推薦組件
5. 首頁猜你喜歡組件
多處會使用到猜你喜歡組件,所以樣式及數據請求都放到組件內部,組件defineExpose暴露出方法供父組件調用
typeof XtxGuess 拿到的是組件的類型,InstanceType拿到的是組件的實例類型
由于類型PageParams中的page是可選的,下面pageParams.page會報錯提示page可能未定義,解決辦法是如下加上Required,將可選參數變成必填
6. 首頁下拉刷新
refresher-enabled: 開啟自定義下拉刷新,會出現對應的動畫;
refresherrefresh 下拉刷新回調
下拉刷新開始,先重置猜你喜歡組件數據
7. 首頁骨架屏
生成骨架屏,把html和樣式抽到PageSkeleton組件,刪除原生的注釋部分、刪除導航部分,只保留滾動部分
四、熱門推薦
1. 動態設置熱門推薦標題
2. 獲取熱門推薦數據
交叉類型: PageParams & { subType?: string }
3. 熱門推薦類型定義
4. 熱門推薦頁面渲染和tab交互
5. 熱門推薦分頁加載
分頁加載的條件判斷
擴展字段;環境變量判斷
五、商品分類
1. 商品分類輪播圖
2. 渲染一級分類和Tab交互
3. 二級分類和商品渲染
4. 商品分類骨架屏
把骨架屏樣式放到.vue文件的style中,把html和css中的注釋刪除,解決html中的報紅
六、商品詳情
1. 商品詳情接口請求
defineProps接收頁面傳參
2. 詳情頁面渲染
3. 商品詳情輪播圖渲染
4. 商品詳情彈出層
彈出層交互
聯合類型;用typeof獲取類型;子組件給父組件通信
七、登錄模塊
1. 小程序快捷登錄
獲取登錄憑證code:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html
獲取手機號:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
調用后臺登錄接口成功示例
模擬快捷登錄
2. 保存登錄信息
如果這里不用延時,登錄成功的提示就看不見了,因為switchTab()會自動關閉當前頁面所有內容并跳轉到 tabBar 頁面
3. 會員信息渲染
4. 會員信息-猜你喜歡部分抽離成組合式函數
并復用到首頁
5. 會員中心-設置頁分包和預下載
6. 會員中心-退出登錄
7. 會員中心-個人信息頁
分包、自定義導航
個人信息頁接口請求及數據類型
修改用戶頭像
uni.chooseMedia 調用拍照/本地相冊
uni.uploadFile 上傳文件,url為后端接口地址
修改用戶昵稱
v-model處去掉非空斷言,定義profile時改用as 斷言
更新Store信息
直接修改單個屬性,不調用setProfile
code 數組的類型和長度都確定了(類型 [string, string, string],元組),這里定義fullLocationCode得定義成如下
修改性別
修改生日
八、地址模塊
1. 動態設置標題
分包規則里置空
2. 新建地址
3. 地址列表
在onShow頁面每次顯示的鉤子函數中調用(新增返回列表也要請求)
修改地址-回顯
修改-保存地址
4. 地址表單校驗
5. 刪除地址
uni-swipe-action 滑動操作組件
九、SKU模塊
1. SKU插件
SKU算法:https://juejin.cn/post/7002746459456176158
2. 渲染商品信息
打開彈窗交互-修改按鈕模式
枚舉按鈕模式
選中值處理
從SKU組件內部獲取選中值,綁定到商品信息頁
3. 加入購物車
十、購物車模塊
1. 購物車列表渲染
uni-swipe-action組件無法渲染,把@dcloudio/uni-ui從1.5.8降級到"@dcloudio/uni-ui": “1.4.23”
2. 刪除購物車商品
3. 修改單品數量
4. 修改選中狀態
5. 底部結算信息
6. 兩個購物車頁面
十一、訂單模塊
1. 填寫訂單-基本信息渲染
2. 填寫訂單-收貨地址
3. 填寫訂單-立即購買
查看頁面參數
4. 填寫訂單-提交訂單
添加編譯模式
十二、訂單詳情
1. 自定義導航欄交互
獲取當前頁面棧集合 getCurrentPages()
小程序滾動驅動動畫
在頁面渲染完成鉤子onReady中調用
2.訂單狀態渲染
3. 待付款倒計時
uni-countdown組件
控制臺報錯uni-countdown.js被無依賴過濾,導致無法顯示該組件,如下設置可解決
4. 訂單支付
發起微信支付wx.requestPayment
關閉當前頁然后跳轉 uni.redirectTo
5. 訂單發貨
6. 確認收貨
7. 訂單物流渲染
8. 刪除訂單
十三、訂單列表
1. Tabs滑動切換
swiper的current綁定activeIndex
Tabs傳參高亮
2. 訂單列表渲染
訂單列表抽成了一個組件,請求列表接口在組件掛載生命周期onMounted中調用
3. 訂單列表訂單支付
這里更新訂單狀態,沒有刷新接口而是前端查找對應數據修改狀態
十四、項目打包
1.打包上傳
2.網頁端 pnpm dev:h5 開發調試
首頁輪播圖、商品詳情圖寬高有問題,沒有自適應:首頁輪播圖 :host選擇器在h5端不生效,修改如下
商品詳情圖寬高有問題,因為圖片上的mode="aspectFill"沒生效,加上image類:寬高100%
調用微信自有能力的地方都要修改,比如以wx.開頭的都加上條件判斷 #ifdef MP-WEIXIN #endif
搜索包含open-type的按鈕,凡是調用微信能力的地方都加條件判斷,注意路由跳轉在h5是支持的,不需要改
3. 網頁端打包 pnpm build:h5
build/h5/index.html 預覽報錯
原因是這里的路徑是根路徑
修改如下,加如下配置重新執行pnpm build:h5打包
4. android app 端預覽及調試
用Hbuilder X 打開項目,按如下操作
注意:華為mate 40 pro USB選項選擇MIDI
項目中的依賴@dcloudio/uni-app 與 Hbuilder X 版本不一致
復制如下命令,改成與Hbuilder X 一致的版本:npx @dcloudio/uvm@latest 4.7.5
在終端執行
重新運行
5. Android app 打正式包(云打包)
在HbuilderX中,打開manifest,獲取AppId
在dcloud開發中心生成證書 https://dev.dcloud.net.cn/pages/app/list
5. IOS端預覽調試打包
十五、跨端兼容樣式
1. 通配符選擇器在小程序端不生效
2. 頁面視口差異導致
去結算部分,如果定位的bottom寫0,在小程序端沒問題,在h5端就會被下面的tabbar覆蓋住,所以這里用的uni-app提供的內置css變量–window-bottom
3. h5端單頁面應用,默認開啟了樣式隔離scoped
導致首頁骨架屏樣式錯亂,解決辦法把首頁各個部分的樣式抽離出來,在各部分及骨架屏組件中單獨引入
注意下面的XtxSwiper.css改成.scss,引入的時候也改成.scss,否則小程序端會報錯
4. navigator組件在h5端渲染包裹了一層a標簽
導致樣式錯亂
小程序端沒有
解決辦法:加render-link:false
5. app端沒有渲染un-page-body
導致app端display:flex;沒生效,scroll-view高度有問題,滾動的時候把頂部固定部分滑走了;
app端外層是id=app的容器
解決:
十六、跨端組件兼容
1. button type=open-type一些能力
只有小程序支持
2. navigator open-type=navigate,在h5及app端會多渲染一層a標簽
解決:選中類名,再設置一次flex: 1
十七、跨端JS API兼容
上傳圖片api,小程序用uni.chooseMedia,app和h5端使用uni.chooseImage
十八、uniClound 云開發
1. 準備工作
2. 完成城市選擇
picker mode=region在app和h5端不支持,需要換成uni-data-picker,城市數據由云端提供
解決如下
加條件判斷,覆蓋默認樣式
解決:加上clear-icon=“false”
另外:修改時無法回顯,加上v-model這句
在h5端,地址列表點擊修改先跳轉修改頁瞬間有返回上一頁了,解決:加上@tap.prevent