uni-app 從0 到 1 製作一個專案,收藏等於學會

語言: CN / TW / HK

uni-app 是使用 vue.js 開發的所有前端應用框架,開發者編寫的一套程式碼,可以釋出到 ios、android、web ,以及各種小程式平臺。

一、建立uni-app

1、hBuilderX 視覺化建立

最便捷的就是使用 hbuilder 視覺化建立專案,在點選工具欄裡的檔案 -> 新建 -> 專案:

選擇uni-app型別,輸入工程名,選擇模板,點選建立,即可成功建立。

2、cli 腳手架建立

2.1、使用正式版

vue create -p dcloudio/uni-preset-vue my-project

2.2、使用 alpha 版

vue create -p dcloudio/uni-preset-vue#alpha my-alpha-project

2.3、使用 vue3/vite 版

建立 js 開發的專案

npx degit dcloudio/uni-preset-vue#vite my-vue3-project

建立 typeScript 開發的xia

npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project

二、專案結構

以 uni-app + vue3 + vite + ts 專案為例,專案結構目錄如圖:

  • index.html 首頁入口檔案。
  • package.json 專案配置檔案。
  • tsconfig.json typescript 配置檔案。
  • vite.config.ts vite 的配置檔案。

src 存放開發資原始檔,基本要做的事情都在這個目錄內,裡面又包含了幾個目錄檔案:

  • pages 存放所有頁面檔案,我們建立的頁面元件都放入該資料夾。
  • static 存放靜態資源的資料夾。
  • App.vue 頁面入口檔案,所有頁面都在 App.vue 下進行切換。
  • env.d.ts 第三方模組的型別宣告檔案。
  • main.ts 專案入口檔案,因為使用 ts 語法,所以後綴是 .ts
  • mainfest.json 應用配置檔案,用於指定應用名稱、圖示、許可權等。
  • pages.json 全域性配置檔案,可以配置頁面檔案路徑、視窗樣式、原生的導航欄、底部tab欄等。
  • uni.scss 是uni-app的樣式包,在其他檔案中可以快速引用樣式包內的樣式。

三、語法:

為了實現多端相容,也綜合考慮到編譯速度,執行效能等因素,uni-app 約定了以下開發規範:

1、頁面檔案遵循 vue 單檔案元件寫法

2、所有需要的標籤接近小程式的規範

3、API介面靠近微信小程式(路由、上傳下載、網路請求)

4、資料繫結及事件繫結處理遵循 vue規範

5、生命週期可以同時相容小程式和VUE的生命週期

6、樣式、為了相容建議使用彈性佈局

四、執行 uni-app 專案

1、執行 web端

2、執行小程式端

2.1、先配置小程式的執行路徑:“執行”-->"執行到小程式模擬器"-->將微信開發者工具

的正確路徑填入

2.2、如果以上配置仍然無法執行,需要開啟微信開發者工具的安全埠,在微信開發者

工具“設定”--> “安全” --> 開啟伺服器埠

2.3、最後在 hBuilder 裡執行到小程式模擬器

3、執行 app 端(android)

3.1、我們執行到的是 mumu 模擬器。需要先設定 abd 路徑,選擇

hBuilderX/plugins/launcher/tools/adbs/adb.exe 的路徑。

3.2、設定 mumu 模擬器的啟動埠為 7555

3.3、最後在 hBuilderX 裡執行到手機模擬器

五、元件

uni-app 裡的元件也是字尾為 .vue 的檔案:

4.1、可以沿用 vue 元件使用的步驟,先建立,再註冊,最後使用

4.2、也可以直接使用,即不需要匯入、註冊,直接使用

4.2、或者直接使用 uni-app 的內建元件,這部分元件與微信小程式的元件類似

4.4、如果以上方式還是無法滿足,可以使用 uni-app 提供的拓展元件,直接去元件頁面匯入到專案中,匯入的擴充套件元件會存放在 uni-modules 資料夾,使用時不需要匯入、註冊,直接使用(注意:有些元件可能依賴其他外掛,按照提示安裝即可)

