
一、概念
1. 原生 VS 跨平臺(tái)
原生開發(fā)
優(yōu)點(diǎn)
性能穩(wěn)定,使用流暢,用戶體驗(yàn)好、功能齊全,安全性有保證,兼容性好 ,可使用手機(jī)所有硬件功能等
缺點(diǎn)
開發(fā)周期長(zhǎng)、維護(hù)成本高、迭代慢、部署慢、新版本必須重新下載應(yīng)用
不支持跨平臺(tái),必須同時(shí)開發(fā)多端代碼
跨平臺(tái)開發(fā)
優(yōu)點(diǎn)
可以跨平臺(tái),一套代碼搞定iOS、Android、微信小程序、H5應(yīng)用等
開發(fā)成本較低,開發(fā)周期比原生短
適用于跟系統(tǒng)交互少、頁面不太復(fù)雜的場(chǎng)景
缺點(diǎn)
對(duì)開發(fā)者要求高,除了本身JS的了解,還必須熟悉一點(diǎn)原生開發(fā)
不適合做高性能、復(fù)雜用戶體驗(yàn),以及定制高的應(yīng)用程序。比如:抖音、微信、QQ等
同時(shí)開發(fā)多端兼容和適配比較麻煩、調(diào)試起來不方便
2. 跨平臺(tái)框架對(duì)比

3. 認(rèn)識(shí)uni-app

4. uni-app VS 微信小程序
相同點(diǎn)
都是接近原生的體驗(yàn)、打開即用、不需要安裝
都可開發(fā)微信小程序、都有非常完善的官方文檔
不同點(diǎn)
跨平臺(tái)
uni-app : 支持跨平臺(tái),編寫一套代碼,可以發(fā)布到多個(gè)平臺(tái)
微信小程序 : 不支持
工程化
uni-app : 純Vue體驗(yàn)、高效、統(tǒng)一、工程化強(qiáng)
微信小程序 : 工程化弱、使用小程序開發(fā)語言
復(fù)雜程度
uni-app : 適合不太復(fù)雜的應(yīng)用,因?yàn)樾枰嫒荻喽?,多端一起兼容和適配增加了開發(fā)者心智負(fù)擔(dān)
微信小程序 : 適合較復(fù)雜、定制性較高、兼容和穩(wěn)定性更好的應(yīng)用
如何選擇
需要跨平臺(tái)、不太復(fù)雜的應(yīng)用選 uni-app,復(fù)雜的應(yīng)用使用uni-app反而增加了難度。
不需要跨平臺(tái)、較復(fù)雜、對(duì)兼容和穩(wěn)定性要求高的選原生微信小程序
5. uni-app架構(gòu)圖

二、uni-app初體驗(yàn)
1. 開發(fā)工具
Hbuilder X : 是通用的前端開發(fā)工具,但為 uni-app 做了特別強(qiáng)化
網(wǎng)址 : hbuilderx
ps : 用Vue3的Composition API 建議用 HBuilder X最新Alpha版,舊版有兼容問題
2. 創(chuàng)建項(xiàng)目
可視化界面創(chuàng)建 ( 推薦 )
點(diǎn)工具欄里的文件 -> 新建 -> 項(xiàng)目 ( 快捷鍵Ctrl+N )
選擇uni-app類型,輸入工程名,選擇模板,選擇Vue版本,點(diǎn)擊創(chuàng)建即可

Vue-CLI 命令行創(chuàng)建

3. 運(yùn)行uni-app
在 瀏覽器 運(yùn)行
點(diǎn)擊工具欄的運(yùn)行 -> 運(yùn)行到瀏覽器 -> 選擇瀏覽器

在 微信開發(fā)者工具 運(yùn)行
如果自動(dòng)啟動(dòng)失敗,可用微信開發(fā)者工具手動(dòng)打開項(xiàng)目
項(xiàng)目在unpackage/dist/dev/mp-weixin路徑下
01 - 開啟服務(wù)端口
微信開發(fā)者工具需要開啟服務(wù)端口:
小程序開發(fā)工具設(shè)置 -> 安全(目的是讓HBuilder可以啟動(dòng)微信開發(fā)者工具)

02 - 運(yùn)行

在 手機(jī)或模擬器 運(yùn)行
這里是mac電腦 + ios手機(jī)環(huán)境
ps : 之所以要用XCode新建一個(gè)項(xiàng)目,先打開模擬器,再用hbuilderx打開相同的模擬器
是為了減少bug,不這么做容易有奇奇怪怪的小問題
XCode 設(shè)置
01 - 安裝XCode

02 - 新建Xcode項(xiàng)?

03 - 選擇項(xiàng)?類型

