ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Ionic/Vue3 北京政务App 问题记录(1)

2021-09-19 15:00:18  阅读:208  来源: 互联网

标签:vue ionic App 接口 列表 Vue3 Ionic 下拉框 路由


目录

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 文件夹中的全局地址

  • 区分三种接口类型:
  1. 模拟接口,即通过 Rap2 或其他接口平台构建的模拟接口,在提供接口文档之后,前端负责编写
  2. 接口平台地址,即通过 token/interface/run.action 等访问接口数据,后端编写,在 Network 中,通过 run 过滤此类请求
  3. 自定义接口地址,即通过 getData.vm 这种访问接口数据

  • 在 utils 文件夹中,包含 接口路径拼接 / axios设置 / 封装http请求 / 配置 token 等内容
  • 在 service 文件夹中,配置 具体业务的 http请求

  • 以上图 事件列表 为例:
  1. 模拟接口复制 Rap2模拟接口平台中 写的地址即可
  2. 后端接口平台复制 interfaceID 字段即可
  3. 自定义开发接口复制 getData.vm 这种带.vm 的字段即可
  4. 在 useApi 中,控制当前使用哪种接口 

  • 注意:后端接口平台接口,需要配置 token,get/post 请求都需要


  • 可以直接在 service 下的模块中,直接定义 接口所需参数类型 / 接口回复数据类型,也可以把这两个定义在 types 下的模块中

  •  接口请求模板定义举例:

  • 上述示例说明如下:
  1. 上面使用了 get/post 两种请求,都已经在 utils 里封装了,使用只有方法名的不同,没有别的区别
  2. 方法内部传入了当前使用的接口名,接口所需参数,是否显示加载等待
  3. param 指定接口参数类型,Promise 里接受泛型,传入 接口返回数据类型

14. 获取事项列表的思路及遇到的问题

  • 页面初始化时,执行了 获取下拉列表 / 获取事项列表的方法,为什么会发送 两次 获取事项列表数据?
  • 原因:我给 ionselect 绑定了 ionChange 方法,当获取到下拉列表后,下拉列表就已经发生了改变,执行了 ionChange 方法;而我在初始化中,又写了一次获取事项列表的请求,因此发送了两次请求

标签:vue,ionic,App,接口,列表,Vue3,Ionic,下拉框,路由
来源: https://blog.csdn.net/Lyrelion/article/details/120361901

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有