六、條件編譯

因為 uni-app 需要跨平臺,而不同平臺下有自己的特殊程式碼,我們為了進行平臺相容,需要區分不同的平臺,進而進行不同的程式碼 uni-app 借鑑了 c 語言裡的 #ifdef 或者 #ifndef 的條件編譯語法來實現不同平臺的相容。

寫法:** 以 #ifdef 或 # ifndef 加 %platform% 開頭,以 #end 結尾

5.1、#ifdef : if defined 僅在某平臺存在

5.2、#ifndef : if not defined 除了某平臺均存在

5.3、%platform% : 平臺名稱

使用示例:

<!-- #ifdef APP-PLUS -->
展示在 APP 端的內容
<!-- #endif -->

<!-- #ifndef H5 -->
除了 h5 之外,其他端都展示
<!-- #endif -->

<!-- #ifdef H5 || MP-WEIXIN  -->
展示在 h5 和 微信小程式端
<!-- #endif -->

支援的檔案:

  • .vue
  • .js
  • .css
  • pages.json
  • 各預編譯語言檔案,如:.scss、.less、.stylus、.ts、.pug

static 目錄的條件編譯:

在 static 資料夾裡面再新建對應平臺的子資料夾,可以讓 uni-app 在編譯的時候選擇對應的靜態資源。

七、網路請求

uni-app 中直接提供了 uni.request 介面,可以直接傳送網路請求。

uni.request({
 url: "https://www.example.com/api/user/login",
 method: "POST",
 data: {
  userName: 'test',
 },
 success: (res) => {
  console.log("請求成功", res)
 },
 fail: (err) => {
  console.log("請求失敗", err)
 }
})

具體的配置引數可以參考官網:

https://uniapp.dcloud.net.cn/api/request/request.html

傳送網路請求的時候,往往會出現跨域問題,uni-app 官方給出了三種解決方案:

1、使用 HBuilderX 內建瀏覽器

HBuilderX 的內建瀏覽器是經過官方處理的,不存在跨域問題,在執行選單裡選擇執行到內建瀏覽器就可以看到。

此方法我們不需要任何處理,但是如果想多看幾個瀏覽器是否相容的時候,還是會存在跨域問題。

2、使用 proxy 代理

方式1:在 mainfest.json 內配置

// manifest.json
{
    "h5": {
        "devServer": {
            "proxy": {
                "/prefix/api/user/list": {
                    "target": "https://api-remote.xxxx.com",
                    "pathRewrite": {
                        "^/prefix": ""
                    }
                }
            }
        }
    }
}

方式2:vue.config.json 內配置

// vue.config.js
module.exports = {
  devServer: {
    proxy: {
      '/prefix/api/user/list': {
        target: 'https://api-remote.xxxx.com',
        pathRewrite: {
          '^/prefix': ''
        }
      }
    },
  }
}

注意:這兩種方式不能同時使用,mainfest.json 會覆蓋 vue.config.json 配置。

如果使用的是 vite + uni-app時,需要配置的 vite.config.json 與 vue.config.json 寫法上有一點點區別:

vite.config.json

import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
export default defineConfig({
 plugins: [
  uni(),
 ],
 server: {
  proxy: {
     '/api': {
      target: "https://test.com",
         rewrite: (path) => path.replace(/^\/api/, '/'),
         changeOrigin: true,
         secure: false
     }
    },
 }
})

八、nvue (native vue)介紹

因為 uni-app 需要提供多端打包,所以其提供了兩種渲染引擎,即基於前端webview渲染和基於 weex 的原生渲染,只有在 app 端 uni-app 才會根據頁面的字尾不同,啟用不同的渲染方式進行頁面內容的渲染。

nvue 雖然也可以輸出 H5 或者小程式端,但是因為其 css 寫法極其受限,所以如果將來我們在用 uni-app 開發時,不需要相容 app 端,就不需要使用 nvue。但也不意味著如果需要相容 APP 端,所有頁面都要建立成 nvue 形式,我們可以根據具體情況選擇某些頁面為 nvue。vue 和 nvue 檔案可以混用,首頁或者內容多的頁面設定為 nvue,其他頁面使用 vue 檔案。