04 - 填寫項(xiàng)?信息

05 - 選擇路徑

06 - 啟動(dòng)Xcode項(xiàng)?生成一個(gè)IOS模擬器

07 - 運(yùn)?Xcode項(xiàng)?的效果

Hbuilderx-Alpha 設(shè)置
01 - 安裝手機(jī)模擬器插件

02 - 配置adb路徑(可跳過)
可不配 : 不配會(huì)自動(dòng)去尋找默認(rèn)的
HBuilderX正式版adb目錄位置 :
windows : 安裝路徑下的 tools/adbs 目錄
mac : HBuilderX.app/Contents/tools/adbs目錄;
HBuilderX Alpha版的adb目錄位置:
windows : 安裝路徑下的 plugins/launcher/tools/adbs 目錄
mac下 : /Applications/HBuilderX-Alpha.app/Contents/HBuilderX/plugins/launcher/tools/adbs目錄
在adbs目錄下運(yùn)行./adb ,即可使用adb命令(Win和Mac一樣)
03 - 選擇模擬器

04 - 選擇模擬器

05 - 效果

有個(gè)很嚴(yán)重的問題,我的這樣沒有熱更新,每次改完得重新運(yùn)行,我要崩潰,有沒有大佬指點(diǎn)迷津
ios模擬器問題 : 未修復(fù)

三、uni-app的架構(gòu)和配置
1. 目錄結(jié)構(gòu)

2. 開發(fā)規(guī)范
為了實(shí)現(xiàn)多端兼容,綜合考慮編譯速度、運(yùn)行性能等因素,uni-app 約定了如下開發(fā)規(guī)范:
頁面文件遵循
Vue 單文件組件 (SFC) 規(guī)范
組件標(biāo)簽靠近小程序規(guī)范
uni-app 組件規(guī)范 => 使用小程序的標(biāo)簽
接口能力(JS API)
靠近微信小程序規(guī)范 => 但需將前綴 wx 替換為 uni
uni-app接口規(guī)范
數(shù)據(jù)綁定及事件處理
同 Vue.js 規(guī)范 => 例如使用@click
生命周期
可用小程序的
也可用vue的
為兼容多端運(yùn)行
建議使用flex布局
推薦使用rpx單位
uni-app的官網(wǎng)文檔
uni-app官網(wǎng)文檔
3. main.js
main.js是 uni-app 的入口文件,主要作用是:
初始化vue實(shí)例
定義全局組件
定義全局屬性
安裝插件,如:pinia、vuex 等
01 - 初始化vue實(shí)例

02 - 定義全局組件
import { createSSRApp } from 'vue'
//引入組件
import myComponent from './components/my-component/my-component.vue'
export function createApp() {
const app = createSSRApp(App)
//調(diào)用app.component方法全局注冊(cè)組件
app.component('my-component', myComponent)
return {
app
}
}
03 - 定義全局屬性
// vue2
Vue.prototype.$http = () => {}
// vue3
export function createApp() {
const app = createSSRApp(App);
app.config.globalProperties.$http = () => {}
return {
app
}
}
04 - 安裝插件,如:pinia、vuex 等
import { createSSRApp } from 'vue'
// 當(dāng)然這里要自己先封一下 Pinia
import pinia from '.stores'
export function createApp() {
const app = createSSRApp(App);
app.use(pinia);
return {
app
Pinia // 此處必須將 Pinia 返回
}
}
4. App.vue
App.vue : 入口組件
App.vue是uni-app的入口組件,所有頁面都是在App.vue下進(jìn)行切換
App.vue本身不是頁面,這里不能編寫視圖元素,也就是沒有<template>元素
App.vue的作用是 :
應(yīng)用的生命周期
編寫全局樣式
定義全局?jǐn)?shù)據(jù) globalData
01 - 應(yīng)用生命周期
注意:應(yīng)用生命的周期僅可在App.vue中監(jiān)聽,在頁面監(jiān)聽無效。

