ionic常用命令记录 - 前端客 - 博客园

mikel阅读(957)

来源: ionic常用命令记录 – 前端客 – 博客园

npm install -g ionic

//安装ionic

ionic lib update

//更新www/lib/ionic 目录的文件,如有项目中有bower,此命令会运行bower update ionic, 否则则会从CDN上下载文件并替换。

ionic start your_app_name [template]

//创建一个项目,其中template可以是内置的模板类型:blank/sidemenu/tabs(default)三种,也可以是github地址:https://github.com/driftyco/ionic-starter-tabs (这叫ionoic-starter),或者是Codepen starter地址:http://codepen.io/ionic/pen/odqCz

//可选的参数: -a your_app_name -i com.yourcompany.youapp -w (不要用cordova)

ionic serve [options]

//启动一个本地的server,在浏览器中打开,并可监视文件变化,随时刷新浏览器。// 可以在主目录下的ionic.project文件的watchPatterns中配置要监视的文件夹。如:

{
  "name": "myApp",
  "app_id": "",
  "watchPatterns": [
    "www/js/*",
    "!www/css/**/*"
  ]
}
ionic setup sass

//增加一个watchPatterns到ionic.project中。

ionic serve --lab

//在浏览器中打开ios和andriod的显示界面

ionic serv --address 68.52.96.10

//指明一个外部的ip地址,可以让外部用户查看。

ionic platform ios android

//添加目标平台

ionic build ios

//构建ios平台

ionic emulate ios [options]

//使用模拟器模拟ios

//该命令等价于: ionic run ios –emulator

ionic run ios [options]

//使用设备运行应用,如果无设备可用将自动使用模拟器。

//options的选项包括:

-l livereload, 实时刷新变化。

-c 打印app里的console

-s 打印设备的console

-p 指定设备的端口

-i 指定livereload的重刷端口

Debug|–release

//当处于livereload模式时,使用r重启客户端,使用 g your_url 跳转到指定url, 使用c启动或关闭console,使用s启动或关闭设备的console, 使用q退出。

ionic resources [--splash] [--icon]

//ionic会将本地的资源文件(支持png、psd和ai,尺寸越大越好)上传到它的服务器进行处理。本地资源文件放到resources目录下,如果是某个平台单独的资源,可以放到对应平台下,比如resources/Android/icon.png,这样就会把处理好的资源自动放到该平台下,而不是所有平台都放。

ionic upload

//该命令上传自己的项目到ionic服务器,上传完成后会有一个项目编号。

//安装Ionic View的app,使用ionic的账号登录进去,可以查看自己的项目。

//也可以直接登录ionic的app网站,下载其他平台的app,比如安卓。

ionic info

//查看系统情况

ionic browser add crosswalk

//安卓自带浏览器性能不好,可以强行安装一个壳,这将安装一个Chromium内核。

ionic browser list

//查看可用的browser

ionic browser revert android

// 删除安装的browser

Ionic2:创建App启动页滑动欢迎界面 - K_Men的博客 - 博客频道 - CSDN.NET

mikel阅读(829)

摘要: 每个有逼格的App在第一次启动时都有一个欢迎界面,通常是几个单页面或者带动画的单页面滑动到最后一页有个启动的按钮,本文将使用Ionic2来创建,So easy!效果如下,图片来自网络本文例子和上图稍有不同,主要功能如下:每滑动一下展示一张全屏图片;滑动到最后一页才出现启动按钮;欢迎界面只在第一次安装启动时出现。下面就让我们一步一步实现这个功能:1.创建应

来源: Ionic2:创建App启动页滑动欢迎界面 – K_Men的博客 – 博客频道 – CSDN.NET

摘要: 每个有逼格的App在第一次启动时都有一个欢迎界面,通常是几个单页面或者带动画的单页面滑动到最后一页有个启动的按钮,本文将使用Ionic2来创建,So easy!

效果如下,图片来自网络

本文例子和上图稍有不同,主要功能如下:

  • 每滑动一下展示一张全屏图片;
  • 滑动到最后一页才出现启动按钮;
  • 欢迎界面只在第一次安装启动时出现。

下面就让我们一步一步实现这个功能:

1.创建应用:

使用Ionic2创建应用非常简单,只需在V1的命令后跟上–v2即可,如下:

ionic start ionic2-welcome --v2

2.创建Component

使用命令行创建页面或者自行在创建文件

ionic g page welcome

然后打开应用跟组件app.component.ts,导入组件,app.module.ts也一样并配置


import { WelcomePage } from '../pages/welcome/welcome';

3.创建模板文件welcome.html

<ion-slides pager>
 
  <ion-slide>
    <img src="images/slide1.png" />
  </ion-slide>
 
  <ion-slide>
    <img src="images/slide2.png" />
  </ion-slide>
 
  <ion-slide>
    <img src="images/slide3.png" />
  </ion-slide>
 
  <ion-slide>
    <ion-row>
        <ion-col>
            <img src="images/slide4.png" />
        </ion-col>
    </ion-row>
    <ion-row>
        <ion-col>
            <button light (click)="goToHome()">立即启动</button>
        </ion-col>
    </ion-row>
  </ion-slide>
 
</ion-slides>

通过ionic自带的ion-slides可以很方便的创建一个欢迎页面
4.创建welcome.scss

ion-slide {
    background-color: #eeeeee;
}
 
ion-slide img {
    height: 70vh !important;
    width: auto !important;
}

5.创建welcome.ts

import { Component } from '@angular/core';
import {NavController} from 'ionic-angular';
import {HomePage} from '../home/home';  
 
@Component({
    templateUrl: 'welcome.html'
})
export class WelcomePage {
    constructor(public navCtr: NavController){ 
    }
 
    goToHome(){
        this.navCtr.setRoot(HomePage);
    }
}

6.在根组件导入welcome组件,编辑app.moudle.ts

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from 'ionic-native';
import { HomePage } from '../pages/home/home';
import { WelcomePage } from '../pages/welcome/welcome';
import { Storage } from '@ionic/storage';
@Component({
  template: `<ion-nav &#91;root&#93;="rootPage"></ion-nav>`,
   
})
export class MyApp { 
  rootPage: any; 

