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

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: "//www.example.com/api/user/login",
 method: "POST",
 data: {
  userName: 'test',
 },
 success: (res) => {
  console.log("請求成功", res)
 },
 fail: (err) => {
  console.log("請求失敗", err)
 }
})

  

具體的配置參數可以參考官網:
//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": "//api-remote.xxxx.com",
                    "pathRewrite": {
                        "^/prefix": ""
                    }
                }
            }
        }
    }
}

 

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

// vue.config.js
module.exports = {
  devServer: {
    proxy: {
      '/prefix/api/user/list': {
        target: '//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: "//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 ,另外需要跟小程式、公眾號授權帳號互通的話,也需要在微信開放平台申請。

微信開放平台:
//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 框架,官網地址:
//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 插件市場提供了很多類似的框架,可以自行選擇一個符合自己項目需求的。

地址:
//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 需要開發者證書,我們可以點擊「如何生成證書」,地址為:
//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的分包優化。