<script>
export default {
/*
* App應(yīng)用的生命周期
*/
onLaunch: function(option) {
// 可以獲取到小程序設(shè)置的啟動(dòng)參數(shù)
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style >
/*每個(gè)頁面公共css */
</style>
02 - 編寫全局樣式
全局樣式 : App.vue 中style的樣式,作用于每一個(gè)頁面(style標(biāo)簽不支持scoped)
App.vue 中通過 @import 語句可以導(dǎo)入外聯(lián)樣式,一樣作用于每一個(gè)頁面
局部樣式 : 在 pages 目錄下 的 vue 文件的style中的樣式為局部樣式,只作用對(duì)應(yīng)的頁面,并會(huì)覆蓋 App.vue 中相同的選擇器
style標(biāo)簽不支持scoped,默認(rèn)就是局部樣式
<script>
export default {
onLaunch: function() {
},
onShow: function() {
},
onHide: function() {
}
}
</script>
<!-- 這里不支持寫scoped屬性 -->
<style lang='scss'>
/*每個(gè)頁面公共css */
/* 這個(gè)文件中定義的變量 */
@import '@/static/css/init.scss';
@import '@/static/css/base.css';
.title{
color: red;
/* 這里可以使用變量,但是其他頁面無法使用,若想使用,那個(gè)頁面也得導(dǎo)入scss文件 */
border: 2rpx solid $mainColor;
}
</style>
03 - 定義全局?jǐn)?shù)據(jù) globalData
<script>
export default {
// 定義全局變量
globalData: {
text: 'text'
},
onLaunch: function() {
// getApp對(duì)象還未獲取,暫時(shí)可以使用this.globalData獲取globalData
console.log('App Launch', this.globalData) // App Launch {text: 'text'}
},
onShow: function() {
// 可通過 getApp().globalData.* 來操作,其他頁面也是這樣調(diào)用
console.log('App Show', getApp().globalData) // App Show {text: 'text'}
},
onHide: function() {
console.log('App Hide')
}
}
</script>
// 頁面使用
onShow() {
// getApp() => 全部頁面自帶,都可以使用
console.log('page', getApp().globalData);
}
5. uni.scss
uni.scss 全局樣式文件
為了方便整體控制應(yīng)用風(fēng)格,默認(rèn)定義了uni-app框架內(nèi)置全局變量,也可以存放自定義的全局變量等
在uni.scss中定義的變量,無需 @import 就可以在任意組件中直接使用。
使用uni.scss中的變量,需在 HBuilderX 里面安裝 scss 插件(dart-sass插件),
然后在該組件的 style 上加 lang=“scss”,重啟即可生效
注意事項(xiàng) :
這里的uni-app框架內(nèi)置變量和后面uni-ui組件庫(kù)的內(nèi)置變量是不一樣的。
uni.scss定義的變量是全局可以直接使用,App.vue定義的變量只能在當(dāng)前組件中使用
uni.scss的作用 :
定義自定義的全局的樣式變量
重寫uni-app內(nèi)置的樣式變量
重寫uni-un內(nèi)置的樣式變量

6. page.json
page.json : 全局頁面配置(兼容h5、weapp、app )
pages.json 文件用來對(duì) uni-app 進(jìn)行全局配置,類似微信小程序中app.json
決定頁面的路徑、窗口樣式、原生的導(dǎo)航欄、底部的原生tabbar 等
{
"pages": [
// 頁面窗口的配置,優(yōu)先級(jí)比全局的要高
// 首頁
{
"path": "pages/index/index",
"style": {
// 相當(dāng)于配置頁面樣式
"navigationBarTitleText": "空我,核彈踢!"
}
}
],
// 相當(dāng)于整個(gè)小程序的頂部窗口
"globalStyle": {
// 導(dǎo)航欄標(biāo)題的顏色 black/white
"navigationBarTextStyle": "black",
// 導(dǎo)航欄標(biāo)題的文字,整體的,會(huì)被上面的單個(gè)頁面配置的覆蓋
"navigationBarTitleText": "迪迦奧特曼,沖啊",
// 頂部背景顏色
"navigationBarBackgroundColor": "#ff8198",
// 下拉刷新時(shí)可以看到的那個(gè)
"backgroundColor": "#F8F8F8"
}
}
7. manifest.json
manifest.json : 應(yīng)用配置
Android平臺(tái)相關(guān)配置
iOS平臺(tái)相關(guān)配置
Web端相關(guān)的配置
微信小程序相關(guān)配置
......

四、uni-ui組件庫(kù)
uni-ui是DCloud提供的一個(gè)UI組件庫(kù),一套基于Vue組件、flex布局的跨全端UI框架
uni-ui不包括uni-app框架提供的基礎(chǔ)組件,而是基礎(chǔ)組件的補(bǔ)充
網(wǎng)址 : uni-ui
1. 安裝 uni-ui 組件庫(kù)
方式一 : uni_modules按需安裝
通過 uni_modules(插件模塊化規(guī)范)單獨(dú)安裝組件
1. 官網(wǎng)找到擴(kuò)展組件清單,然后將所需要的組件導(dǎo)入到項(xiàng)目,導(dǎo)入后直接使用,無需import和注冊(cè)
2. 若想切換應(yīng)用風(fēng)格,可以在uni.scss導(dǎo)入uni-ui提供的內(nèi)置scss變量,然后重啟應(yīng)用
ps :需要登錄 DCloud 賬號(hào)才能安裝