  constructor(platform: Platform, public storage: Storage) {

    this.storage.get('firstIn').then((result) => { 
             
      if(result){  
        this.rootPage = HomePage; 
      } 
      else{
        this.storage.set('firstIn', true);
        this.rootPage = WelcomePage;
      }
            
    }
    );  

  	
 
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      StatusBar.styleDefault(); 
    });
  } 
}

这里判断是否是第一次开启app采用的是native的storage组件,第一次启动会写入storage一个变量firstIn,下次启动时如果读取到这个变量则直接跳过欢迎页,注意ionic2开始storage默认使用的是IndexedDB,而不是LocalStorage

Cordova webapp实战开发:(2)认识一下Cordova - 周 金根 - 博客园

mikel阅读(902)

来源: Cordova webapp实战开发:(2)认识一下Cordova – 周 金根 – 博客园

如何封装一个浏览器成webapp?

在群里,有个朋友问了一个问题“如何封装一个浏览器成webapp?”

每个手机就像电脑一样,都带着自己的操作系统。如果你愿意,你可以从头写一个浏览器,把浏览地址隐藏了,这就像你的一个app了,对吧。当然,我们自己写浏览器,这也太难了,所以我们肯定不是这么做的。其实,我们只是基于各种手机上Web浏览器内核去做手脚,而Js是Web开发的最佳语言,至于如何封装成一个Web app?说实话,我也没有真正去探究过是如何去做的,因为我对Andorid和iOS原生开发也不熟悉,最主要是现在也没有时间去研究这些了,但是我告诉你的是,通过一些移动开发框架,你只需要专注于写你的前端代码,然后通过一个开发框架的黑盒的操作,编译后就成了一个可以安装的App了。是否很神奇呢:)

不用管它有多神奇了,看看下面这张图,先从架构上总体了解到这个层次就行了。最上面是H5,中间是Web前端框架,以及移动开发框架的API。如果你需要调用手机原生的功能,例如摄像头、录音等,这些工作会由移动开发框架去做,你只需要了解这种框架是如何工作的即可。学会如何使用摄像头,就知道如何使用录音了,举一反三。

移动开发框架

在准备使用Web App重新编写之前的原生APP前,工信部的人有点怀疑,因为大家都听说HTML5的移动应用太慢,体验太差,这万一做完不行怎么办?我解释了一下,发现没用,所以索性自己就动工了。我想告诉大家的是,只要你不是对性能要求特别高,例如画图之类的App,其实很多应用都可以使用HTML5来做的。昨天我还在一个材料计算器群里和群主说,可以使用Web App方式来做,免得群里的人都在等着你的iOS版本出来。群主说他尝试过,但是每次计算要等好几秒,还给我举例说见过12306订火车票的App吗?

我想告诉大家的就是,这里存在很多偏见,因为以前手机性能差,H5也没有这么普及,所以体验不好、效率差强人意,但是现在HTML5越来越好,移动硬件性能也越来越强,很多应用都已悄然上演了混合式开发的方式。你看看支付宝、淘宝,其实手机App里面都有Web的影子,你发现了吗?

因为移动设备的普及,App也越来越多,早就了高价收购Andorid和iOS开发者的现象,而现在因为Web App的兴起,又造价了Web前端的高价,虽不是主要原因,但肯定是其中一个原因,所以学习移动开发会提升你的身价,当然前提是你真的一个人能搞定。

以前我们做桌面或Web应用一样,语言和框架都有很多可以选择,那做移动开发框架呢?依然我们有很多选择,只是我真的很长时间或者没有太多时间专注学习每一个,所以下面只能简单介绍一下了。

PhoneGap

PhoneGap是一款开源的手机应用开发平台,它仅仅只用HTML和JavaScript语言就可以制作出能在多个移动设备上运行的应用。 PhoneGap将移动设备本身提供的复杂的API进行了抽象和简化,提供了一系列丰富的API供开发者调用,只要你会HTML和JavaScript或 者Java语言,就可以利用PhoneGap提供的API去调用各种功能,制作出在各种手机平台(iPhone,Android ,BlackBerry,Symbian,Palm,Window Phone)上运行的应用。目前phonegap获得Apple,IBM,NOKIA,palm等众多公司的支持。简单来说使用PhoneGap就是使用HTML,JavaScript和CSS来开发程序,最终通过PhoneGap可以产生对应版本的native 程序。

IONIC

IONIC 是目前最有潜力的一款HTML5手机应用开发框架,它提供了很多UI组件来帮助开发者开发强大的应用。它使用JavaScript MVVM框架和 AngularJS来增强应用。提供数据的双向绑定,使用它成为Web和移动开发者的共同选择。即将发布的AngularJS 2.0将会专注于移动开发,相信IONIC一定会取得不错的成就 。

IONIC的开发团队将尽快开发出一种通过IONIC creator提供开发者快速创建IONIC应用的方式。我们将很快就会看到一个支持拖拉功能的可视化开发工具,几分钟内开发一个app将不再只是吹xx。

这里要说一AngularJS,这个框架我在前两年看过,我喜欢这种MVVM框架的东东,当时只是简单学习了一下,如果有时间我可能会把现在急于JQueryMobile和没有框架的Js改为急于IONIC来编写。

……

除了以上一个我实际做过,一个我想学的之外,还有很多Web App开发框架,国内现在网上也能收到好几个,不过我都没怎么用过,这里也就不做介绍了,总之这一小段就是告诉,开发框架有很多,基于我以前自己也做框架(OpenExpressApp)的经验,任何东西都不可能完美,所以我们不要太苛求了,如果你喜欢这个框架,那就去学习,学习之后如果觉得可行,那就找个小项目试试,如果试后觉得不错,那就多花些功夫做好,仅此而已。 

大家看此系列blog就知道,我后续所有的博文都是围绕第一个来介绍,所以如果你对第一个不感兴趣,那么可能这个系列就不适合你了,当然,你以后也可以择取系列中一些单独篇章来学习你所需要的。

cordova与phonegap有什么关系?

phoengap

