目錄
1. 初始化專案,上傳 GitLab
2. Android App 打包流程
3. App 在真機上無法訪問網路的問題
4. 替換 App 應用名 / 包名 / 唯一標識 scheme
5. 一些 Ionic 樣式修改注意事項 / 回傳按鈕
6. 無資料組件 no-data.vue / !! 作用
7. async/await VS promise.all()【select and list】
8. await 最好回傳 promise 防止意外錯誤發生
9. ion-select 使用程序中遇到的問題
10. Vue3 獲取路由資訊及路由傳參
11. 在 ionic 中使用 Vuex【以登錄為栗子】
12. 通用 vue 模板 / 其他細節模塊 / 路由模塊化
13. 移動端原型工程中的 http 相關配置
14. 獲取事項串列的思路及遇到的問題
1. 初始化專案,上傳 GitLab
- 拿到一個專案之后,先請專案經理開通 GitLab 專案權限,并新建一個倉庫
- 接著下載 移動端原型工程,根據 GitLab 提示,將前述檔案上傳 GitLab
2. Android App 打包流程
- Vue3/Ionic 打包需要依靠 Android Studio + 命令列工具,環境配置類似于 Angular/Ionic
在專案根目錄下,任意命令列工具中,執行如下操作:- 添加平臺: ionic capacitor add android 【結束后命令列換行】
- 構建 原生app 資源:ionic capacitor build android 【結束后命令列換行,且自動打開 Android Studio 執行下述操作(構建app)】
- 構建完 原生app 資源之后,自動通過 Android Studio 構建 app 【可以觀察面板右下角,會顯示構建進度,初次構建app會比較慢】
- 點擊 Android Studio 導航欄中的 Build → Build Bundles/APKs → Build APKs 【通過下方導航條的 build 可以查看打包進度】
后續在 vscode 中撰寫app,需要將 vscode 中的 靜態資源/插件 更新到 Android Studio 中,執行下面兩條命令的任意一條- ionic capacitor update android
- ionic capacitor sync
- 我的電腦上執行第一條不太行,執行第二條可以成功同步
- 同步完成之后,再次執行 Build APKs 即可獲得新的 .apk 檔案
3. App 在真機上無法訪問網路的問題
- 在 res/xml 下,創建 network_security_config.xml 檔案,并添加如下內容:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config>
- 接著,在 AndroidManifest.xml 檔案下的 application 標簽中,增加以下屬性:
<application ... android:networkSecurityConfig="@xml/network_security_config" ... />
4. 替換 App 應用名 / 包名 / 唯一標識 scheme
- AndroidManifest.xml 是 app入口檔案
- 從下圖的位置可以點進配置 App 應用名 / 包名 / 唯一標識 scheme 的檔案 【必須是在 Android Studio 中才能點進去】
- 點開之后長這樣子:
- 說一下唯一標識的作用:比如我從 a應用 跳轉到 b應用,就需要 b應用的唯一標識,命名規則目前還沒有總結出來,需要后續專案完善
5. 一些 Ionic 樣式修改注意事項 / 回傳按鈕
- 回傳按鈕:
- <ion-buttons slot="start">
<ion-back-button text=""></ion-back-button>
</ion-buttons>
串列項底邊要求:- 讓 最后的串列項 沒有邊:<ion-item lines="none"></ion-item>
- 讓 除了最后一個之外的串列項 有邊:<ion-item lines="full"></ion-item>
- 切換串列項狀態:<ion-item :lines="index + 1 === listData.length ? 'none' : 'full'"></ion-item>
- 注意:動態系結 lines 之后,他的值必須加單引號 ' '
ionic 在 <style lang="scss" scoped> 中,可以直接修改標簽樣式- ion-label {
display: flex !important;
height: 40px;
}- 需要區分 element-plus,在帶 scoped 標簽下修改它時,是通過 類名(不是標簽名)修改樣式,且需要添加 :deep()
在 vue3 中使用 ionic 時,頁面中用到的 ionic 組件,都需要引入,舉個栗子:- import { IonList, IonItem, IonLabel, IonThumbnail } from '@ionic/vue'
components: { IonList, IonItem, IonLabel, IonThumbnail },
如果不宣告組件,也可以正常使用 ionic 組件,但網頁會把他們當成 web component,而不是 Vue組件,也就是說,不能使用類似于 v-model 的 Vue 語法,舉個栗子:- ion-select 組件,系結的值是通過 :value="xx" 這么寫的,但是這么寫不是回應式的
- 在 vue 里通過 v-model 進行雙向系結實作回應式,而 ion-input 上不能直接使用 v-model 替代 :value,因為他是 web component
- 如果想在 ion-input 上使用 v-model 的話,需要將 ion-input 進行引入并宣告
在 variables.css 中有常見的主題色變數,可以把 自定義顏色 放在該檔案的 :root { } 里- 在 ionic 中,使用 主題色變數/全域變數:
- ion-content {
--background: var(--bg-color-black);
}
全域樣式檔案,可以在 assets/style/ 中創建檔案,并在 main.ts 中進行引入- ionic 的全域樣式,就可以在上述檔案中修改
6. 無資料組件 no-data.vue / !! 作用
- no-data.vue
<slot v-if="!haveData"> <p class="no-data">暫無資料</p> </slot> <slot v-else name="haveData">需要展示的串列資料</slot>
- 使用串列及無資料組件
<no-data :haveData="haveData"> <template #haveData> <list-show :listData="listData"></list-show> </template> </no-data> // 匯入 串列組件 及 串列組件內部匯出的資料型別介面 import ListShow, { ListData } from '@/components/list-show.vue'
- 根據是否有串列資料,決定 haveData 的值
- state.haveData = !!state.listData.length;
- 注意:!! 可以把任意型別的判斷,最終轉換為布林值
7. async/await VS promise.all()【select and list】
- promise.all() 獲得的 成功結果陣列里的 資料順序,和 promise.all() 接收 異步方法陣列的 順序是一致的,舉個栗子:
- 假設執行 promise.all([p1, p2]),即便 p1 結果 獲取的比 p2結果晚,最終 p1結果在前
- 作用:沒有邏輯關系的異步方法,在 onMounted 中同時呼叫
- 注意:promise.all() 讓方法同時執行,而不是先后執行
async/await 可以控制方法執行的順序,不是同步執行異步方法- 假設現在有一個頁面:里面包含了需要介面請求的下拉框及串列,串列的內容是根據下拉框的內容決定的,此時就應該考慮 async/await 決定異步請求順序
- 也就是說,必須 await 下拉框請求,且拿到結果之后,才能執行串列獲取請求
- 此時不能使用 promise.all(),因為此方法只能保證結果獲取的順序,而不能保證方法執行的順序,也就是說,會同時執行 下拉框獲取 / 串列獲取 兩個方法,而不是先執行下拉框獲取并且拿到結果,再執行串列獲取方法
8. await 最好回傳 promise 防止意外錯誤發生
- await 后面必須跟一個 promise,即使該 promise 回傳空值;回傳空值的情況下,也必須 resolve(), 否則,await getSelectOptions() 之后的代碼都將無法執行
- 錯誤場景回顧:當時我寫 await getSelectOptions() ,后面執行 getListData(),getListData() 方法內部使用了 state.selectValue,getSelectOptions() 沒寫 resolve(),這直接導致加載錯誤的 bug
解決方法:const getSelectOptions = (): Promise<void> => { return new Promise((resolve, reject) => { setTimeout(() => { state.eventTypeOptions.push({ label: '行政許可', value: '行政許可', }); state.eventTypeModel = state.eventTypeOptions[0].value; resolve(); }, 2000); }) };
- 一般情況下,獲取下拉串列,都應回傳首個選中的值,否則方法耦合度會高
9. ion-select 使用程序中遇到的問題
- ion-select 自帶屬性 和 自定義配置項 會同時生效
- 自帶屬性:cancelText="取消"
- 自定義配置項: :interface-options="customActionSheetOptions"
- const customActionSheetOptions = {
cssClass: 'my-custom-interface', // 自定義類名
header: '事件型別', // 下拉框標題
translucent: true, // 讓選中項高亮
};<ion-select v-model="eventTypeModel" @ionChange="handleSecOrInpChange($event)" cancelText="取消" :interface-options="customActionSheetOptions" interface="action-sheet" > <ion-select-option v-for="(item, index) of eventTypeOptions" :value="item.value" :key="index"> {{ item.label }} </ion-select-option> </ion-select>
關于雙向系結:- 官方給的示例是 :value="eventTypeModel" 系結下拉框當前系結的值
- 如果想使用 vue 實作 --- 雙向系結 --- 的話,可替換為 v-model="eventTypeModel"
- 引入和宣告 ionic 組件之后,才能讓瀏覽器把它們當成 vue 組件,識別 vue 語法哦
關于下拉框串列獲取方式【列舉 vs 介面獲取】:- 應該通過介面獲取下拉框串列
- 假設本地使用了列舉,如果需求變更,就需要修改列舉,重新打包發布 app,并讓用戶安裝以獲取更新,用戶體驗感會降低,因此必須使用介面獲取下拉串列
使用列舉示例:- // 事項型別列舉
export enum eventType {
XZXK = '行政許可',
XZQR = '行政確認',
}- // 下拉框雙向系結的值
eventTypeModel: eventType.XZXK,
// 下拉框串列
eventTypeOptions: [{
value: eventType.XZQR,
label: eventType.XZQR,
}],
當下拉框串列發生變化時,可在 html 中傳入 $event,監聽變化- $event.detail 可以查看當前系結的 value
- const handleSecOrInpChange = (ev: any) => {
console.log(ev.detail)
};
10. Vue3 獲取路由資訊及路由傳參
- 路由跳轉并傳參【動詞,router】:
import { useRouter } from 'vue-router';
const router = useRouter();router.push({
path: 'projectListPage',
query: {
eventName: item.eventName,
},
});路由引數獲取【名詞,route】:
import { useRoute } from 'vue-router'
const route = useRoute();
eventName: route.query.eventName,
11. 在 ionic 中使用 Vuex【以登錄為栗子】
- 關于安裝版本的問題:
- 最開始是直接去 vuex 官網安裝,但是官網的版本是 3.x.x,本專案使用的是 ionic/vue3,因此要使用 4.0.0 以上的 vuex
- 綜上所述,安裝正確版本的方法 —— 修改 package.json:"vuex": "^4.0.2",然后 yarn
在頁面中使用 vuex:- src/main.ts:
import store from './store/index';
const app = createApp(App)
.use(store);src/store/index.ts:
import { createStore } from 'vuex'; // 全域變數 const state = { // 用戶資訊 userInfo: { userId: '', userName: '', phone: '', } } // mutations const mutations = { // 更新用戶資訊 UPDATAUSERID(states: any, userinfo: object){ states.userInfo = userinfo; } } // actions const actions = { // 更新用戶資訊(異步) upDataUserInfo(context: any, userinfo: object) { console.log('當前登錄用戶資訊', userinfo); context.commit('UPDATAUSERID', userinfo); } } export default createStore({ actions, mutations, state, })
src/views/login/login.vue:- import { useStore } from 'vuex';
- const store = useStore();
- const upDataUserInfo = (userInfo: any) => store.dispatch('upDataUserInfo', userInfo); // 異步更新用戶資訊
- upDataUserInfo({
userId: '2333',
userName: state.loginInfo.loginName,
phone: '110',
});
12. 通用 vue 模板 / 其他細節模塊 / 路由模塊化
- vue 通用模板:
<template> <ion-page> <ion-header> <ion-toolbar color="primary"> <ion-title>搜索</ion-title> </ion-toolbar> </ion-header> <ion-content> 搜索 </ion-content> </ion-page> </template> <script lang="ts"> import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent, } from '@ionic/vue'; import { defineComponent } from 'vue'; import { useRouter } from 'vue-router'; export default defineComponent({ name: 'Login', components: { IonHeader, IonToolbar, IonTitle, IonContent, IonPage, }, setup(props, context) { const router = useRouter(); return { } } }); </script> <style lang="scss" scoped> </style>
tab 模塊:
types 檔案夾,定義專案中需要的 typescript 型別- 還可以加 enums 檔案夾,定義專案中需要的 列舉enum 型別
路由根據 tab 可以分成多個模塊,寫在不同的 .ts 中,主路由模塊中會加方法,將 router 檔案夾下的所有路由 .ts 檔案,添加到主路由模塊中- 如果帶了 子路由,展示地址: localhost:8080/tabs/home
- 如果不帶 子路由,展示地址: localhost:8080/project-list-page
一個技巧:將路由路徑存盤到單獨的 .ts 檔案里,需要路由跳轉時,通過變數代替直接寫地址,這樣可以避免后期修改路徑名,需要全域挨個修改的麻煩// 路由變數 import { RouteApp } from '@/enums/route-config'; router.push({ path: RouteApp.ProjectList, query: { ... }, });
13. 移動端原型工程中的 http 相關配置
- 首先需要修改 public/config.js 檔案夾中的全域地址
區分三種介面型別:
- 模擬介面,即通過 Rap2 或其他介面平臺構建的模擬介面,在提供介面檔案之后,前端負責撰寫
- 介面平臺地址,即通過 token/interface/run.action 等訪問介面資料,后端撰寫,在 Network 中,通過 run 過濾此類請求
- 自定義介面地址,即通過 getData.vm 這種訪問介面資料
在 utils 檔案夾中,包含 介面路徑拼接 / axios設定 / 封裝http請求 / 配置 token 等內容- 在 service 檔案夾中,配置 具體業務的 http請求
- 以上圖 事件串列 為例:
- 模擬介面復制 Rap2模擬介面平臺中 寫的地址即可
- 后端介面平臺復制 interfaceID 欄位即可
- 自定義開發介面復制 getData.vm 這種帶.vm 的欄位即可
- 在 useApi 中,控制當前使用哪種介面
注意:后端介面平臺介面,需要配置 token,get/post 請求都需要
可以直接在 service 下的模塊中,直接定義 介面所需引數型別 / 介面回復資料型別,也可以把這兩個定義在 types 下的模塊中
- 介面請求模板定義舉例:
- 上述示例說明如下:
- 上面使用了 get/post 兩種請求,都已經在 utils 里封裝了,使用只有方法名的不同,沒有別的區別
- 方法內部傳入了當前使用的介面名,介面所需引數,是否顯示加載等待
- param 指定介面引數型別,Promise 里接受泛型,傳入 介面回傳資料型別
14. 獲取事項串列的思路及遇到的問題
- 頁面初始化時,執行了 獲取下拉串列 / 獲取事項串列的方法,為什么會發送 兩次 獲取事項串列資料?
- 原因:我給 ionselect 系結了 ionChange 方法,當獲取到下拉串列后,下拉串列就已經發生了改變,執行了 ionChange 方法;而我在初始化中,又寫了一次獲取事項串列的請求,因此發送了兩次請求
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/301557.html
標籤:其他
上一篇:iOS獲取IP地址 --詳細教程




