方式二 : uni_modules全部安裝

方式三 : 創(chuàng)建項(xiàng)目時(shí)安裝
ps: 該方式使得全部組件都下載了

方式四 : npm 安裝
2. 定制 uni-ui 主題風(fēng)格
安裝dart-sass插件(一般都會(huì)提示,并自動(dòng)安裝)
在項(xiàng)目根目錄的uni.scss文件中引入uni-ui組件庫(kù)的variable.scss變量文件
然后就可以使用或修改對(duì)應(yīng)的scss變量
變量主要定義的是主題色

3. 組件樣式穿透
// 小程序 和 app 有效果
.uni-forms-item_label{
color:red !important;
}
// 小程序 和 app 和 h5
:deep(.uni-forms-item_label){
color:red !important;
}
// 小程序 和 app 和 h5
:global(.uni-forms-item_label){
color:red !important;
}
五、跨端兼容實(shí)現(xiàn)
uni-app能實(shí)現(xiàn)一套代碼、多端運(yùn)行,核心是通過編譯器 + 運(yùn)行時(shí)實(shí)現(xiàn)的:
編譯器:將uni-app統(tǒng)一代碼編譯生成每個(gè)平臺(tái)支持的特有代碼
如在小程序平臺(tái),編譯器將.vue文件拆分生成wxml、wxss、js等。
運(yùn)行時(shí):動(dòng)態(tài)處理數(shù)據(jù)綁定、事件代理,保證 Vue和對(duì)應(yīng)宿主平臺(tái) 數(shù)據(jù)的一致性
1. 存在的問題
跨平臺(tái)存在的問題:
uni-app 已將常用的組件、JS API 封裝到框架中,按照 uni-app 規(guī)范開發(fā)即可保證多平臺(tái)兼容
大部分業(yè)務(wù)均可直接滿足。
但每個(gè)平臺(tái)有自己的一些特性,因此會(huì)存在一些無法跨平臺(tái)的情況
大量寫 if else,會(huì)造成代碼執(zhí)行性能低下和管理混亂
編譯到不同的工程后二次修改,會(huì)讓后續(xù)升級(jí)變的很麻煩
跨平臺(tái)兼容解決方案:
在 C 語言中,通過 #ifdef、#ifndef 的方式,為 windows、mac 等不同 os 編譯不同的代碼
uni-app 參考這個(gè)思路,為 uni-app 提供了條件編譯手段,在一個(gè)工程里優(yōu)雅的完成了平臺(tái)個(gè)性化實(shí)現(xiàn)
2. 條件編譯
01 - 具體語法

// #ifdef %PLATFORM%
平臺(tái)特有的API實(shí)現(xiàn)
// #endif
02 - 支持的文件

<template>
<view class="content">
頁面!!!!
<!-- 只在h5中顯示 -->
<!-- #ifdef H5 -->
<view>
<uni-badge text="1" type="primary"></uni-badge>
</view>
<!-- #endif -->
<!-- 在微信中 或 app中顯示 -->
<!-- #ifdef MP-WEIXIN || APP-PLUS -->
<view class="img"></view>
<!-- #endif -->
</view>
</template>
<script>
export default {
data() {
return {
title: '1999888'
}
},
onLoad() {
// #ifdef H5
document.title = 'h5 !!!!!!!'
// 可以在這里操作dom
// #endif
// #ifdef MP-WEIXIN
// pages.json中設(shè)定的優(yōu)先級(jí)比較高
wx.setNavigationBarTitle({
title: 'WXapp'
})
// #endif
// #ifdef APP-PLUS
// 這個(gè)是跨端的
uni.setNavigationBarTitle({
title: 'APP'
})
// #endif
},
onShow() {
console.log('page', getApp().globalData);
},
}
</script>
<style lang="scss">
/* #ifdef H5 */
.uni-badge--x {
background-color: blue;
}
/* #endif */
/* #ifdef APP-PLUS || MP-WEIXIN */
.img {
height: 200rpx;
background: url("~@/static/abc/logo.png") no-repeat;
background-size: contain;
}
/* #endif */
</style>
03 - 注意事項(xiàng)
Android 和 iOS 平臺(tái)不支持條件編譯
如需區(qū)分 Android、iOS 平臺(tái),請(qǐng)通過調(diào)用 uni.getSystemInfo 來獲取平臺(tái)信息

六、頁面 - Page
1. 新建頁面
01 - 新建頁面
可直接新建頁面,不用新建目錄,會(huì)帶同名目錄

02 - 在pages.json中配置
一般會(huì)自動(dòng)生成,如果沒有,手寫即可

03 - 配置tabBar