如果能了解一个框架的兴起还是一件比较有趣的事。08年一次ios开发者大会上来自Nitobi软件公司的几个家伙突发奇想,提出一个想法,想做一个工具来弥补web和ios开发之间的不足,并提出 Bridging the gap between the web and the iPhone sdk。一开始的目标并不是很大,但是做到了现在的written once,run everywhere。我们很多人做事其实也应该这样,一开始不要把目标弄得那么大,跳一步能够上就好,敏捷个人的形成也是这样,一开始只是分享而已,随着分享越多才成为了一个帮助有成长意识的人去认识自我管理自我的成长体系。如果一下子目标太大,你会因为难以实现而给自己找理由,这样到头来你什么都没有。

09年他们推出Android adk和blackberry sdk,成了移动开发者的福音,就连ibm也加入进来。phonegap继续成长,在2011年10月,整个Nitobi团队被adobe收购,PhoneGap的项目主管Brian LeRoux指出开源PhoneGap的决定在Adobe收购Nitobi之前就做出了,由于Adobe现在拥有PhoneGap商标,他们不得不换个名字,第一个选中的名字是Callback,毫无创意,因此再改一次,产品现在叫Apache Cordova。随后adobe把 phonegap送给了apache软件基金会,接着apache把phonegap改名为cordova,cordova是Nitobi团队当时坐落的街道名称,用此名来纪念Nitobi团队的贡献。

所以Apache Cordova是从PhoneGap中抽出的核心代码,是驱动PhoneGap的核心引擎,你看着两个官网风格多差不多。

Cordova

我们后续的所有文章和代码都是基于Cordova的,如果有谁知道Phonegap和Cordova的具体差异在哪里,可以回复补充一下。

谁在使用PhoneGap

诚实的说,上面的都是在官网看到放上去的,至于真的用的怎么样就不知道了。这样说起来感觉我很不负责似的,所以在本系列第一盘中我就告诉了大家,我自己做的敏捷个人App和掌中广材App就是用Cordova做的,而且都已经在各大Andorid市场和iOS AppStore上架了。

支持平台

我相信很多人选择这种方式,而不是原生,很看重的一点就是跨平台,也就是一次代码,多个平台复用。没错,我现在主要在Andorid上开发,然后把www目录下的所有文件都拷贝到iOS目录下,然后就OK了。至于你说,wp系列的复用起来如何呢?很抱歉,我没有wp的手机,没有试过。之所以还没有试过,是因为这类客户群数量还比较少,所以我们也没有投入精力去做这个部分,这不是技术问题,而是产品对技术的定位方面决定的。

但是,从官网我们可以看到,它对平台的支持是很不错的,我也相信它们能做到iOS和Andorid复用,就能做到其他平台复用,因为从架构原理来看是一样的。

 

预习作业

真是晕?竟然还有预习作业,弄得我就像老师一样。呵呵,不过还真有很多人叫我周老师,可能是因为我把敏捷个人的博客当做练习变成习惯了,所以在本篇结尾时,希望大家在轻松读完本篇之后,做一下几个练习,遇到问题呢可以回复,这样我在写下一篇的时候呢就可以帮你解决问题了,这既锻炼你的学习能力,也能够更及时更好的解决你的问题。

  1. 去官网下载Cordova框架(提醒,不是Phonegap)
  2. 自己建立一个Andorid项目,并在手机上调试安装成功
  3. 在iOS上也调试安装一下。(如果没有iOS环境,那就略过吧) 

ionic入门教程第十九课-ionic路由详解(state、route、resolve) - 小虎Oni - 博客频道 - CSDN.NET

mikel阅读(1025)