如果一個頁面路由下同時有 vue 頁面和 nvue 頁面,即出現同名的 vue 和 nvue 檔案。那麼在 App 端,會僅使用 nvue 頁面,同名的 vue 檔案將不會被編譯到 App 端。而在非 App 端,會優先使用 vue 頁面。

weex 編譯模式和 uni-app 編譯模式,可以通過配置設定:

manifest.json

{
  // App平臺特有配置
  "app-plus": {
    "nvueCompiler":"uni-app" || "weex" //是否啟用 uni-app 模式
  }
}

uni-app預設內建整合原生模組,BindingX,animation, DOM.addRule 。通過 uni.requireNativePlugin 引入 App 原生外掛,常見的原生外掛:

  • dom
  • addRule
  • scrollToElement
  • getComponentRect
  • animation

九、生命週期

uni-app 的生命週期可以分為三類:

  • 應用程式的生命週期
  • 頁面的生命週期
  • 元件的生命週期

1、應用程式生命週期

應用程式的生命週期,一般我們直接使用,不會宣告,應用程式的生命週期只能寫到 App.vue 裡,在其他頁面裡監聽無效。

App.vue 為 uni-app 的主元件,是入口檔案,所有的頁面切換均在 App.vue 下進行,其本身不是頁面,所以在該檔案中沒有 template 模板,不能編寫檢視。一般情況下,我們會在 uni-app 的 App.vue 檔案裡進行如下操作:

  • 呼叫應用程式級別的生命週期函式
  • 配置全域性的 CSS 樣式
  • 設定全域性需要儲存的 globalData,然後可以在任意的位置通過 getApp() 獲取到uni-app 小程式例項,進而拿到 globalData
onLaunch: function() {
  //當 uni-app 程式初始化完成時觸發,在整個程式執行期間只執行一次
 console.log('App Launch')
},
  
onShow: function() {
 // 當 uni-app 啟動,從後臺進入前臺時觸發 
 console.log('App Show')
},
onHide: function() {
 // 當 uni-app 從前臺進入到後臺時觸發
 console.log('App Hide')
}

2、頁面的生命週期

頁面的生命週期,參考微信小程式的生命週期函式,其特點有:

2.1、頁面初始化時,首先觸發的是 onLoad、onShow、onReady 三個生命週期函式

2.2、這三個生命週期函式裡面均可獲得 data 內的資料

2.3、通過 tabbar 切換頁面,不管是小程式還是H5、APP端,頁面都不會被銷燬,只會觸發 onHide ,該現象遵循微信小程式

2.4、通過 navigator 進入詳情頁,依然遵循微信小程式,即當前頁觸發 onHide,詳情頁觸發 onLoad、onShow、onReady,從詳情頁返回時,詳情頁觸發 onUnload,頁面被銷燬。

<script setup>
  import { onLoad, onShow, onReady, onHide, onUnload } from "@dcloudio/uni-app"
	onLoad(() => {
		console.log("onload被執行")
	})
	onShow(() => {
		console.log("onShow被執行")
	})
	onReady(() => {
		console.log("onReady被執行")
	})
</script>

3、元件的生命週期

元件的生命週期,參考 vue 的標準生命週期,可自行檢視 vue2 和 vue3 的生命週期函式不同。

3.1、當元件所在的頁面被載入時,先觸發頁面的 onLoad、onShow ,然後再執行元件的 beforeCreate、created、beforeMount、mounted ,最後觸發頁面的 onReady 函式。

3.2、當元件所在的頁面被銷燬時,先觸發頁面的 onUnload ,之後觸發元件的 beforeDestory 和 destroyed ,最後一級頁面才觸發 onShow

總結:

page頁面建議使用微信小程式的生命週期函式

component 元件建議使用vue的生命週期函式

不建議混用

十、第三方授權登入