2. 頁面路由
uni-app 有兩種頁面路由跳轉(zhuǎn)方式: 和小程序一模一樣
使用navigator組件跳轉(zhuǎn)
調(diào)用API跳轉(zhuǎn)(類似小程序,與vue-router不同)

API跳轉(zhuǎn)
跳轉(zhuǎn)到 TabBar 頁面
uni.switchTab
跳轉(zhuǎn)到 tabBar 頁面,并關(guān)閉其他所有非 tabBar 頁面
<template>
<view class="content">
<button type="primary" @click="jumpFn">switchTab</button>
</view>
</template>
<script>
export default {
methods: {
jumpFn() {
uni.switchTab({
// 需要跳轉(zhuǎn)的 tabBar 頁面的路徑(需在 pages.json 的 tabBar 字段定義的頁面),路徑后不能帶參數(shù)
url: '/pages/about/about',
success: (res) => {
console.log('success', res); // success {errMsg: 'switchTab:ok'}
},
fail: (err) => {
console.log('fail', err);
},
complete: (res) => {
console.log('complete', res); // complete {errMsg: 'switchTab:ok'}
}
})
}
}
}
</script>
跳轉(zhuǎn)到 普通 頁面
uni.navigateTo
保留當(dāng)前頁面,跳轉(zhuǎn)到應(yīng)用內(nèi)的某個(gè)頁面,使用uni.navigateBack可以返回到原頁面
<template>
<view class="content">
<button type="primary" @click="jumpFn">navigateTo</button>
</view>
</template>
<script>
export default {
methods: {
jumpFn() {
uni.navigateTo({
// 需要跳轉(zhuǎn)的應(yīng)用內(nèi)非 tabBar 的頁面的路徑 , 路徑后可以帶參數(shù)
url: '/pages/detail/detail?name=coder&age=18',
// 僅支持在app端看到運(yùn)動(dòng) 效果
animationType: 'fade-in',
animationDuration: 2000,
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
})
}
}
}
</script>
uni.navigateBack
關(guān)閉當(dāng)前頁面,返回上一頁面或多級(jí)頁面
可通過 getCurrentPages() 獲取當(dāng)前的頁面棧,決定需要返回幾層
// 此處是A頁面
uni.navigateTo({
url: 'B?id=1'
});
// 此處是B頁面
uni.navigateTo({
url: 'C?id=1'
});
// 在C頁面內(nèi) navigateBack,將返回A頁面
uni.navigateBack({
delta: 2,
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
});
uni.redirectTo
關(guān)閉當(dāng)前頁面,跳轉(zhuǎn)到應(yīng)用內(nèi)的某個(gè)頁面
uni.redirectTo({
url:'test?id=1',
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
});
uni.reLaunch
關(guān)閉所有頁面,打開到應(yīng)用內(nèi)的某個(gè)頁面
uni.reLaunch({
url:'test?id=1',
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
});
Navigator跳轉(zhuǎn)

跳轉(zhuǎn)到 tabBar 頁面
open-type="switchTab" 對(duì)應(yīng) uni.switchTab 的功能
<navigator open-type="switchTab" url="../profy/profy">跳轉(zhuǎn)到個(gè)人</navigator>
跳轉(zhuǎn)到 普通 頁面