今天好好的跟大家讲讲ionic的路由配置。问到的朋友有点多,因为这个内容比较多,所以我一直想等我多了解一些再出关于路由的教程。但是有些很简单的也有朋友不理解,所以我就提前出了这篇教程。希望能对大家有点帮助,关于我遗漏的部分,后面再发教程补充吧。但是基本的内容,简单的应用,应该这篇教程里面都会提到了。首先我们还是从tabs类型的新建项目来学习(这个项目真的很厉害,大家可以花时间好

来源: ionic入门教程第十九课-ionic路由详解(state、route、resolve) – 小虎Oni – 博客频道 – CSDN.NET

今天好好的跟大家讲讲ionic的路由配置。

问到的朋友有点多,因为这个内容比较多,所以我一直想等我多了解一些再出关于路由的教程。

但是有些很简单的也有朋友不理解,所以我就提前出了这篇教程。

希望能对大家有点帮助,关于我遗漏的部分,后面再发教程补充吧。

但是基本的内容,简单的应用,应该这篇教程里面都会提到了。

首先我们还是从tabs类型的新建项目来学习(这个项目真的很厉害,大家可以花时间好好看看)。

我们就按照代码的启动流程开始看这个路由吧。

使用的ide是webstorm9.0.3

首先让我们运行这个项目,右键点击index.html,选择用浏览器运行,选择谷歌浏览器。

在打开的谷歌浏览器中打开开发人员工具(快捷键F12),

然后选择手机调试模式(开发人员工具栏,放大镜旁边那个按钮,可能是手机样子或者别的,版本问题,我忘记图标长什么样子了),

选择iphone6。然后刷新。重新适配界面。(只是为了比较好看而已)

既然这节课是说路由,那最开始我们最先要关注的就是

http://localhost:63342/routeDemo/www/index.html#/tab/dash

为什么会访问这个地址呢?#tab/dash这个就是路由,但是为什么访问的是这个路由,又是什么意思,怎么定义的呢?

首先我们做一个操作,在地址栏里面访问http://localhost:63342/routeDemo/www/就是去掉了index.html#/tab/dash这不部分的内容。

访问之后,你会发现,就算是只访问http://localhost:63342/routeDemo/www/最后访问的还是http://localhost:63342/routeDemo/www/index.html#/tab/dash

这里有两个知识点,一个是web的,当url访问的是网站的某个文件夹时,浏览器会自动打开该文件夹下的index.html文件。

即打开的就是上面这个代码,代码是按照顺序从上到下解析的。跑到body的ng-app=“starter”,就是自动启动应用的脚本。

就会在模块池(我随意说的,便于理解)查找名字叫做starter的模块。是的,模块,没有应用,你没有看错。

纸上得来终觉浅,绝知此事要读源码(read the fucking source code)

我们打开app.js查看源码

可以看到这里定义了名字叫做starter的模块,前面自动启动的就是它,后面中括号里面的内容,可以理解为这个模块的依赖,就是说这个模块要运行起来,是要在这三个模块运行起来的基础上才行的,这么说不是很严谨,但是新手这么理解是可以的。

一般在项目中,会把这个模块的返回值保存下来,这样在代码中操作会比较方便。

var app = angular.module(name,[])这样子的形式,在代码中直接使用app就是当前这个应用了,比较方便。

恩,我们接着往下看

注意看前面的.run()可以这么理解在app运行的时候执行的内容,看内容这一块是打包之后才有用的。所以你的项目只是一个单存的web项目,可以把这个删除了也没有关系。

这个.run()还可以用来引入rootscope,全局的控制器上下文,可以实现一些简单的数据传递,或者通用函数的统一处理。写法如下

.run(function($rootScope){  $rootScope.Debug = true;})这样子你在子控制器里面引入$rootScope,就能获得这个全局变量了,比如在是否打印log的时候可以这么实现

$rootScope.Debug && console.log(“运行日志”)

这里还要注意的是.run()是直接接在angular.module(name,[]).run()注意这是一个链式的写法。有语句后面加分号编程习惯的小伙伴,可以注意一下,按照上面提到的,可以把这个拆开写var app = angular.module(name,[]);  这是可以断开的app.run(); 这样子的写法有个好处就是,这两部分的内容可以写到不同的文件里面。有些人喜欢把route这部分的内容分离,就是可以这么实现的。

还是接着看源码

.config()可以理解为应用运行的配置文件,可以用来定义一些基础的配置,这里引入的是$stateProvider,用来配置路由。第二个参数其实是可以不用的。但是这里是用来定义,当你访问链接的时候没有携带任何的路由信息,那系统会自动访问otherwise配置的路由。就像我们一开始访问的地址http://localhost:63342/routeDemo/www/。浏览器自动帮我们补齐了地址http://localhost:63342/routeDemo/www/index.html。这是一个没有路由信息的地址,所以这里配置的otherwise就会帮我们自动补上#/tab/dash。这里就解释了为什么我们直接访问项目目录,会访问http://localhost:63342/routeDemo/www/index.html#/tab/dash。

接下来,我们来看一个详细的路由配置。这里有两种情况。是否为母版(模板).

我们看tab的这个路由,url就是路由地址,abstract:true就是指设置这个界面为母版界面,可以这么理解,这是一个架子,所有的子界面都有这个统一的界面。

templateUrl是定义了这个路由视图对应的界面。这里我们还是围绕着http://localhost:63342/routeDemo/www/index.html#/tab/dash。这个链接。我们要解释里面的这个tab是什么。

这里我们做一个有意思的尝试,我们注销掉路由配置里面的$urlRouterProvider.otherwise(‘/tab/dash’)防止我们输入错误路由的时候,系统自动跳转。然后我们在浏览器里面访问http://localhost:63342/routeDemo/www/index.html#/tab只访问到tab这一级。(注意在浏览器中只修改路由是不会重新加载页面的,这也是路由的一个优点,所以要刷新页面之后在修改路由,这样我们刚才修改的代码才会有效)

然后我们会在界面上看到两个浅浅的框框。

要仔细看,不然会以为没有东西。我们在从控制台看一下html

注意看这个视图是有解析的。恩,这 暂且放一边不看,我们接着看另外一个路由配置

首先是这个路由的名字tab.dash这里的点和js中的点一样理解为对象的属性,这里表示一种从属关系。指dash这个视图是tab的一个子视图。

这个路由配置和tab的路由配置有个明显不同的地方就是多了一个views,可以简单理解为用来定义视图详情。格式是views:{name:{parms}}

这里最应该关注的就是‘tab-dash’这个视图名字。首先要指导这个视图名字是从哪来的,又是什么意思?

我们打开tabs.html文件

可以看到在tabs地下定义的tab里面有一个ion-nav-view 它的名字定义为‘tab-dash’这个意思就是。tab.dash这个路由定义了,这个路由的视图是在‘tab-dash’这个tab的视图里面绘制的。

这个ion-nav-view我们在index.html中也有见过<ion-nav-view ></ion-nav-view>。那这里要怎么理解呢?

我们对代码做一点小改动。改动tab的配置。加入views属性。

然后给index.html中的<ion-nav-view ></ion-nav-view>加入属性name=’main’。

然后运行项目,项目运行成功。给每一个视图定义了名字之后,理解起来就容易很多了。下面我画一个简单的图来说明这几个关系。

这里我把视图之间画的比较开,便于理解。但是这些视图之间的关系,要以我下面的说明为主。

首先我们来理解系统默认的那种没有定义views属性的路由,它们会被默认绘制在最上层的main视图里面。从上往下,第一个没有定义名字的view。

比如我们在项目中常常会有一些界面不需要下面的tab切换。所以我们可以把他们定义为不带views属性的,即不声明所属视图的路由,他们都会被绘制在main视图中,他们和tabs视图是同级的关系。这个视图是直接在主视图中绘制的,所以图中蓝色的tabs视图,实际上是不存在的。

tabs视图下面有定义了很多个子视图,根据代码控制这些子视图是只能同时有一个是显示的,其他的子视图都会被放入视图缓存中。所以途中紫色的视图,应该是和tabs视图一样的的,但是它们是存在的。当这些视图的大小都完全一样的时候,那我们看起来就像只有一个视图了。这里我在画一个简化版的tabs切换的视图关系,便于理解。

正视图侧视图

根据上面这两个不同角度的图应该能够理解tabs是怎么做到切换的了。我们能够看到的就是最上层的,所以在tabs母版里面定义的tabs切换栏,在每一个子视图里面都有,就是这么实现的。

所以说视图要不要定义,要怎么定义可以根据项目需要灵活的选择。定义在同一个视图地下的路由在切换的时候,会有历史保留,可以直接使用back按钮,进行返回操作。但是游离在子视图,即没有设置views的视图,相互之间是没有历史的,他们之间的返回需要手动的补充功能,我觉得应该是我哪里使用的不对。但是还没定位出来。

看完了新建项目中定义的这几个属性,我们接下来来看几个,比较常用的新建项目中没有提到的属性。

1、template

这个属性和templateUrl都是用来定义视图对应的html模板的,前者接受的是一个html的字符串,后者接受的是一个文件路径的地址。比较好理解。

2、prefetchTemplate

默认为true。这个设置为false,表示不提前加载html,模板。这里我们看一下新建项目的日志

这里我们在启动项目的时候,走过路由配置,所有的html都会被预加载到缓存中。是的后面的视图之间的切换会很流畅。

但是也有一个问题,就是启动项目的时候,要加载过多的文件,有些文件还不一定有用,在很多级下面的文件,很少使用到。

所以可以选择,把一些不常用的视图设置为false,这样一开始就不会去加载它们了。

在做按需加载的时候。也可以把这个值设置为false。js文件都按需加载了,访问首页只加载了一个js文件却加载了几十个上百个的html文件,这很不科学。

3、resolve:预载入
使用预载入功能,可以预先载入一系列依赖或者数据,然后注入到控制器中。
在路由中的resolve,能够保证在路由到达前载入数据保证(promises).
预载入对象需要一个对象,这个对象的key纪要注入到控制器的依赖,这个对象的值为需要被载入的服务。
如果传入的是字符串,路由会视图匹配已经注册的服务。
如果传入的是函数,该函数会被注入,并且该函数返回的值便是控制器的依赖之一。
如果该函数返回一个数据保证(promise),这个数据保证将在控制器被实例化前被预先载入并且数据会被注入到控制器中。

这个用来实现按需加载的基础,也有其他的模块依赖,或者前置函数的执行,都是靠它来完成的。

接下来还要讲到的几个常用事件。

1、$ionicView.enter

在进入视图的时候响应的事件,在控制器中使用on方法监听触发

2、$ionicView.leave

在离开视图的时候响应的事件。注意如果从A界面到B界面跳转,那么B界面的enter会先响应,再响应A界面的leave事件

3、$stateChangeStart

在切换路由是响应的事件,可以用来判断前置路由是什么,控制当进入某些页面时执行的函数,比如说进入某些页面都要把右上角的按钮显示出来等等

暂时能想起来的,就这么多,其中需要明确关注的是resolve这个属性。后续的深入学习,对它的涉及会比较多。

这节课没有demo,直接新建一个tabs类型的项目跟着看就可以了。

Jayway第一讲:ionic从搭建开发环境到生成apk详细教程 - wudizhukk的专栏 - 博客频道 - CSDN.NET

mikel阅读(1406)

Jayway第一讲:ionic从搭建开发环境到生成apk详细教程 先叨几句:以下教程的过程中,是需要翻墙的。ionic cordova node等是干嘛的,有要了解。总而言之,你想用一次网页开发,同时多平台发布,来这里就对了。 软件材料准备:JDKAndroid SDKNode.js (为了安装 ionic 和 cordova)Visual Studio Code (轻量级) 或者

来源: Jayway第一讲:ionic从搭建开发环境到生成apk详细教程 – wudizhukk的专栏 – 博客频道 – CSDN.NET

Jayway第一讲:ionic从搭建开发环境到生成apk详细教程

先叨几句:以下教程的过程中,是需要翻墙的。ionic cordova node等是干嘛的,有要了解。总而言之,你想用一次网页开发,同时多平台发布,来这里就对了。

软件材料准备:

  1. JDK
  2. Android SDK
  3. Node.js (为了安装 ionic 和 cordova)
  4. Visual Studio Code (轻量级) 或者 VS2015
  5. Android Studio

安装步骤:

这里写图片描述

本来用vs2015开发的,虽然体积大,毕竟一条龙服务,试了一下还不错的,但,我还是喜欢自己搞,让vs做的多了,自己懂的就少了。所以用了vscode来做开发,需要用到的插件如图所示。

这里写图片描述

很多东西,相应的官网都有详细的说明,我不开发软件,我只是代码的搬运工。下载安装完vscode,如图所示安装一下 Cordova Tools 这个插件。 vscode 里按 Ctrl+P 输入 ext install cordova-tools 就可以了。

这里写图片描述

接下来安装 Node.js 也没什么好讲的,下载下来,一步一步直到Finish。Cmd里输入npm有反应就说明安装成功了。

这里写图片描述

开始安装Cordova 命令直接看图吧。

这里写图片描述

接着安装Ionic 这是今天的主角。 命令也可以看图,以上两个一起装,分开显示,只是为了明确点。装完后,运行命令 ionic start jwApp tabs 。其中app名字是 jwApp,tabs是模板的名字,当然也有空白的模板,可以自己搜索了解下。

这里写图片描述

运行成功后,会生成如图所示的ionic项目

这里写图片描述

添加Android平台,当然你也可以添加iOS平台的。成功后会有刚才的目录下生成一个Platforms的文件夹,里面有一个android的工程项目,这个项目是可以拉到android studio里跑的,如果你想自己再加点什么非网页的界面,可以导入这个android的文件夹。

这里写图片描述

都有项目了,那就编译,跑一下呗,唉,发现出错了,原来Android_Home 还没有指定,就是说Android的SDK还没有装。

这里写图片描述

你可以下载一个android studio ,里面是有一个sdk的,只有最新版本的api,之前的都没的,更新太麻烦,我试了一上会有一些问题,缺斤少两的。网上更新到最新的sdk很多,可以直接下载下来使用,当然你之前在开发安卓的,肯定有这玩样,这里就不多讲开了,本文章使用到的所有最新软件,都会直接分享,到时大伙自己拿走就是。我最后没用as自带的sdk,我的是这样的,就一个文件夹,即拿即用:

这里写图片描述

编译通过后,环境上的配置基本就结束了,结果如图所示:

这里写图片描述

现在回到vscode里来,用vscode打开app文件夹,点击Debug,Run Android on emulator 这样就会启动一个模拟器,开始跑app。前提你得先建了一个模拟器,怎么建我就不说了吧。在vscode里挖个断点,能断上,这样就能调试了,当然ionic是可以在网页上及时显示运行的,这个搜索一下都有的。

这里写图片描述

再去android studio 里转一下,导入platforms/android文件夹,问题不大,也能跑跑,如果是新安装的AS,一开始会联网gradle下载相应文件,然后就OK可以玩了。

这里写图片描述

能跑,能断点,大伙都开心,中间怎么开发怎么玩,就不说了,玩好后的生成发布得说一下,网上其他文章一般只搭环境,不管后面死活,这样是不对的,一条龙服务必须要有。先是Release一个没签名的apk。然后就是用jdk里的工具,生成证书,打个码,性能对齐一下。就算完工了。

这里写图片描述

最后的工作就直接上官方原文了,一目了然

这里写图片描述

结束,先写到这,有问题留言,会补充,软件大伙先网上下着吧,一搜一大把,太懒的我随后会发地址上来

python模块以及导入出现ImportError: No module named 'xxx'问题 - 我的新博客 - 博客频道 - CSDN.NET

mikel阅读(2255)

python中,每个py文件被称之为模块,每个具有__init__.py文件的目录被称为包。只要模块或者包所在的目录在sys.path中,就可以使用import 模块或import 包来使用如果你要使用的模块(py文件)和当前模块在同一目录,只要import相应的文件名就好,比如在a.py中使用b.py: import b 但是如果要import一个不同目录的文件(例如b.

来源: python模块以及导入出现ImportError: No module named ‘xxx’问题 – 我的新博客 – 博客频道 – CSDN.NET

python中,每个py文件被称之为模块,每个具有__init__.py文件的目录被称为包。只要模
块或者包所在的目录在sys.path中,就可以使用import 模块或import 包来使用
如果你要使用的模块(py文件)和当前模块在同一目录,只要import相应的文件名就好,比
如在a.py中使用b.py:
import b

但是如果要import一个不同目录的文件(例如b.py)该怎么做呢?
首先需要使用sys.path.append方法将b.py所在目录加入到搜素目录中。然后进行import即
可,例如
import sys
sys.path.append(‘c:\xxxx\b.py’) # 这个例子针对 windows 用户来说的
大多数情况,上面的代码工作的很好。但是如果你没有发现上面代码有什么问题的话,可要

注意了,上面的代码有时会找不到模块或者包(ImportError: No module named
xxxxxx),这是因为:
sys模块是使用c语言编写的,因此字符串支持 ‘\n’, ‘\r’, ‘\t’等来表示特殊字符。所以

上面代码最好写成:
sys.path.append(‘c:\\xxx\\b.py’)
或者sys.path.append(‘c:/xxxx/b.py’)
这样可以避免因为错误的组成转义字符,而造成无效的搜索目录(sys.path)设置。

sys.path是python的搜索模块的路径集,是一个list
可以在python 环境下使用sys.path.append(path)添加相关的路径,但在退出python环境后
自己添加的路径就会自动消失了!

3、搜索路径和路径搜索

模块的导入需要叫做“路径搜索”的过程。

搜索路径:查找一组目录

路径搜索:查找某个文件的操作

ImportError: No module named myModule

这种错误就是说:模块不在搜索路径里,从而导致路径搜索失败!

导入模块时,不带模块的后缀名,比如.py
Python搜索模块的路径:
1)、程序的主目录
2)、PTYHONPATH目录(如果已经进行了设置)
3)、标准连接库目录(一般在/usr/local/lib/python2.X/)
4)、任何的.pth文件的内容(如果存在的话).新功能,允许用户把有效果的目录添加到模块搜索路径中去
.pth后缀的文本文件中一行一行的地列出目录。
这四个组建组合起来就变成了sys.path了,