常見的三方登入有:

  • 微信授權登入
  • QQ 授權登入
  • 新浪微博登入
  • facebook 登入
  • 賬號密碼或驗證碼登入等等

三方授權登入是如何實現的呢?以微信授權登入為例:

APP 微信授權登入需要在微信公眾平臺申請,註冊開發者賬號,獲得相應的 AppId 和 AppSecret ,在 hBuilderX 的 mainfest.json 配置微信登入的 AppId ,另外需要跟小程式、公眾號授權賬號互通的話,也需要在微信開放平臺申請。

微信開放平臺:

https://open.weixin.qq.com/

App 端登入相關的 SDK 需要在 mainfest 中配置:

  1. 開啟 manifest.json -> App模組配置,勾選 OAuth(登陸鑑權)。檢視到登陸鑑權。在說明中有藍色連結,其中包括向微信、QQ、微博等平臺申請 sdk 的連結。
  2. 向微信、QQ、微博等平臺申請到sdk的資訊後,回填到 manifest.json 裡。
  3. 這些配置需要打包生效,真機執行仍然是HBuilder基座的設定,可使用自定義基座包。離線打包請參考離線打包文件在原生工程中配置。
  4. 配置並打包後,通過 uni.getProvider() 可以得到配置的結果列表,注意這裡返回的是 manifest.json 配置的,與手機端是否安裝微信、QQ、微博無關。

如果手機端未安裝QQ、微信、微博 呼叫時會啟動這些平臺的wap頁面登陸,如果已安裝相應客戶端,會啟動它們的客戶端登陸

以下是使用者授權登入的方法:

function userLogin(type) {
 // 獲取服務供應商
 uni.getProvider({
  service: 'oauth',
   success: (res) => {
      // 判斷是否存在供應商,存在時 發起授權請求
	if (res.provider.indexOf(type) != -1) {
		uni.login({
		  provider: type,
		  success: (res) => {
		  //獲取使用者資訊
		  uni.getUserInfo({
		    provider: type,
		    success: (info) => {
                    //使用者資訊處理
			 console.log("info", info)
		    }
		   })
		  },
		  fail: (err) => {
		    uni.showToast({
           	      title:"登入失敗",
                     duration:3000
                   })
		  }
		})
	    }
	  }
	})
}

十一、第三方框架使用

目前支援 vue3 的框架比較多,此處我們以 uView 為例:

支援Vue3 的 uView 框架,官網地址:

https://vkuviewdoc.fsq.pub/components/icon.html

1、安裝:

npm i vk-uview-ui

2、在 main.js 中全域性引入:

// 引入 uView
import uView from 'vk-uview-ui';

import { createSSRApp } from 'vue'
export function createApp() {
  const app  = createSSRApp(App)
  
  // 使用 uView UI
  app.use(uView)
  
  return { app }
}

3、引入全域性樣式

在 app.vue 入口檔案內加入全域性樣式:

@import "vk-uview-ui/index.scss";

4、引入全域性 scss 變數檔案, uni.scss 檔案內加入

@import "vk-uview-ui/theme.scss";

5、pages.json 檔案中寫入 easycom 規則(外掛市場匯入方式不需要)

"easycom": {
 "autoscan": true,
 "custom": {
  "^u-(.*)": "vk-uview-ui/components/u-$1/u-$1.vue"
 }
}

此時就能夠正常使用了。該框架能夠滿足移動端常見的佈局元件,如果我們需要做視覺化資料展示的時候,就有些不能滿足需求了,在 PC 端,我們經常使用的是 Echarts,但是由於 echart 涉及大量 dom 操作,無法跨端使用,如果需要考慮小程式就不能使用 Echarts 了。

DCloud 外掛市場提供了很多類似的框架,可以自行選擇一個符合自己專案需求的。

地址:

https://ext.dcloud.net.cn/search?q=%E5%9B%BE%E8%A1%A8

推薦使用全端可用的 uChart ,提供了豐富多樣的圖表。

