ionic3-时间选择器

1、安装 npm install ion-multi-picker --save2、导入模块 import { MultiPickerModule } from 'ion-multi-picker';@NgModule({ imports: [ IonicModule.forRoot(MyApp), **MultiPickerModule** ]3、html文件中引入 <ion-multi-picker item-content [multiPickerColumns]="heightChoose" [(ngModel)]="defaultHeight" (ionChange)="historyPickerChange($event)" [cancelText]="'cancel'" [doneText]="'done'" [resetText]="'reset'" [showReset]="false"></ion-multi-picker>4、数据 constructor() { this.heightChoose = [ { options: [ {text: "0", value: "0"}, {text: "1", value: "1"}, {text: "2", value: "2"}, {text: "3", value: "3"}, {text: "4", value: "4"}, {text: "5", value: "5"}, {text: "6", value: "6"}, {text: "7", value: "7"}, {text: "8", value: "8"}, {text: "9", value: "9"}, {text: "10", value: "10"}, ] }, { options: [ {text: "00", value: "0"}, {text: "01", value: "1"}, {text: "02", value: "2"}, {text: "03", value: "3"}, {text: "04", value: "4"}, {text: "05", value: "5"}, {text: "06", value: "6"}, {text: "07", value: "7"}, {text: "08", value: "8"}, {text: "09", value: "9"}, {text: "10", value: "10"}, // {text: "1-1", value: "1-1", parentVal: "1"}, 指定父级 // {text: "1-2", value: "1-2", parentVal: "2"}, ] }, { options: [ {text: "am", value: "0"}, {text: "pm", value: "1"}, ] } ]; }

May 7, 2019 · 1 min · jiezi

使用ionic4组建ionmodal的时候报错

在使用ionic4的组件ion-modal的时候 按照官网上的事例敲好之后,webstorm会报这样一个错误 大致的意思就是这样的传参格式是不对滴 所以就开始各种尝试 最后采用的这种方式 interface ModalOptions { component: any; componentProps: any;} const modal = await this.modalController.create({ component: ModalPage, componentProps: {value: 123} } as ModalOptions);终于解决了ide的报错了,紧接着在触发这个事件的时候浏览器又抛出一个错误 问我是否添加到ngmodule上的entryComponents,那我就加吧没办法,但是发现加完之后又遇到新的错误。 直接崩溃,初始化都没进去,这可咋整无奈只好去百度最好终于解决了 declarations: [AppComponent, ModalPage], entryComponents: [ModalPage],这个组件是真的调的心累不过谁让你用别人的东西呢,哎,一波三折总算是实现了。

April 29, 2019 · 1 min · jiezi

ionic4+vue+cordova开发混合应用

摘要ionic是可以让我们使用web开发即使来移动应用的框架。ionic4之前,ionic只能和angular搭配使用,ionic4后把ionic抽离成四个版本,@ionic/core,@ionic/angular,@ionic/react,@ionic/vue来满足更多开发者的需求,但是@ionic/vue和@ionic/react还处于内部测试阶段。如果你熟悉angular可以直接使用@ionic/angular开发,但如果你熟悉使用react或vue并且也想使用ionic,可以使用@ionic/core版本,本文就以@ionic/core + vue 来说明这两者如何结合使用。除此之外ionic还引入cordova和capacitor来对把我们代码打包成安卓或ios应用。。https://ionicframework.com使用ionic来搭建我们环境安装ionic脚手架npm install -g ionic安装androd stuiod来编译android代码https://ionicframework.com/docs/installation/android安装xcode来编译ios代码https://ionicframework.com/docs/installation/ios初始化项目 用提供的模版为来测试环境是否已经安装成功ionic start myApp blank在android studio上启动https://ionicframework.com/docs/building/android1, ionic cordova prepare android2, ionic cordova run android -l在xcode上启动1,ionic cordova prepare ios2, ionic cordova run ios -l自己来搭建环境代码可见 https://github.com/gdutjiweijin/webapp适应vue-cli脚手架来搭建vue基础基础代码1, npm install –global vue-cli2, vue init webpack webapp3, cd webapp4, yarn install5, yarn run dev引入ionic@core在index.html上加入<link href=“https://unpkg.com/@ionic/core@4.0.0-beta.13/css/ionic.bundle.css" rel=“stylesheet”><script src=“https://unpkg.com/@ionic/core@4.0.0-beta.13/dist/ionic.js"></script>在main.js加入Vue.config.ignoredElements = [/^ion-/];初始化cordova项目1,cordova create cordovawebapp2,cordova platform add android3,cordova platform add ios把我们代码放入到cordova目录1)打包我们项目代码 npm run build2) 把dist目录代码拷贝到安卓对应目录上cp -r dist/ ./cordovawebapp/platforms/android/app/src/main/assets/www/3)把dist目录代码拷贝到ios对应目录上cp -r dist/ ./cordovawebapp/platforms/ios/www/具体代码可参考https://github.com/gdutjiweij…,效果如下webandroidios

April 18, 2019 · 1 min · jiezi

Ionic4 cordova混合开发的开发调试环境搭建

Ionic4混合开发首选应该是capacitor,但capacitor刚推出不久还不够成熟,所以选择使用传统的cordova方式开发。基本上,Ionic native5和之前版本使用方式上变化不大,但cli有些选项上有些区别。1.创建platform添加android平台ionic cordova platform add android删除android平台ionic cordova platform remove android2.编译ionic项目源文件到www目录只有在Android studio中运行调试ionic项目才需要执行cordova的prepare命令,用于ionic源代码被修改之后,更新Android studio中相应的原生项目。ionic cordova prepare android如果要编译release版本,可以添加参数:ionic cordova prepare android –release –prod3.ionic模拟器或者真机调试以下命令在模拟器上运行app,最好在运行命令之前启动模拟器。ionic cordova emulate android -l注意,原先3.x版本的–consolelogs参数在4.x版本已经不支持,至少在4.1版本不支持,也不知道以后是否会支持。因此,调用console.log等方法输出到浏览器控制台的信息,无法通过ionic输出到命令行。要查看console.log等方法输出到浏览器控制台的信息,目前只能进入模拟器的Extended controls窗口的Bug report选项卡,然后在Bug report data下方窗口复制日志信息到记事本中,然后查找"SystemWebChromeClient"或者"I chromium"定位console信息。这个方法比较麻烦,所以建议采用第4步的方法,使用Android studio调试app。连接真机运行调试app的cli:ionic cordova run android -l4.在Android studio中运行调试ionic项目(真机或者模拟器调试)如果项目之前曾经使用ionic在模拟器和真机上调试运行,Android studio导入项目可能会失败,此时需要用ionic cordova platform remove android删除android平台,然后再次使用ionic cordova platform add android添加。运行Android studio,导入项目platformsandroid,可能会提示配置gradle.wrapper,点击确定。配置过程中,可能会发生build失败,提示gradle版本过高,可以点击自动修改配置。然后还可能出现android sdk版本缺失,可以按照提示下载安装android sdk。点击 Run/Edit configurations菜单,点击+号,添加一个android app配置;在Gerenal选项卡的Module下拉框中选择app,点击确定创建配置。然后可以运行或者调试配置。之后修改ionic源代码,只需要重新执行第2步的ionic cordova prepare命令,就可以同步到android studio项目。调试之前,最好先把模拟器运行起来,运行模拟器之前最好wipe data。在下方的Logcat窗口中,筛选框中输入 I/chromium,可以查看ionic项目中调用console.info/debug等方法输出到浏览器console中的消息。真机调试时比较有用。

March 27, 2019 · 1 min · jiezi

Ionic start(4.x版本)发生bad status code 400错误以及离线创建新项目的解决方法

使用ionic start创建新项目,出现错误:Error: Encountered bad status code (400) forhttps://d2ql0qc7j8u4b2.cloudfront.net/angular-official-tabs.tar.gzThis could mean the server is experiencing difficulties right now–please tryagain later. at Request.req.on.res(C:\Users\xxx\AppData\Roaming\npm\node_modules\ionic\lib\utils\http.js:68:28) at emitOne (events.js:116:13) at Request.emit (events.js:211:7) at Request._emitResponse(C:\Users\xxx\AppData\Roaming\npm\node_modules\ionic\node_modules\superagent\lib\node\index.js:862:8) at ClientRequest.req.once.res(C:\Users\xxx\AppData\Roaming\npm\node_modules\ionic\node_modules\superagent\lib\node\index.js:412:10) at Object.onceWrapper (events.js:315:30) at emitOne (events.js:121:20) at ClientRequest.emit (events.js:211:7) at HTTPParser.parserOnIncomingClient (_http_client.js:543:21)| Downloading and extracting tabs starter (100.00%)然后就一直卡在Downloading and extracting tabs starter不动。直接原因是ionic cli无法下载ionic的template文件angular-official-tabs.tar.gz,从url看这个文件没有放在npm库中,所以使用淘宝npm镜像不能解决这个问题。在网上搜了很多文章都无法解决这个问题。后来在Ionic官网上看到,Ionic新项目模板(starter)作为一个开源项目托管在github上,于是尝试去找到starter template的源码,然后直接从starter template手工创建新项目。在github上搜索ionic-team,发现ionic-team/starters项目,这就是要找的模板源码项目。地址是:https://github.com/ionic-team/starters然后打包下载这个项目的所有源码。根目录下,有三个文件夹angular、ionic-angular和ionic1三个文件夹,显然分别对应三种ionic4项目的starter模板。angular是ionic4.x的angular项目;ionic-angular是ionic2.x/3.x的项目;ionic1是ionic1.x项目。我需要创建的是ionic4.x的项目,所以进入angular文件夹,里面有base和official两个文件夹,从前面错误信息看到下载文件名为angular-official-tabs.tar.gz,所以显然这个模板应该放在official文件夹中。打开official文件夹,里面果然有一个tabs的文件夹,里面有src和e2e两个文件夹,应该就是模板的源文件。但是angular/official/tabs文件夹下没有包含完整的ionic/angular的项目文件,显然,angular.json、package.json文件都没有。然后查找其他文件夹,发现angular/base文件夹下,有这些缺失的文件。于是做以下尝试:a.新建一个文件夹作为我们自己的项目文件夹,假设是testv4。b.把angular/base下的所有文件复制到testv4中。c.把angular/official/tabs文件夹下所有文件复制到testv4中,提示有同名文件,全部覆盖。d.打开testv4/package.json文件,修改前面几行内容为自己的应用名称等: “name”: “ionic-app-base”, “version”: “0.0.0”, “author”: “Ionic Framework”, “homepage”: “https://ionicframework.com/",e.在testv4文件夹上执行npm install,中间可能会出现错误,如果出错则删除node_module文件夹然后再次运行npm install,直到成功。f.执行npm run start,启动浏览器打开localhost:4200,成功。这个方法也可以实现不联网状态下,离线创建Ionic新项目,当然你可以说离线创建新项目没有意义,因为npm install一样需要联网,但如果能够手工建立node_module文件夹,离线创建ionic项目也是有意义的。 ...

March 25, 2019 · 1 min · jiezi

ionic4 ion-reorder-group组件拖拽改变item顺序

2018在ionic项目中用到的组件有很多,这篇文章讲一讲ion-reorder-group这个组件的使用。刚开始我都不知道ionic4中已经封装了拖拽排序的组件,也是主管告诉我的。使用了这个组件的经历告诉我:仔细读官方文档,是没错的!HTML中使用组件,代码如下 <!–一个排序组合一个ion-reorder-group–> <ion-reorder-group [disabled]=“false” (ionItemReorder)=“reorder($event)"> <ion-item color=“tertiary” *ngFor=“let field of fieldList,let i=index”> <ion-label>{{ field.name}}</ion-label> <!–拖拽按钮–> <ion-reorder slot=“end”></ion-reorder> </ion-item> </ion-reorder-group>ionItemReorder绑定reorder事件,是item被拖拽时会被触发的事件,这个事件是ionic绑定在IonReorderGroup组件上的。记得一定要设置disabled属性,不然不会有拖拽按钮出现。export class HomePage {fieldList = [{name:1}];ngOnInit() { let fields = [{name: “1”, type: null, jsonobject: ‘’, level: 0, index: 0, order: true}, {name: “2”, type: null, jsonobject: ‘’, level: 1, index: 0, order: true}, {name: “3”, type: null, jsonobject: ‘’, level: 1, index: 1, order: true}, {name: “4”, type: null, jsonobject: ‘’, level: 2, index: 0, order: true}, {name: “5”, type: null, jsonobject: ‘’, level: 2, index: 1, order: true}, {name: “6”, type: null, jsonobject: ‘’, level: 2, index: 2, order: true} ]; let index = []; // 获取层次的最大值 let maxLevel = 0; fields.forEach((item) => { if (item.level > maxLevel) { maxLevel = item.level; } }); console.log(‘mac’, maxLevel); for (let i = 0; i < maxLevel + 1; i++) { for (var j = 0; j < fields.length; j++) { if (fields[j].level === i) { index.push(j); break; } } } // 添加层次说明 this.fieldList = []; for (let i = 0; i < fields.length; i++) { let j = index.indexOf(i); if (j > -1) { this.fieldList.push({ name: “第” + (j + 1) + ‘层’, type: null, jsonobject: ‘’, level: fields[i].level, index: 0, order: false }); } this.fieldList.push(fields[i]); } if (index.length < fields.length) { this.fieldList.push({ name: “第” + (index.length + 1) + ‘层’, type: null, jsonobject: ‘’, level: maxLevel + 1, index: 0, order: false }); } console.log(this.fieldList);}reorder(ev) { try { if (ev.detail.to === this.fieldList.length) { ev.detail.to -= 1; } // let from = this.fieldList[ev.detail.from]; // let to = this.fieldList[ev.detail.to]; if (ev.detail.from < ev.detail.to) { this.fieldList[ev.detail.from].level = this.fieldList[ev.detail.to].level; console.log(‘aaa’, this.fieldList); // 添加和删除字段 this.fieldList.splice(ev.detail.to + 1, 0, this.fieldList[ev.detail.from]); this.fieldList.splice(ev.detail.from, 1); // this.fieldList.map((item, index) => { // if (item.level === to.level) { // return this.fieldList[index].index = i; // } else if (item.level > from.level) { // return; // } // }); console.log(‘bbb’, this.fieldList); } else if (ev.detail.from > ev.detail.to) { this.fieldList[ev.detail.from].level = this.fieldList[ev.detail.to - 1].level; console.log(‘from’, this.fieldList[ev.detail.from]); console.log(’to’, this.fieldList[ev.detail.to]); this.fieldList.splice(ev.detail.to, 0, this.fieldList[ev.detail.from]); console.log(‘111’, this.fieldList); this.fieldList.splice(ev.detail.from + 1, 1); console.log(‘222’, this.fieldList); } else { ev.detail.complete(); return; } // 层次修改(1、层次是否为空) // let filter = []; // this.fieldList.forEach((item, index) => { // if (item.order === false) { // filter.push({field: item, index: index}); // } // }); // console.log(‘chishi’, filter); // filter.forEach((item, index) => { // item.field.name = ‘第’ + (index + 1) + ‘层’; // this.fieldList[item.index] = item.field; // }); // console.log(‘长度’,filter.length) // // console.log(‘长度’,this.fieldList.length) // if (filter.length < this.fieldList.length/2) { // this.fieldList.push({ // name: “第” + (filter.length + 1) + ‘层’, // type: null, // jsonobject: ‘’, // level: filter.length + 1, // index: 0, // order: false // }); // } let fields = this.fieldList.filter((item) => { return item.order === true; }); console.log(‘chishi’, fields); let index = []; let maxLevel = 0; fields.forEach((item, index, array) => { if (item.level > maxLevel) { maxLevel = item.level; } }); for (let i = 0; i < maxLevel + 1; i++) { for (var j = 0; j < fields.length; j++) { if (fields[j].level === i) { index.push(j); break; } } } console.log(‘index’, index); // 添加层次说明 this.fieldList = []; index.sort(); for (let i = 0; i < fields.length; i++) { let j = index.indexOf(i); if (j > -1) { this.fieldList.push({ name: “第” + (j + 1) + ‘层’, type: null, jsonobject: ‘’, level: fields[i].level, index: 0, order: false }); } this.fieldList.push(fields[i]); } console.log(this.fieldList); if (index.length < fields.length) { this.fieldList.push({ name: “第” + (index.length + 1) + ‘层’, type: null, jsonobject: ‘’, level: maxLevel + 1, index: 0, order: false }); } console.log(this.fieldList); ev.detail.complete(); } catch (e) { return; }}get() { console.log(this.fieldList); let fields=this.fieldList.filter((item)=>{ return item.order==true; }) console.log(fields); var levels=[]; fields.forEach((item,index)=>{ if(levels.indexOf(item.level)===-1){ // 新的level值,加入到levels levels.push(item.level); } }); levels.sort(); console.log(levels); // 改变字段的level和index levels.map((level,index)=>{ let i=0; fields.forEach((item)=>{ if(item.level===level){ item.level=index; item.index=i; i++; } }) }) console.log(fields);}} ...

January 27, 2019 · 3 min · jiezi

Ionic 环境搭建和安装教程

Ionic 环境搭建和安装教程本篇教程基于 Ionic 官方文档编写,希望对初次安装 Ionic 的你们有所帮助。环境搭建在使用 Ionic 框架之前,唯一的前提条件是 Node 和 npm 环境。当然,你同样需要一个代码编辑器。这里推荐使用 VS Code。Node & npm安装 Node.js 和 npm下载(推荐下载 LTS 版本):Node.js安装:双击下载的文件直接安装即可(npm 是和 Node 捆绑安装的,无需单独安装)验证是否安装成功:打开新的cmd窗口,输入:$ node –version$ npm –version出现版本号说明安装成功安装 Ionic CLI直接在 cmd 中输入下方命令安装:$ npm install -g ionic验证是否安装成功:$ ionic -v出现版本号等信息说明安装成功。安装 Cordova直接在 cmd 中输入下方命令安装:$ npm install -g cordova验证是否安装成功:$ cordova -v出现版本号信息说明安装成功。创建项目这里有三种最常见的启动器可供选择,分别是blank启动器,tabs启动器和sidemenu启动器。需要在指定路径中创建项目的话,使用cd进入指定路径即可,默认为当前路径。直接在cmd中输入下方命令安装:$ ionic start myApp tabs耐心等待创建完成,进入对应的文件夹即可看到创建的项目。运行项目在cmd中cd进入到刚才创建的项目文件夹(myApp)$ cd myApp使用ionic serve命令来启动项目$ ionic serve项目启动成功之后会自动在浏览器中打开

January 25, 2019 · 1 min · jiezi

ionic4: Error: read ECONNRESET

ionic4执行命令:ionic cordova build android,直接报以下错误:> ionic integrations enable cordova[INFO] Downloading integration cordovaError: read ECONNRESET at _errnoException (util.js:992:11) at TLSWrap.onread (net.js:618:25)原因在于:在该项目中,cordova平台中并没有android的相关资源。解决方案:执行命令ionic cordova prepare android有时候在执行命令:ionic cordova prepare android,控制台会直接报错: ionic4: Error: connect ETIMEDOUT 13.33.186.65:443下载资源文件超时,这时候需要进行翻墙。然后重新执行以上命令。

December 17, 2018 · 1 min · jiezi

初探Subject and Subscribe (Ionic4 Angular6)

类似的东西很多,但是不得不说大部分资料中的例子不是难以理解就是形而上学,所以我想分享一点自己的代码来帮助更多初学者。起源:我打算做一个弹出登录,里面包含一个注册按钮,点击注册则切换到弹出注册,当然在注册时也能切换回登录。在实现的过程中一路踩过以下的坑:如果将一个component/page应用到modal中,那么这个component/page必须在不低于弹出modal的层级的module.ts文件中的@NgModule的entryComponents部分声明出来,不然会得到一个错误。一个component/page只能在一个module.ts文件中声明调用弹出方法的ts文件必须引用使用到的component/page如果两个ts文件中都同时引用了对方(a.ts import b, b.ts impot a)那么会得到一个循环依赖的警告,这不影响运行,但是看着闹心。所以我要再次修改一下,避免这个警告,最后选择了subject的方案。不要尝试直接复制运行,因为我去掉了和本文无关的部分,比如import { Component } from ‘@angular/core’;这样的语句。首先在某个单例模式的service中加入如下代码:import { Subject, Subscription } from ‘rxjs’;//公有属性switchModel,这是一个可供订阅的主题@Injectable({ providedIn: ‘root’})export class SiteService { public switchModel: Subject<Object> = new Subject<Object>();}为了解决问题4,所以弹出的行为将仅在app.component上发生import { ModalController } from ‘@ionic/angular’;import { SiteService } from ‘../services/site/site.service’; //自行替换为声明了subject的serviceimport { LoginComponent } from ‘../login/login.component’; //自行替换为你要弹出的内容1import { SignupComponent } from ‘../signup/signup.component’; //自行替换为你要弹出的内容2/如果有的话你可以添加更多的内容注意确认它们被正确的声明在entryComponents部分对于app.component.ts,其对应的module必然是app.module.ts/export class AppComponent { constructor( private modalController: ModalController, private siteService: SiteService ){ this.siteService.switchModel.subscribe(option => { this._switchModel(option); }); } private _switchModel(option) { let component = null; switch(option.componentName) { case ‘LoginComponent’: component = LoginComponent; break; case ‘SignupComponent’: component = SignupComponent; break; case ‘’: //如果没有指定component那就是直接关闭咯,这是为了在component内部能省掉引用ModalController和关闭modal的代码 break; default: return; //这件事和我无关,跳过。防止对其它subscriber负责的component重复处理 } this.modalController.dismiss().then(() => { this.modalController.create({ component: component, componentProps: option.params || null }).then(modal => modal.present()); }); }}然后在LoginComponent为注册按钮添加一个事件,SignupComponent做类似的处理import { SiteService } from ‘../services/site/site.service’;export class LoginComponent implements OnInit { doSwitch() { this.siteService.switchModel.next({ componentName: ‘SignupComponent’ }); } cancel() { this.siteService.switchModel.next({ componentName: ’’ }); }}逻辑描述:LoginComponent调用Subject的next方法同时传递数据,这样Subject就会将该数据通知到订阅者(AppComponent订阅了这个subject),AppComponent在得到Subject更新的消息时会根据最新的消息做出适当的处理。理论上来说,我们可以创建一个全局的主题,每个订阅者都可以通过消息的数据类型或其它特征决定自己如何处理,但是个人还是喜欢定制主题从而减少订阅。刚接触Angular6不久,不管是我这个想法本身有错误还是解决的方式有问题都请拍砖不要客气,只求大侠的砖头上绘制一下示例代码,不胜感激。 ...

November 7, 2018 · 1 min · jiezi