>>> import sys
>>> sys.path
导入时,Python会自动由左到右搜索这个列表中每个目录。

关于 python ImportError: No module named ‘xxx’的问题?
解决方法如下:
1. 使用PYTHONPATH环境变量,在这个环境变量中输入相关的路径,不同的路径之间用逗号
(英文的!)分开,如果PYTHONPATH 变量还不存在,可以创建它!
这里的路径会自动加入到sys.path中,永久存在于sys.path中而且可以在不同的python版本
中共享,应该是一样较为方便的方法。
C:\Users\Administrator\Desktop\test\module1.py:
def func1():
print(“func1”)

将C:\Users\Administrator\Desktop\test添加到PYTHONPATH即可直接import module1,然后
调用:module1.func1()即可。

2. 将自己做的py文件放到 site_packages 目录下

3. 使用pth文件,在 site-packages 文件中创建 .pth文件,将模块的路径写进去,一行一
个路径,以下是一个示例,pth文件也可以使用注释:

# .pth file for the  my project(这行是注释),命名为xxx.pth文件
C:\Users\Administrator\Desktop\test
这个不失为一个好的方法,但存在管理上的问题,而且不能在不同的python版本中共享。

4. 在调用文件中添加sys.path.append(“模块文件目录”);

5. 直接把模块文件拷贝到$python_dir/Lib目录下。