uCharts是一款基於canvas API開發的適用於所有前端應用的圖表庫,開發者編寫一套程式碼,可執行到 Web、iOS、Android(基於 uni-app / taro )、以及各種小程式(微信/支付寶/百度/頭條/飛書/QQ/快手/釘釘/淘寶/京東/360)、快應用等更多支援 canvas API 的平臺。

1、使用 npm 安裝,或只獲取 u-charts.js 或 u-charts.min.js 單檔案。

npm i @qiun/ucharts

2、使用時引入 uCharts

import uCharts from "@qiun/ucharts"

繪製一個雷達圖,如圖所示:

程式碼示例:

<template>
 <view>
  <canvas canvas-id="ss" id="ss" class="charts" @touchend="tap" />
 </view>
</template>

<script setup>
 import uCharts from "@qiun/ucharts"
 var uChartsInstance = {};
 import { ref, onMounted } from "vue"
 let cWidth = ref(750)
 let cHeight = ref(500)
 onMounted(() => {
  //這裡的 750 對應 css .charts 的 width
  cWidth.value = uni.upx2px(750);
  //這裡的 500 對應 css .charts 的 height
  cHeight.value = uni.upx2px(500);
  getServerData();
 })
 function getServerData() {
  //模擬從伺服器獲取資料時的延時
  setTimeout(() => {
   //模擬伺服器返回資料,如果資料格式和標準格式不同,需自行按下面的格式拼接
	let res = {
	 categories: ["維度1", "維度2", "維度3", "維度4", "維度5", "維度6"],
	 series: [{
		 name: "成交量1",
		 data: [90, 110, 165, 195, 187, 172]
	  },
		{
			name: "成交量2",
			data: [190, 210, 105, 35, 27, 102]
		}
	]
 };
 drawCharts('ss', res);
 }, 500);
}

 function drawCharts(id, data) {
  const ctx = uni.createCanvasContext(id, this);
  uChartsInstance[id] = new uCharts({
   type: "radar",
   context: ctx,
   width: cWidth.value,
   height: cHeight.value,
   categories: data.categories,
   series: data.series,
   animation: true,
   background: "#FFFFFF",
   color: ["#1890FF", "#91CB74"],
	 padding: [5, 5, 5, 5],
	 dataLabel: false,
	 legend: {
	  show: false,
	  position: "right",
	  lineHeight: 25
	 },
	 extra: {
		 radar: {
			gridColor: "rgba(0,0,0,0.1)",
			gridCount: 3,
			opacity: 0.6,
			max: 200
		 }
		}
	});
}
 function tap(e) {
	uChartsInstance[e.target.id].touchLegend(e);
	uChartsInstance[e.target.id].showToolTip(e);
 }
</script>

<style scoped>
	.charts {
		width: 100%;
		height: 500rpx;
	}
</style>

十二、打包到各端

1、 H5、WEB 端打包

1.1、通過 “發行 -> 網站PC WEB 或手機 H5,點選“發行”。

1.2、如果直接失敗,可能是因為沒有 uni-app 的 appid,需要對應專案的mainfest.json檔案裡的基礎配置,去設定 uni-app 的 appid。

1.3、設定完畢 appid之後可以打包成功,打包成功的包會存在當前專案的 unpackage 資料夾裡的 dist 資料夾裡。

1.4、注意:預設打包完畢的專案需要部署到 web 伺服器使用,不要使用資源管理器直接開啟,除非進行相對路勁配置。

1.5、如果需要配置相對路徑,還需要去當前專案的 mainfest.json 檔案裡的 H5 選項卡里的配置路徑裡,設定為”./“

1.6、H5 選項裡除了可以配置基礎路徑之外,還可以配置專案標題,路由模式、https 協議設定、埠號打包的搖樹優化、地圖配置等。

2、Android 端 apk 包

2.1、通過發行 -> 原生 APP 雲打包。

2.2、Android 需要開發者證書,我們可以點選“如何生成證書”,地址為:

https://ask.dcloud.net.cn/article/35777,檢視如何生成證書,但是這樣麻煩的很,我們可以使用線上自制證書,需要儲存證書別名、證書私鑰密碼、匯出的證書(字尾為 keystore 的檔案)

2.3、可以選擇開啟渠道包(例如:華為、小米、VIVO等),也可以只打通用包 .android 的安裝包字尾為 apk

2.4、根據需要決定勾選程式碼混淆,是否選擇廣告推送。

2.5、打包需要個人登入 hBuilderX 賬號需要驗證,預設會提示勾選 x86cpu,我們需要在 mainfest.json 檔案裡的常用其他配置,勾選 x86;預設會提示需要遵循中國的消費者隱私協議,需要在 mainfest.json 檔案裡原始碼視圖裡的 app-plus 裡增加 privacy 欄位。

"app-plus" : {
  "privacy" : {
    "prompt" : "template",
     "template" : {
       "title" : "",
       "message" : "",
       "buttonAccept" : "我知道了",
       "buttonRefuse" : "暫不註冊"
       }
     },
  "usingComponents" : true,
}

3、小程式端

打包微信小程式之前,需要先去微信公眾平臺註冊賬號,申請一個小程式,然後在開發設定裡找打小程式的 appId。

3.1、通過發行 -> 小程式-微信

3.2、需要填寫用的小程式 appId

3.3、也可以設定高階選項,即 mainfest.json 的微信小程式配置選項卡里進行高階的打包配置,如 ES6 轉 ES5 ,程式碼樣式補全,程式碼自動壓縮,檢查安全域名,還可以配置微信小程式的位置介面。

3.4、最終打包完成的微信小程式包會儲存在當前專案的 unpackage 資料夾裡的 dist 資料夾內,包名叫 mp-weixin 。

3.5、打包完成後微信小程式需要通過微信開發者工具將小程式上傳到微信公眾平臺,在版本管理可檢視上傳的小程式。

4、基於uni-app的微信小程式分包

分包的原因:當小程式的專案比較大時,專案的頁面過多或者圖片等靜態資源過多時,小程式的單包大小限制為 2M ,如果超過時,需要考慮分包。

微信小程式的分包標準:不超過 16 個分包,單個包或者主包大小不超過 2M ,總體積一共不能超過20M。

分包的基本規範:

  • 主包裡面一般儲存 tabbar 或者即時展示的 page ,主包預設存在,即 pages 資料夾。
  • 分包儲存詳情頁或者更深的頁面,注意 tabbar 對應的頁面不可以打包到分包裡。

分包基本步驟:

4.1、在開發啟動之前設計好分包的數量,以及子包名與放置 page 和對應的 static 靜態資源。

4.2、子包的 page 不要再 pages 裡註冊了,需要使用 subpackages 欄位進行註冊。

4.3、subpackages 是一個數組,每個子包的配置資訊都是一個物件,每個物件裡都有兩個欄位:root 表示子包的相對路徑,pages 子包的頁面配置資訊,可以參考主包的 pages 配置,注意:子包的 path 路徑是相對於 root 進行配置的。

"subPackages": [
 {
  "root": "pageA",
  "pages": [{
   "path": "detail/index",
   "style": {
    "navigationBarTitleText": "pageA"
		}
	}]
 }
]

4.4、通過 preloadRule 進行分包預載入設定,該欄位值為一個物件,key 是每個分包的頁面路徑,value 是一個物件,物件裡有兩個欄位:network 表示什麼網路下可以預載入分包,有 all 、wifi。packages 表示進入頁面後預下載分包的 root 或 name,__APP__ 表示主包。

4.5、開啟分包優化,需要在對應平臺的配置下新增"optimization":{"subPackages":true}開啟分包優化,在 mainfest.json 原始碼檢視內,找到 “mp-weixin”,新增 optimaztion 。

"mp-weixin": {
  "appid": "************5843",
  "optimization": {
    "subPackages": true
  }
}
  • 目前只支援mp-weixin、mp-qq、mp-baidu、mp-toutiao的分包優化。