# ionic3-App **Repository Path**: 1270731118/ionic3-App ## Basic Information - **Project Name**: ionic3-App - **Description**: 用ionic3 做个app 练习一下; - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: dev - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2018-08-30 - **Last Updated**: 2021-11-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 安装离子 ``` npm install -g ionic ``` ### 启动应用程序 ``` ionic start myApp tabs ``` ### 运行你的App ``` cd myApp ionic serve ``` ***** ### 新建一个ionicUI 页面 ``` ionic g page ionicUI ``` ### 添加到tabs栏 *********** ### 新建一个ionicUI 页面 ``` ionic g component ui ``` 并在ionicUI页面上引入使用 ****** ### 页面修改为懒加载(组件报错) ### ******* ### 组件修改为懒加载 ************* ### 引入轮播图 并开启自动轮播 >标签ion-slides上的属性配置 pager loop="true" autoplay="3000" > >page表示轮播图开启显示当前页码,loop="true"表示开启循环播放 autoplay="3000"表示每个3秒钟自动播放一次。 ******* ### 引入tab 栏segment 并ts 设定默认选中第一个tab ***** ### 在android 手机上运行测试 参考:http://www.cnblogs.com/wangpinzhou/articles/8948482.html http://www.cnblogs.com/wangpinzhou/articles/8949923.html ``` cordova platform add android cordova run android // 环境安装总报错是建议重启电脑换时间段再试; ``` >cordova run android命令等于cordova build android(生成apk)和adb install -r apk路径(安装apk到真机) >如果代码有修改,记得先执行ionic serve或者使用ionic cordova run android *************** ###生成app图标 splash 图片 将 resources文件夹下的 icon 和 splash 图标替换; 格式png/ psd ``` $ ionic cordova resources android --icon $ ionic cordova resources android --splash 或全部生成 ionic cordova resources ``` 第一次 生成 有提示 Email 及密码; 在ionic 官网注册免费版即可; 网址https://dashboard.ionicframework.com/apps ************ ### 打包app 并签名 (签名后才可以安装手机使用) ### 打包 ``` ionic cordova build android --release ``` (如果这条命令有问题,可以去掉–release然后debug编译,编译完成Dos会显示apk目录位置) Build Success! 说明成功打包;命令行结束会提示你apk的生成位置。 如果报错,根据报错情况,下载对应的sdk 包 ; ### 签名 [Android应用程序签名(或重新签名)详解](https://blog.csdn.net/yu17310133443/article/details/52701492) 打包后文件必须签名才可安装使用; 在JDK目录下的bin文件夹下有 keytool.exe和jarsigner.exe文件,这两个程序用于给APK签名,签名以后即可发布安装; 配置环境变量;见前面的链接 找到 打包后的app 文件夹,运行命令行; ``` keytool -genkey -v -keystore dome.keystore -alias dome.keystore -keyalg RSA -validity 20000 ``` ``` /*说明:-genkey 产生密钥 -alias demo.keystore 别名 demo.keystore -keyalg RSA 使用RSA算法对签名加密 -validity 40000 有效期限4000天 -keystore demo.keystore */ ``` ``` jarsigner -verbose -keystore dome.keystore -signedjar notepad_signed.apk(新文件名) notepad.apk(旧文件名) dome.keystore ``` ``` /*说明:-verbose 输出签名的详细信息 -keystore demo.keystore 密钥库位置 -signedjar demor_signed.apk demo.apk demo.keystore 正式签名,三个参数中依次为签名后产生的文件demo_signed,要签名的文件demo.apk和密钥库demo.keystore.*/ ``` ************* ### 调用 原生 Camera 参考官方文档: ##### 安装Cordova and Ionic Native plugins: ``` $ ionic cordova plugin add cordova-plugin-camera $ npm install --save @ionic-native/camera ``` ##### 增加插件(plugin)到项目应用模块 app.module.ts ``` import { Camera } from '@ionic-native/camera'; ... @NgModule({ ... providers: [ ... Camera ... ] ... }) export class AppModule { } ``` ##### Camera 支持的平台(platforms) > - Android > - Browser > - iOS > - Windows ``` // 这里注意;在chrome 打开时用 ionic cordova platform add browser ionic cordova run browser ``` 将图片存为 base64 并用*ngFor渲染到 html 上的轮播图slides中; 增加一个clear Button ; 没有图片时 用*ngIf *ngIf="images.length>'0'" 隐藏slides; *********** ## 页面跳转的方式 ### (1)NavController 1.在first.ts中,先导入NavController,再注入到构造器中。 ``` import { NavController } from 'ionic-angular'; class FirstPage { constructor(public navCtrl: NavController) { } } ``` 2.然后导入要跳转到的页面,再定义跳转按钮触发的跳转方法,调用push方法跳转 ``` import { SecondPage } from '../second/second'; class FirstPage { constructor(public navCtrl: NavController) { } goSecondPage(){ this.navCtrl.push(SecondPage); } } ``` 3.在模板中写上按钮绑定事件: ``` ``` > 报错 No component factory found for “......” **解决办法:在app.module.ts 中引入新模块,并在declarations,entryComponents里面添加新模块即可。** ***** #### 改为懒加载 app.module.ts中删除引入; ``` this.navCtrl.push("SecondPage"); //页面增加双引号; ``` ******** ###(2)[navPush]指令 同样,先导入SecondPage,然后定义一个变量,将SecondPage赋值给它。然后在模板中,向button添加[navPush]属性,绑定pushPage,实现跳转 ``` import { SecondPage } from '../second/second'; class FirstPage { pushPage; constructor(){ this.pushPage = SecondPage; // 使用懒加载时app.module.ts不用引入页面;这里改为加双引号: "SecondPage" } } 模板中: ``` *********** ## 将参数传递给下一个页面 ### (1)NavController 为push函数添加第二个参数(发送页面) 假设我们要为TestPage传入一个标题,用来显示到页面上,我们为push方法传入一个对象。 ``` pushTestPage(){ this.navCtrl.push(TestPage,{ title:'没有人可以比我帅' }); } ``` 引入NavParam并使用(接受页面) 利用NavParams的get方法,可以将传进来的页面参数读取出来。 切换到 test.ts,完成三个步骤 1.引入NavParams并,并在构造函数添加注入语句 2.为TestPage类添加title属性,读取参数并赋给title 3.将title输出到模板中 - 文件 test.ts ``` import { Component } from '@angular/core' import { NavParams } from 'ionic-angular' //step1 @Component({ selector: 'page-test', templateUrl:'./test.html' }) export class TestPage { title:string; //step2 constructor(public params:NavParams){ //step1 this.title=this.params.get('title'); //step2 } } ``` ### (2)[navPush]指令 ``` ``` ## 另一种页面跳转 ModalController:(类似模态框) modal:一个覆盖整个屏幕的overlay,可认为是一个特殊的page。Modals不可重用。当一个modal被关闭(或覆盖)后,它将被毁灭(从堆栈中去除)。 比如,qq登录,你登录成功后,即使你隐藏了页面的返回按钮,安卓手机也是可以使用返回键跳回上一个页面的,那一按返回又退回了登录页面,这显然不是我们想要的,我们需要在登录后销毁页面。 ``` import { ModalController } from 'ionic-angular'; import { SecondPage } from '../second/second'; @Component(...) class FirstPage { constructor(public modalCtrl: ModalController) {} presentSecondPage () { let SecondPage = this.modalCtrl.create("SecondPage"); SecondPage.present(); } } ``` 同样在模板中用button触发该方法。 #### 返回上一页面 ` this.navCtrl.pop();` ************* ##引入vconsole 方便手机调试(腾讯出品) ``` / 在 main.ts 引入vconsole 方便手机调试 入口main.ts引入可以全局使用; import VConsole from "vconsole"; let vConsole = new VConsole(); ``` ********* ## ionic cordova run android 运行报错处理 ; 原因分析 :安装扫描插件后报错; ``` FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:processDebugManifest'. > Manifest merger failed with multiple errors, see logs * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. * Get more help at https://help.gradle.org BUILD FAILED in 2s at ChildProcess.whenDone (C:\Users\wpz\Desktop\app\myapp\platforms\android\c ordova\node_modules\cordova-common\src\superspawn.js:169:23) at ChildProcess.emit (events.js:159:13) ``` 处理过程如下;重装android 平台 ``` cordova platform rm android cordova platform add android ``` **移除安装的包;** ``` $ ionic cordova plugin add cordova-plugin-qrscanner $ npm install --save @ionic-native/qr-scanner ``` ************ ## 引入扫一扫原生插件 ; 参考链接:https://www.jianshu.com/p/45f8b44b9a42 ``` app.module.ts import { QRScanner } from "@ionic-native/qr-scanner"; providers: [ ... QRScanner ] ``` ``` scan.ts scan.scss scan.html ******* variables.scss //背景白屏解决 ion-app.cameraView, ion-app.cameraView ion-content, ion-app.cameraView .nav-decor { background: transparent none !important; .tabbar.show-tabbar { opacity: 0; } } ``` ### 封装一个公共组件 进度条 ``` ionic g component progress-bar ``` ### 使用segment + swiper 4.0 插件 做 滑动菜单; 参考菜单:https://blog.csdn.net/dan_2017/article/details/78774034 > 关注如何引入第三方库 ``` index.html ``` ``` ts import { Component, ViewChild } from '@angular/core'; import { NavController, Slides, IonicPage} from 'ionic-angular'; //声明一个Swiper对象,是全局的引用 declare var Swiper; //引入******** ``` ``` //当页面加载的时候触发,只触发一次,当有缓存的的时候,打开页面时不在加载 ionViewDidLoad() { this.initSwiper(); } //初始化swiper initSwiper() { this.swiper = new Swiper('.pageMenuSlides .swiper-container', { .....参swiper 设置 }); } ``` ## 安装 cordova-plugin-statusbar 状态栏插件; 安装命令 ``` cordova plugin add cordova-plugin-statusbar ``` 消除控制台报警; ### 增加两个页面做投票 > this.navCtrl.push("nextPage")练习页面跳转; --加引号是,懒加载方式 > > ion-grid ion-row ion-col col-6 练习栅格布局; > > *ngFor="let item of list;index as i;" 练习数据渲染; > > 引用进度条组件progress-bar .. ---需要在module.ts 引入; ## 使用ionic 的storage 做一个存储的搜索记录功能; 类似localstorage; ``` //app.module.ts import { IonicStorageModule } from "@ionic/storage"; // 本地存储; @NgModule({ ... imports: [ IonicStorageModule.forRoot(), //本地存储 ], ... ``` 页面中使用 ``` import { Storage } from '@ionic/storage'; // 本地存储 存搜索记录 ... searchdata: string = ''; // 双向绑定数据 [(ngModel)] searchHistoryList: Array; // 历史数据 constructor( private storage: Storage, // 本地存储 存搜索记录 ) { } ngOnInit() { // 初始化,获取本地的数据; this.storage.get('searchHistoryList').then((val) => { if (!val) { // 没有数据时设定为 []; this.searchHistoryList = [] } else { this.searchHistoryList = val; } }) }; search() { // 点searchBtn 时记录 数据 this.searchdata = this.searchdata.trim(); // 去除两边的空格符; if (!this.searchdata) { // 空数据时 实用 toast 提示 输入; let toast = this.toastCtrl.create({ message: '请输入搜索值', duration: 1000 }); toast.present(); } else { for (let i = 0; i < this.searchHistoryList.length; i++) { // 判断是否重复 先删 再加在第一位; let element = this.searchHistoryList[i]; if (element === this.searchdata) { this.searchHistoryList.splice(i, 1); } } this.searchHistoryList.unshift(this.searchdata); this.storage.set('searchHistoryList', this.searchHistoryList); // console.log(this.searchHistoryList); } } clearbtn() { // 清除记录 this.storage.remove('searchHistoryList'); // 注意与clear() 方法的区别 this.searchHistoryList = []; // 页面也清除; } gotoInput(val) { //点击记录时 填入inputsearch this.searchdata = val; } ``` ## 使用ionic的 ion-select ui 组件 ,并做一个简单的联动效果; ``` 单选 // placeholder 默认显示值 {{item.examineClassify}} 上面单选的联动加多选 {{item.enrollBatch}} {{item.enrollBatch}}
{{item.enrollStartTime}}
{{item.enrollEndTime}}
``` ``` export class SelectPage { danxian: string; // 这个数据可用于返回后台 liandong: string; // 这个数据可用于返回后台 selectdate: Array = [] mock: Array = [ // 联动的全部数据 { examineClassify: "考试分类1", "examineClassifyId": "考试分类id", "enrollBatchList": [ // 联动的数据 { "enrollBatch": "报名批次1111111", "enrollBatchId": "报名批次id1", "enrollStartTime": "2017/12/01 16:30", "enrollEndTime": "2017/12/01 16:30", "limitNumber": "50", "enrollNumber": "21", }, { "enrollBatch": "报名批次1111111111112", "enrollBatchId": "报名批次id22", "enrollStartTime": "2017/12/01 16:30", "enrollEndTime": "2017/12/01 16:30", "limitNumber": "50", "enrollNumber": "21", } ] }, { examineClassify: "考试分类2", "examineClassifyId": "考试分类id", "enrollBatchList": [ { "enrollBatch": "报名批次222222221", "enrollBatchId": "报名批次id1", "enrollStartTime": "2017/12/01 16:30", "enrollEndTime": "2017/12/01 16:30", "limitNumber": "50", "enrollNumber": "21", }, { "enrollBatch": "报名批次222222222222", "enrollBatchId": "报名批次id22", "enrollStartTime": "2017/12/01 16:30", "enrollEndTime": "2017/12/01 16:30", "limitNumber": "50", "enrollNumber": "21", }, { "enrollBatch": "报名批次222222221", "enrollBatchId": "报名批次id1", "enrollStartTime": "2017/12/01 16:30", "enrollEndTime": "2017/12/01 16:30", "limitNumber": "50", "enrollNumber": "21", }, { "enrollBatch": "报名批次222222222222", "enrollBatchId": "报名批次id22", "enrollStartTime": "2017/12/01 16:30", "enrollEndTime": "2017/12/01 16:30", "limitNumber": "50", "enrollNumber": "21", } ] } ] mock2: Array = []; // 联动的数据 constructor(public navCtrl: NavController, public navParams: NavParams) { } change(val) { // 点击 选项是 生成 关联项目的 数据; console.log(val); this.mock2 = val.enrollBatchList; } change2(val) { console.log(val); this.selectdate = val; } } ```