通过以上5个方法就可以直接使用import module_name了。

参考文章:http://my.oschina.net/leejun2005/blog/109679

初次使用树莓派并启用root管理员(登录root管理员)

mikel阅读(1259)

初次使用树莓派系统时,默认用户是pi ,密码为raspberry。

要想使用root帐号,或者说开启root用户,可使用pi用户登录,执行下面命令(此命令是给root账户设置密码的,当切换到root管理员后,此命令无sudo passwd root

说明:sudo是Linux系统管理指令,是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,如halt,reboot,su等等

执行此命令后系统会提示输入两遍的root密码(用来确保你记住了密码)。

接着输入下面命令,用来解锁root账户

sudo passwd –unlook root

用下面命令切换到root管理员

su root

会提示输入密码

当从root用户切换到pi用户后,我们再次使用su passwd root来修改密码,会报错

树莓派2代干货帖(第一天)按图索骥的搭建 - 浩克匠心 - 博客园

mikel阅读(1272)

来源: 树莓派2代干货帖(第一天)按图索骥的搭建 – 浩克匠心 – 博客园

(序章)

 

本文目的:今日到手树莓派2B两套及配件一坨,经过一番摸索,发现硬件接口和配置步骤与一代大有不同,网上资料大多陈旧(包括网上流传深广的那个O’Reilly14MB的pdf ),2代资料不多且难找,为了帮广大pi友节省时间少走弯路,也为了帮自己归纳,遂书此帖以记之。

本文宗旨:帮助pi友最快速搭建树莓派2B系统(如果赶上win10系统发布,后续有win10的试玩帖),并实现各配件子功能 ,网上现有且可用的资料概不赘述,直接给出链接,所述内容皆为原创。

简称约定

2B  指代树莓派2代B型;

Pi 指代所有树莓派设备;

Pi友 认真看到这一行的都可以算是了^_^

(第一天)按图索骥的搭建

 

1.系统搭建

对于2B的系统安装,最便捷的方法是(非Win32DiskImager方法):

1.1 官网下载NOOBS zip文件 http://www.raspberrypi.org/downloads/

1.2 使用SDFormatter (https://www.sdcard.org/downloads/formatter_4/eula_windows/)工具格式化TF卡;

1.3 解压zip文件,全部拷贝到TF卡根目录;

 

1.4 TF卡插入2B,上电启动,选择系统进行安装;

 

在本向导中,共有7种可选的操作系统供我们安装。分别是

 

Rasbian(标准的Debian移植版)

Rasbian(轻量级的,面向初学者的编程平台,在树莓派中很流行)

Arch Linux

Pidora(Fedora的分支,对树莓派做了优化)

OpenELEC(一种XBMC系统的分支)

RaspBMC(一种XBMC系统的分支,专门针对树莓派做了调整)

RISC OS(一个轻量级的基于Acorn的操作系统,在80-90年代非常活跃,专门针对树莓派做了优化)

注意硬盘剩余空间,因为仅仅安装Rasbian和Pidora就占用了4G,如果你想把所有的系统都安装上,并且还要保证系统运行的足够预留空间,那么你至少需要一张32GB的SD卡。

 

2.网络搭建

2.1 将pi用网线插入路由器;

2.2 通过路由器查看pi的地址;

(如果pi用hdmi线连接着显示器,可以直接开机进入pi的raspbian系统,输入ifconfig 查看IP地址)

 

2.4 PC端安装putty http://rj.baidu.com/soft/detail/15699.html?ald ,打开输入ip地址;

 

 

2.5 进入terminal输入用户名pi 密码raspberry;远程登录完成;

3.顺便说说2代的最大不同

pi2代的硬件接口和pi1代B+是完全一致的,只是内存升到了1g,但是网上的资料主要集中在1代,B+的资料也不多,特搜集如下:

 

3.1 GPIO端口有原来的26个引脚增加到了现在的40个引脚。并且没有改变原GPIO扩展插座的顺序,只是增加了14个引脚,这样当前市场上大部分外接卡都可以用在pi2B上。

 

 

 

3.2 其他不同

其他不同对开发影响不大,简述如下。

增加了2个usb口,这样插上无线网卡后还能再接入鼠标,键盘,麦克风灯其他IO设备:

SD卡槽换成了TF卡槽,占用空间更小:

 

欢迎大家批评指正,明天继续研究camera的组装与调试^_^

Excel操作类C#版 - 许明吉博客 - 博客园

mikel阅读(1437)

来源: Excel操作类C#版 – 许明吉博客 – 博客园

 

//引入Excel的COM组件
using System;
using System.Data;
using System.Configuration;
using System.Web;
using Excel = Microsoft.Office.Interop.Excel;
using Microsoft.Office.Core;
namespace ExcelEdit
{
///

/// ExcelEdit 的摘要说明
///

public class ExcelEdit
{
public string mFilename;
public Excel.Application app;
public Excel.Workbooks wbs;
public Excel.Workbook wb;
public Excel.Worksheets wss;
public Excel.Worksheet ws;
public ExcelEdit()
{
}
//创建一个Excel对象
public void Create()
{
app = new Excel.Application();
wbs = app.Workbooks;
wb = wbs.Add(true);
}
//打开一个Excel文件
public void Open(string FileName)
{
app = new Excel.Application();
wbs = app.Workbooks;
wb = wbs.Add(FileName);
//wb = wbs.Open(FileName, 0, true, 5,””, “”, true, Excel.XlPlatform.xlWindows, “t”, false, false, 0, true,Type.Missing,Type.Missing);
//wb = wbs.Open(FileName,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Excel.XlPlatform.xlWindows,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing);
mFilename = FileName;
}
//获取一个工作表
public Excel.Worksheet GetSheet(string SheetName)
{
Excel.Worksheet s = (Excel.Worksheet)wb.Worksheets[SheetName];
return s;
}
//添加一个工作表
public Excel.Worksheet AddSheet(string SheetName)
{
Excel.Worksheet s = (Excel.Worksheet)wb.Worksheets.Add(Type.Missing, Type.Missing, Type.Missing, Type.Missing);
s.Name = SheetName;
return s;
}
//删除一个工作表
public void DelSheet(string SheetName)
{
((Excel.Worksheet)wb.Worksheets[SheetName]).Delete();
}
//重命名一个工作表一
public Excel.Worksheet ReNameSheet(string OldSheetName, string NewSheetName)
{
Excel.Worksheet s = (Excel.Worksheet)wb.Worksheets[OldSheetName];
s.Name = NewSheetName;
return s;
}
//重命名一个工作表二
public Excel.Worksheet ReNameSheet(Excel.Worksheet Sheet, string NewSheetName)
{
Sheet.Name = NewSheetName;
return Sheet;
}
//ws:要设值的工作表 X行Y列 value 值
public void SetCellValue(Excel.Worksheet ws, int x, int y, object value)
{
ws.Cells[x, y] = value;
}
//ws:要设值的工作表的名称 X行Y列 value 值
public void SetCellValue(string ws, int x, int y, object value)
{
GetSheet(ws).Cells[x, y] = value;
}
//设置一个单元格的属性 字体, 大小,颜色 ,对齐方式
public void SetCellProperty(Excel.Worksheet ws, int Startx, int Starty, int Endx, int Endy, int size, string name, Excel.Constants color, Excel.Constants HorizontalAlignment)
{
name = “宋体”;
size = 12;
color = Excel.Constants.xlAutomatic;
HorizontalAlignment = Excel.Constants.xlRight;
ws.get_Range(ws.Cells[Startx, Starty], ws.Cells[Endx, Endy]).Font.Name = name;
ws.get_Range(ws.Cells[Startx, Starty], ws.Cells[Endx, Endy]).Font.Size = size;
ws.get_Range(ws.Cells[Startx, Starty], ws.Cells[Endx, Endy]).Font.Color = color;
ws.get_Range(ws.Cells[Startx, Starty], ws.Cells[Endx, Endy]).HorizontalAlignment = HorizontalAlignment;
}
public void SetCellProperty(string wsn, int Startx, int Starty, int Endx, int Endy, int size, string name, Excel.Constants color, Excel.Constants HorizontalAlignment)
{
//name = “宋体”;
//size = 12;
//color = Excel.Constants.xlAutomatic;
//HorizontalAlignment = Excel.Constants.xlRight;
Excel.Worksheet ws = GetSheet(wsn);
ws.get_Range(ws.Cells[Startx, Starty], ws.Cells[Endx, Endy]).Font.Name = name;
ws.get_Range(ws.Cells[Startx, Starty], ws.Cells[Endx, Endy]).Font.Size = size;
ws.get_Range(ws.Cells[Startx, Starty], ws.Cells[Endx, Endy]).Font.Color = color;
ws.get_Range(ws.Cells[Startx, Starty], ws.Cells[Endx, Endy]).HorizontalAlignment = HorizontalAlignment;
}
//合并单元格
public void UniteCells(Excel.Worksheet ws, int x1, int y1, int x2, int y2)
{
ws.get_Range(ws.Cells[x1, y1], ws.Cells[x2, y2]).Merge(Type.Missing);
}
//合并单元格
public void UniteCells(string ws, int x1, int y1, int x2, int y2)
{
GetSheet(ws).get_Range(GetSheet(ws).Cells[x1, y1], GetSheet(ws).Cells[x2, y2]).Merge(Type.Missing);
}
//将内存中数据表格插入到Excel指定工作表的指定位置 为在使用模板时控制格式时使用一
public void InsertTable(System.Data.DataTable dt, string ws, int startX, int startY)
{
for (int i = 0; i <= dt.Rows.Count - 1; i++) { for (int j = 0; j <= dt.Columns.Count - 1; j++) { GetSheet(ws).Cells[startX + i, j + startY] = dt.Rows[i][j].ToString(); } } } //将内存中数据表格插入到Excel指定工作表的指定位置二 public void InsertTable(System.Data.DataTable dt, Excel.Worksheet ws, int startX, int startY) { for (int i = 0; i <= dt.Rows.Count - 1; i++) { for (int j = 0; j <= dt.Columns.Count - 1; j++) { ws.Cells[startX + i, j + startY] = dt.Rows[i][j]; } } } //将内存中数据表格添加到Excel指定工作表的指定位置一 public void AddTable(System.Data.DataTable dt, string ws, int startX, int startY) { for (int i = 0; i <= dt.Rows.Count - 1; i++) { for (int j = 0; j <= dt.Columns.Count - 1; j++) { GetSheet(ws).Cells[i + startX, j + startY] = dt.Rows[i][j]; } } } //将内存中数据表格添加到Excel指定工作表的指定位置二 public void AddTable(System.Data.DataTable dt, Excel.Worksheet ws, int startX, int startY) { for (int i = 0; i <= dt.Rows.Count - 1; i++) { for (int j = 0; j <= dt.Columns.Count - 1; j++) { ws.Cells[i + startX, j + startY] = dt.Rows[i][j]; } } } //插入图片操作一 public void InsertPictures(string Filename, string ws) { GetSheet(ws).Shapes.AddPicture(Filename, MsoTriState.msoFalse, MsoTriState.msoTrue, 10, 10, 150, 150); //后面的数字表示位置 } //插入图片操作二 public void InsertPictures(string Filename, string ws, int Height, int Width) { GetSheet(ws).Shapes.AddPicture(Filename, MsoTriState.msoFalse, MsoTriState.msoTrue, 10, 10, 150, 150); GetSheet(ws).Shapes.get_Range(Type.Missing).Height = Height; GetSheet(ws).Shapes.get_Range(Type.Missing).Width = Width; } //插入图片操作三 public void InsertPictures(string Filename, string ws, int left, int top, int Height, int Width) { GetSheet(ws).Shapes.AddPicture(Filename, MsoTriState.msoFalse, MsoTriState.msoTrue, 10, 10, 150, 150); GetSheet(ws).Shapes.get_Range(Type.Missing).IncrementLeft(left); GetSheet(ws).Shapes.get_Range(Type.Missing).IncrementTop(top); GetSheet(ws).Shapes.get_Range(Type.Missing).Height = Height; GetSheet(ws).Shapes.get_Range(Type.Missing).Width = Width; } //插入图表操作 public void InsertActiveChart(Excel.XlChartType ChartType, string ws, int DataSourcesX1, int DataSourcesY1, int DataSourcesX2, int DataSourcesY2, Excel.XlRowCol ChartDataType) { ChartDataType = Excel.XlRowCol.xlColumns; wb.Charts.Add(Type.Missing, Type.Missing, Type.Missing, Type.Missing); { wb.ActiveChart.ChartType = ChartType; wb.ActiveChart.SetSourceData(GetSheet(ws).get_Range(GetSheet(ws).Cells[DataSourcesX1, DataSourcesY1], GetSheet(ws).Cells[DataSourcesX2, DataSourcesY2]), ChartDataType); wb.ActiveChart.Location(Excel.XlChartLocation.xlLocationAsObject, ws); } } //保存文档 public bool Save() { if (mFilename == "") { return false; } else { try { wb.Save(); return true; } catch (Exception ex) { return false; } } } //文档另存为 public bool SaveAs(object FileName) { try { wb.SaveAs(FileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); return true; } catch (Exception ex) { return false; } } //关闭一个Excel对象,销毁对象 public void Close() { //wb.Save(); wb.Close(Type.Missing, Type.Missing, Type.Missing); wbs.Close(); app.Quit(); wb = null; wbs = null; app = null; GC.Collect(); } } } [/code]