路由跳轉(zhuǎn)中相互傳值
若有特殊字符
傳遞時(shí) : encodeURIComponent 編碼
接受時(shí) : decodeURIComponent 解碼
url查詢字符 和 直接修改值
首頁 => 詳情頁
jumpFn() {
uni.navigateTo({
// 需要跳轉(zhuǎn)的應(yīng)用內(nèi)非 tabBar 的頁面的路徑 , 路徑后可以帶參數(shù)
url: '/pages/detail/detail?name=coder&age=18',
// 僅支持在app端看到運(yùn)動(dòng) 效果
animationType: 'fade-in',
animationDuration: 2000,
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
})
}
詳情頁 => 首頁
export default {
// 可在這獲取到首頁傳遞過來的值
onLoad(option) {
console.log(option); // {name: 'coder', age: '18'}
},
/**
* 寫在這里的理由 : 用戶可能點(diǎn)擊頂部狀態(tài)欄中的返回鍵,寫在這不管怎么返回,都會(huì)觸發(fā)
*/
// 頁面被注銷時(shí)調(diào)用
onUnload() {
// 1. 獲取到已經(jīng)存在的所有頁面
const pages = getCurrentPages()
// 2. 拿到上一個(gè)頁面的實(shí)例 當(dāng)前頁面為最后一個(gè),所以上一個(gè)頁面是減2
const prePage = pages[pages.length - 2]
/**
* 3. 設(shè)置值
*/
// H5端
// #ifdef H5
prePage.arr[1].name = 'ccc'
// #endif
// 微信端,有個(gè)$vm
// #ifdef MP-WEIXIN
prePage.$vm.arr[1].name = 'ccc'
// #endif
// app端,上述兩種都可滿足,奇怪
// #ifdef APP-PLUS
// prePage.arr[1].name = 'ccc'
prePage.$vm.arr[1].name = 'ccc'
// #endif
}
}
url查詢字符 和 EventChannel修改
只有 uni.navigateTo 才能使用這個(gè)哦
首頁 => 詳情頁
jumpFn() {
uni.navigateTo({
// 需要跳轉(zhuǎn)的應(yīng)用內(nèi)非 tabBar 的頁面的路徑 , 路徑后可以帶參數(shù),如果有特殊字符記得編碼
url: `/pages/detail/detail?name=${encodeURIComponent('coder')}&age=18`,
events: {
// 為指定事件添加一個(gè)監(jiān)聽器,獲取被打開頁面?zhèn)魉偷疆?dāng)前頁面的數(shù)據(jù)
acceptDataFromOpenedPage: (data) => {
console.log('acceptDataFromOpenedPage',
data) // acceptDataFromOpenedPage {name: 'coder'}
},
someEvent: (data) => {
console.log('someEvent', data) // someEvent {age: 10}
}
},
success: (res) => {
console.log('success:', res);
// 通過eventChannel向被打開頁面?zhèn)魉蛿?shù)據(jù),用此方式可不用在url上拼接參數(shù)
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'data from starter page' })
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
})
}
詳情頁 => 首頁
export default {
// 可在這獲取到首頁傳遞過來的值
onLoad(option) {
console.log(option, decodeURIComponent(option.name)); // {name: 'coder', age: '18'}
},
/**
* 寫在這里的理由 : 用戶可能點(diǎn)擊頂部狀態(tài)欄中的返回鍵,寫在這不管怎么返回,都會(huì)觸發(fā)
*/
// 頁面被注銷時(shí)調(diào)用
onUnload() {
// 1. 拿到eventChanner渠道
const eventChanner = this.getOpenerEventChannel()
// 2. 通過渠道,傳遞數(shù)據(jù)給上一個(gè)頁面
eventChanner.emit('acceptDataFromOpenedPage', {
name: 'coder'
})
eventChanner.emit('someEvent', {
age: 10
})
// 3. 監(jiān)聽上一個(gè)頁面?zhèn)鬟f過來的數(shù)據(jù)
eventChanner.on('acceptDataFromOpenerPage', function(data) {
console.log(data) // {data: 'data from starter page'}
})
}
}
vue3寫法
首頁 => 詳情頁
<template>
<view class="content">
<button type="primary" @click="jumpFn">navigateTo</button>
</view>
</template>
<script setup>
import { ref } from 'vue'
const arr = ref([{
name: 'coder',
age: 12
},
{
name: 'star',
age: 18
},
])
const age = ref(-1)
const jumpFn = () => {
uni.navigateTo({
// 需要跳轉(zhuǎn)的應(yīng)用內(nèi)非 tabBar 的頁面的路徑 , 路徑后可以帶參數(shù),如果有特殊字符記得編碼
url: `/pages/detail/detail?name=${encodeURIComponent('coder——餓$12${}')}&age=18`,
events: {
// 為指定事件添加一個(gè)監(jiān)聽器,獲取被打開頁面?zhèn)魉偷疆?dāng)前頁面的數(shù)據(jù)
acceptDataFromOpenedPage: (data) => {
console.log('acceptDataFromOpenedPage',
data) // acceptDataFromOpenedPage {name: 'coder'}
},
someEvent: (data) => {
console.log('someEvent', data) // someEvent {age: 10}
age.value = data.age
}
},
success: (res) => {
console.log('success:', res);
},
fail: (err) => {
console.log('fail:', err);
},
complete: (res) => {
console.log('complete:', res);
},
})
}
</script>
詳情頁 => 首頁
<template>
<view>
detail-view
</view>
</template>
<script setup>
import { ref, getCurrentInstance } from 'vue'
import { onLoad, onUnload } from "@dcloudio/uni-app";
// 方式二 : 也可在defineProps中拿到傳遞過來的值
const props = defaineProps({
name: String,
age: Number
})
console.log(option.name,option.age)
// 方式一 : 可在這獲取到首頁傳遞過來的值
onLoad((option) => {
console.log(option, decodeURIComponent(option.name)); // {name: 'coder', age: '18'}
})
// 拿到當(dāng)前實(shí)例,可以理解為this
const instance = ref(getCurrentInstance().proxy)
/**
* 寫在這里的理由 : 用戶可能點(diǎn)擊頂部狀態(tài)欄中的返回鍵,寫在這不管怎么返回,都會(huì)觸發(fā)
*/
// 頁面被注銷時(shí)調(diào)用
onUnload(() => {
// 1. 拿到eventChanner渠道
const eventChanner = instance.value.getOpenerEventChannel()
// const eventChanner = getCurrentInstance().proxy.getOpenerEventChannel()
// 2. 通過渠道,拿到回調(diào)函數(shù),并且傳遞數(shù)據(jù)給上一個(gè)頁面
eventChanner.emit('acceptDataFromOpenedPage', {
name: 'coder'
})
eventChanner.emit('someEvent', {
age: 10
})
})
</script>
3. 事件總線
01 - 注意事項(xiàng)
需先監(jiān)聽,再觸發(fā)事件,比如:你在A界面觸發(fā),然后跳轉(zhuǎn)到B頁面后才監(jiān)聽是不行的
通常on 和 off 是同時(shí)使用,可以避免多次重復(fù)監(jiān)聽文章來源:http://www.zghlxwxcb.cn/news/detail-531245.html
適合頁面返回傳遞參數(shù)、適合跨組件通訊,不適合界面跳轉(zhuǎn)傳遞參數(shù)文章來源地址http://www.zghlxwxcb.cn/news/detail-531245.html
02 - 頁面通訊
uni.$emit
觸發(fā)全局的自定義事件,附加參數(shù)都會(huì)傳給監(jiān)聽器回調(diào)
uni.$emit('emitFn',{msg:'頁面更新'})
uni.$on
監(jiān)聽全局的自定義事件
事件可以由 uni.$emit 觸發(fā),回調(diào)函數(shù)會(huì)接收所有傳入事件觸發(fā)函數(shù)的額外參數(shù)
uni.$on('emitFn',(data) => {
console.log('監(jiān)聽到事件來自 emitFn ,攜帶參數(shù) msg 為:' + data.msg);
})
uni.$once
監(jiān)聽全局的自定義事件
事件可以由 uni.$emit 觸發(fā),但是只觸發(fā)一次,在第一次觸發(fā)之后移除監(jiān)聽器
uni.$once('emitFn',(data) => {
console.log('監(jiān)聽到事件來自 emitFn ,攜帶參數(shù) msg 為:' + data.msg);
})
uni.$off
移除全局自定義事件監(jiān)聽器

// 注 : 這樣并不能清除監(jiān)聽過的emitFn
uni.$off('emitFn',(data) => {
console.log('監(jiān)聽到事件來自 emitFn ,攜帶參數(shù) msg 為:' + data.msg);
})
03 - 代碼示例
需先監(jiān)聽,再觸發(fā)事件 ,比如:你在A界面觸發(fā),然后跳轉(zhuǎn)到B頁面后才監(jiān)聽是不行的
A監(jiān)聽,B發(fā)射,A再監(jiān)聽才能拿到值
A組件監(jiān)聽
<template>
<view class="content">
<button type="primary" @click="jumpFn">navigateTo</button>
</view>
</template>
<script setup>
import { onLoad, onUnload } from "@dcloudio/uni-app";
// 跳轉(zhuǎn)到詳情頁
const jumpFn = () => {
uni.navigateTo({
url: `/pages/detail/detail`,
})
}
const emitFn = (res) => {
console.log('emitFn', res);
}
onLoad(() => {
// 監(jiān)聽
uni.$on('emitFn', emitFn)
})
onUnload(() => {
// 移除
uni.$off('emitFn', emitFn)
})
</script>
B組件發(fā)射
<template>
<view>
detail-view
</view>
</template>
<script setup>
import { onUnload } from "@dcloudio/uni-app";
onUnload(() => {
uni.$emit('emitFn', {
msg: '沖啊,迪迦奧特曼?。?!'
})
})
</script>
4. 生命周期
tabBar的頁面不會(huì)銷毀,不會(huì)觸發(fā)onUnload
Options API
export default {
/**
* 都會(huì)觸發(fā)
* */
// 1.頁面的生命周期
onLoad(options) {
console.log('onLoad');
},
onShow() {
console.log('onShow');
console.log(this);
},
onReady() {
console.log('onReady');
},
onHide() {
console.log('onHide');
},
onUnload() {
console.log('onUnload');
},
onPullDownRefresh() {
console.log('onPullDownRefresh');
setTimeout(() => {
uni.stopPullDownRefresh()
}, 1000)
},
onReachBottom() {
console.log('onReachBottom');
},
// 2.Vue組件的生命周期
beforeCreate() {
console.log('beforeCreate');
},
created() {
console.log('created');
},
beforeMount() {
console.log('beforeMount');
},
mounted() {
console.log('mounted');
},
beforeDestroy() {
console.log('beforeDestroy');
},
destroyed() {
console.log('destroyed');
}
}
Composition API
<script setup>
import { ref, onBeforeMount, onMounted } from 'vue'
import {
onLoad,
onShow,
onReady,
onHide,
onUnload,
onPullDownRefresh,
onReachBottom
} from '@dcloudio/uni-app'
// 1.頁面的生命周期
onLoad((options) => {
console.log('onLoad');
})
onShow(() => {
console.log('onShow');
})
onReady(() => {
console.log('onReady');
})
onHide(() => {
console.log('onHide');
})
onUnload(() => {
console.log('onUnload');
})
onPullDownRefresh(() => {
console.log('onPullDownRefresh');
setTimeout(() => {
uni.stopPullDownRefresh()
}, 1000)
})
onReachBottom(() => {
console.log('onReachBottom');
})
// 2.Vue組件的生命周期
onBeforeMount(() => {
console.log('onBeforeMount');
})
onMounted(() => {
console.log('onMounted');
})
</script>
七、系統(tǒng)API調(diào)用
1. 網(wǎng)絡(luò)請(qǐng)求

簡(jiǎn)單使用
偷個(gè)懶,文檔上復(fù)制的~
uni.request({
url: 'https://www.example.com/request', //僅為示例,并非真實(shí)接口地址。
data: {
text: 'uni.request'
},
header: {
'custom-header': 'hello' //自定義請(qǐng)求頭信息
},
success: (res) => {
console.log(res.data);
this.text = 'request success';
}
});
01 - 進(jìn)行封裝
目錄結(jié)構(gòu)

request目錄
index.js
/**
* 封裝請(qǐng)求
*/
import { BASE_URL, TIME_OUT } from './config.js'
// 封裝成類
class StarRequest {
// 設(shè)定公共URL + 超時(shí)時(shí)間
constructor(url, timeout) {
this.baseUrl = url
this.timeout = timeout
}
request({ url, method = 'GET', data } = {}) {
// 返回一個(gè)promise
return new Promise((resolve, reject) => {
uni.request({
url: this.baseUrl + url,
timeout: this.timeout,
method,
data,
success: (res) => {
resolve(res.data)
},
fail: reject
})
})
}
get() {
return this.request(option)
}
post() {
return this.request({ ...option, method: 'POST' })
}
}
// 可創(chuàng)建多個(gè)實(shí)例,請(qǐng)求不同的地址
export const sRequest = new StarRequest(BASE_URL, TIME_OUT)
config.js
/**
* 設(shè)定常量
*/
export const BASE_URL = 'http://www.baidu.com/api'
export const TIME_OUT = 10000
modules目錄
common.js
/**
* 封裝公共邏輯
*/
import { sRequest } from '@/service/request/index.js'
// 獲取公共的字典數(shù)據(jù)
export const getAllDics = () => {
return sRequest.request({
url: '/common/dic'
})
}
統(tǒng)一導(dǎo)出index.js
/**
* 作統(tǒng)一導(dǎo)出
*/
// 公共數(shù)據(jù)
export { getAllDics } from './modules/common'
// ...
02 - 使用
import { onLoad, onUnload } from "@dcloudio/uni-app";
import { getAllDics } from '@/service/index.js'
// 封裝一下請(qǐng)求,可以寫在utils中,這里為了方便寫在這
const awaitWrap = (promise) => {
// 就不用寫try...catch了
return promise.then(res => [res, null]).catch(err => [null, err])
}
onLoad(async () => {
// 使用請(qǐng)求
const [res, err] = await awaitWrap(getAllDics())
// 如果不為空,說明拋出了異常,返回即可
if (err !== null) return console.log('請(qǐng)求錯(cuò)誤');
// 拿到數(shù)據(jù)
console.log(res);
})
2. 數(shù)據(jù)緩存
sync : 同步,不存儲(chǔ)完,不會(huì)執(zhí)行后續(xù)代碼

八、Vue文檔總結(jié)
Vue2 - Options API

Vue3 - Composition API

九、打包配置
H5 - 打包配置
1. 修改manifest.json的配置

2. 發(fā)行 - 打包H5

3. 部署到服務(wù)器即可
可看我的另一篇文章 : 云原生 之 docker
微信小程序 - 打包配置
1. 拿到小程序appId

2. 修改manifest.json的配置

3. 發(fā)行-微信小程序

4. 在微信開發(fā)者工具中進(jìn)行上傳

APP - 配置
待更新,未操作~
到了這里,關(guān)于uni-app 之 跨平臺(tái)開發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!