phonegap安装 环境搭建与配置详解(3.4 完整版 提供下载地址)

phonegap 3.4  安装 环境搭建 完整版

刚刚接触 phonegap 因为配环境遇到各种各样问题.花了一下午时间才完成,所以写一个篇文章希望能给大家节约点时间.

      本文主讲windows系统下的phonegap的环境搭建 ,以android视角为主.ios用户可参考;

首先介绍搭建环境的基本准备:

1 java JDK   (搜索一下…….)

2 android SDK 最新版(我当时的版本是 API 19  点击打开链接)

3 Ant 打包工具  (百度一个或者 点击打开链接)

4 eclipse   (建议使用google的  因为内置ADT     点击打开链接 )

5 ADT (ecplise 里的插件,安卓开发工具插件     下载上面的链接,内部集成了ADT)

6 Node.js   (点击打开链接)

7 sublime  点击打开链接 ;是我开发js h5 css 的工具;如果大家有好的开发软件希望能告诉我一下谢谢

下图是Node.js安装成功后

SouthEas

将以上配置好环境变量  (配置方法略 点击 )

特别提一下需要配环境变量的东西:  java JDK  ; android SDK;Ant ; 

贴上我的 path 供大家参考:

 (建议配成 ;%ANT_HOME%\bin;  去掉\bin)

F:\工具\Ant\ant-1.8\bin;     

C:\Develop\sdk\sdk\platform-tools;C:\Develop\sdk\sdk\tools;%Android%\.;C:\Develop\nodejs;%JAVA_HOME%\bin;C:\Develop\nodejs\

拥有以上工具后 

接下来开始phonegap的安装了

 phonegap 官网 点击

在控制台运行命令:

npm install -g phonegap                                     ( Mac使用: sudo npm install -g phonegap )

//等待安装   完成后安装 cordova:

 npm install -g cordova                                       ( Mac使用: sudo npm install -g cordova )

SouthEast

SouthEast

安装完成后
检验语句:

phonegap -version

cordova -version

SouthEast

SouthEast

在命令行 使用:

[html] view plaincopy::__IHACKLOG_REMOTE_IMAGE_AUTODOWN_BLOCK__::1
  1. phonegap create my-app  
  2. cd my-app  
  3. phonegap run android  

第一个 phonegap写的程序就出现了

在my-app 目录下出现5个文件夹     打包好的工程放在platforms里面

SouthEast

文件夹详解:

www              : 文件夹  开发的 HTML5 ; CSS ; JS 文件都拷贝到这下面

plugins          : 文件夹  存放的是phonegap插件  以后 文件,摄像头等插件都下载到这里,在下篇文章中介绍用法 

merges          : 我也没用过  以后知道了再补上

platforms      : 文件夹 存放的是编译好后的android文件   ,(如果这个文件夹为空,需要你在命令行编译一次才能生成. 如上面 phonegap run android)

.cordova        : 存放的是配置文件 

将此文件夹导入 eclipse 就可以使用

phonegap 将以第三方库的形式导入

如果src文件报错 检查是否是   phonegap的功能没有导入进来

导入eclipse后  文本结构….下图打的camera 和 vibration 是 相机与铃声的插件  下章节介绍

SouthEast

(图 1)

下图是     phonegap的启动页面  调用 super.loadUrl(); 方法

[java] view plaincopy::__IHACKLOG_REMOTE_IMAGE_AUTODOWN_BLOCK__::3
  1. public class baozi extends CordovaActivity   
  2. {  
  3.     @Override  
  4.     public void onCreate(Bundle savedInstanceState)  
  5.     {  
  6.         super.onCreate(savedInstanceState);  
  7.         super.init();  
  8.         // Set by <content src=”index.html” /> in config.xml  
  9. //        super.loadUrl(Config.getStartUrl());  
  10.         super.loadUrl(“file:///android_asset/www/index.html”);  
  11.             
  12.           
  13.     }  
  14. }  

在 super.loadUrl(”  “); 中填写你的启动页面

参数: ” file:///android_asset/www/index.html “

指的是( 图  1)的  assets目录下 www 文件夹下的  index.html

贴上一张 工程导入后的属性图

SouthEast

工程下载    将phonegap的platforms导入到eclipse中

如果报错clear一下  查看导的lib包 有没有报错

如果还有错  那么就是您选用了  google的API   改成最新版的android  API 就好了

如果导入工程遇到问题 可以查阅我此篇文章

Blog:  http://blog.csdn.net/aaawqqq/article/details/20463183

Phonegap解决错误:Error initializing Cordova:Class not found:

 

http://blog.csdn.net/aaawqqq/article/details/21243869

新一代Web packs UI 组件系统 Polymer

怎么看都像是未来趋势啊

在今年的Google I/O大会上,Google发布了Polymer,它是一个使用Web组件构建Web应用的类库,同时也使用了为Web构建可重用组件的新的HTML 5标准。Polymer为大部分Web组件技术提供了polyfills功能,它能让开发者在所有的浏览器支持新特性前创建自己的可重用组件。此外,Polymer提供了一系列的部件的例子,其中包括天气、时钟、股票行情和线型图。 
Web组件让开发者能创建自定义和可重用的HTML 标记。下面的例子中,是一个<my-own-tag>标记组件的框架:

<element name="my-own-tag">
 <template>
   HTML elements here
 </template>
 <script>
   // JavaScript implementing logic
 </script>
</element>

鉴于许多Web框架通过暴露JavaScript API来构建用户界面,而构建用户界面实际上就是生成一堆div和spans标记,Web 组件是原生浏览器的解决方案因此不依赖于一个完整的框架。因此,与现在的一般依赖某个Javscript框架的HTML组件相比,Web组件希望能减少碎片

尽管Web组件是一项有趣的新技术,但在浏览器们都支持它们(并且大部分用户都开始使用这些浏览器们)之前,其中的大部分功能还派不上用场。解决这个问题的一种方法是使用polyfills(译者注:polyfills原指一种墙面填料)。polyfill指的是一段代码,它能实现期望最终由浏览器自身实现的功能。如果浏览器本身已经实现了该功能,则polyfill什么都不做。否则,它模拟其实现而不依赖API。例如,webshims库实现了HTML5中各种功能,包括canvas、HTML5表格和在某些尚不支持地理位置定位的浏览器中实现地理位置定位功能。

Polymer中的polyfills为需要使用Web组件成功构建应用提供了多种Web技术,包括:

  • HTML imports:种在其他HTML document中引入和重用HTML document的方法。
  • 自定义元素:让开发者定义和使用自定义DOM元素。
  • Shadow DOM:在DOM中提供的封装。
  • 模型驱动视图(Model Driven Views):提供象AngularJS的数据绑定。
  • ·Web动画:实现复杂动画的API。
  • ·Pointer事件:对鼠标触摸和手写笔事件的封装

这些polyfills可以分开使用而不需要使用Polymer的其他部分。此外,Polymer提供:

  • polymer.js: Polymer的核心运行引擎,能轻易创建自定义属性和事件。
  • 一系列可重用的可视和非可视元素。


Polymer不是第一个尝试实现Web组件相关标准的项目。Mozilla在此之前启动了X-Tag项目——针对自定义元素标准的polyfill。Web UI package 使用Google的Dart语言编写了Model Driven View技术从而实现了自定义元素。

用户可以在YouTube上观看Google I/O大会关于Polymer的演讲。如果用户想了解更多关于Web组件的信息,可以观看Google I/O上Web组件的演讲。另外,用户可以在Polymer的网站查看导学文章和其他相关文档。

查看英文原文:Use Web Components Today With Google’s Polymer

阅读 : Sketch 3 的新变化

Sketch 3 的新变化

满足一切所想,并且超过期待

我从2014年2月底就开始使用 Sketch 3 。在此为大家介绍其中一些新的特性,告诉你要玩转新版软件,值得注意的地方。

过去的一年里,我写过几篇文章、在谷歌举办了一些内部研讨会,一直在推广 Sketch 软件。许多人(不仅仅是设计师们)把自己的工具切换到Sketch上。通过这次更新, Bohemian Coding 身体力行地表达了他们的座右铭:倾听、制作、发布

以快到惊人的节奏,每天他们都在推送推送大量的更新和修正,而这是个仅由2名工程师、3名设计师组成的团队。

事实上,他们几乎解决了我在 第一篇博客 中列出的、所有希望它们改进的问题。

让我们沉浸其中吧!

新的用户界面

新的用户界面[+]查看原图

用户界面焕然一新:新的图标、搜索栏如今不再隐藏、可以过滤图层和切片、对齐工具挪到了检查器面板、可供单击的翻转按钮。大工具条下面不再有小工具条了。这些细小的变化,给人感觉非常的清新。

各就各位,各司其职

检查器面板

检查器面板现在只有一级深度,字体和颜色选择器不需要再进第二层了。这里很多其他的功能都改变了位置。逻辑非常简单:所有的在 Sketch 2 中放错位置的东西,都归到了它们应该在的地方。

画板

创建画板的方式发生了一点点改变。

Sketch 3 的新变化 – 画板

曾经这是让人非常困扰的事情之一。现在你可以为所有的画板选择背景色,在导出时可以选择是否导出背景色。不用再在画板底层画一个锁定矩形当背景了,这真是大快人心。

为画板选择背景色

你可以在“画板设置( Artboard Settings )”检查器里找到这个选项

插入

插入菜单多了新内容[+]查看原图

插入菜单多了新内容。一些在 Sketch 2 的界面中漏掉的功能已经被合情合理地加进这个菜单了。

共享的元素

工具条中的元件按钮

要定制工具条,右击工具条,选择“定制工具条( Customize Toolbar )”

像很多其他功能一样,共享元素重新恢复了。而且这次更明显、也更实用。

他们还加入了呼声最高的功能之一:元件。你现在可以很轻松地跨页面创建、编辑和共享元素。

元件

每次在解释为什么切换到 Sketch 时,我经常遇见的问题是:“有像 Fireworks 的元件功能么?”我知道这确实是一个大家最想要的功能,而 Bohemian 的程序员没有失信于它们的用户。他们以一种聪明、高效的方式把它实现了。

就像你想象的那样,它会使你的生活简单很多。

Sketch 3 的新变化 – 元件

图层样式

创建和更改图层样式的界面现在变得非常友好。这个功能在 Sketch2 中就在手边但是非常难用。没有办法命名或者辨别相似的样式。

Sketch 3 的新变化 – 图层样式

样式链接

在左边,当一个形状被链接,它的图标会变成紫色。

文字样式

Sketch 3 的新变化 – 文字样式

和之前的非常相像,只是更好用了。就像视频中展示的哪样,仍然有一些使用上的限制。

导出

导出功能被重新构思,更贴近你的工作流。它不再是一个分离的操作模式。你可以象操作设计元素一样设置切片和切片参数。切片的创建和导出从没有这么简单过。新的切片工具让我意识到,以前为了创建一个特殊尺寸的画板来导出设计,我花费了多少时间。

Sketch 3 的新变化 – 导出

非常酷的新功能之一就是你可以导出多个预先设定的尺寸,或者设置你自己的导出尺寸。如果你同时给 Andriod 设备做设计,这个功能将会节省你很多时间,省去很多麻烦。对于未来的任何设备分辨率它也是非常灵活的。这里添加了一个选项,允许你自定义文件名字的后缀。

多尺寸导出[+]查看原图

我没这么用过,但你可以将同一个尺寸导出为不同的格式。我想这个功能非常有用,便于你在更复杂的产品、特别是 Web 设计中,要同时保存 PNG 、 JPG 和 SVG 等多种格式。

UI 元素

Teehanlax 宣布 他们著名的 iOS7 GUI 模板将会被内置到 Sketch 3 中。你可以在模板( Template )菜单中找到它。第一页说明了这个文档的结构,第二页重新将全部可用的元件摆在一起。你还可以在 Web Design 模板中找到面向网页的元件。

UI元素模板[+]查看原图

矢量和位图编辑

矢量编辑[+]查看原图

矢量和位图编辑工具同样被移动到检查器面板中。这样就直接多了,而且有更多的空间来用图标解释点编辑工具。至于位图编辑工具也有了新的选项,但还是一些基本功能,并且不再隐藏。如果你需要,现在有了一个好用的魔术棒工具。

位图编辑

反选、剪切、填充选区、多边形选区

最后一个功能很有趣,不过表现恐怕不尽人意。位图矢量化,这是一项非常复杂的处理过程,所以不要期望一张非常复杂的图片能转换成可以无限缩放的文件。

颜色选择器

颜色选择器

纯色、线性渐变、径向渐变、锥形渐变、图案填充、噪点填充

你会发现,熟悉的颜色选择器工具变成了一个弹出层。之前在重新摆放调色盘时会出现讨厌的颜色随机乱序问题,也得到了修正。

其他改进

所有这些我刚才描述的是你们用眼睛可以看到的,不过我们经常忘记谈论性能。举例来说,“画板预览列表”过去很慢,不过已经彻底地改进了。预览的缓慢速度经常让我灰心丧气。这个问题看上去已经解决掉了。载入大文件也明显快了很多。

将来的改进?

我有一些想法可以使我们的生活变的简单。其中的一些可能已经以插件的形式存在了,然而还是让我列举出来,这些很酷的功能有:

  • 共享元件:想象你在一个团队里工作,大家在忙同一个项目。你知道维护一个基本设计资源库是多棘手的事,我想我们这样解决问题:创建一个设计资源库,在这里提交你的图标,然后同事们都能使用。

  • 应用内购商店:作为一间小型创业公司,要面对很多难题,其中之一就是如何获得持续的现金流。基于共享元件的思路,我们可以想象一个应用内购商店,在这里出售图标集、样式、渐变、网格, UI 元素等。

  • 自动标注:如果已经做过类似的事情,你就知道这是工作流中必要的一环,但很花时间,是不是有什么自动化的方法来实现。想象你可以导出你的模型,其中包括了网格布局以及所需要的数值:字体尺寸、颜色、元素尺寸和边距。值得一提的是我刚写完这段,有人已经 做出插件 了!

  • 按钮元件:现在元件有了,如果能创建按钮模板就好了,可以在里面输入文字、同时持固定的边距。有一个 插件 已经做了这项工作,不过还是希望可以和元件更好地整合起来。

  • 批量命名:现在搜索变得给力了,给图层命名就非常重要。RenameIt 插件已经做了这项工作,不过如果成为内置功能会更酷。

Mongoose学习参考文档——基础篇

一、快速通道

1.1 名词解释

  • Schema : 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力

  • Model : 由Schema发布生成的模型,具有抽象属性和行为的数据库操作对

  • Entity : 由Model创建的实体,他的操作也会影响数据库

注意

1.本学习文档采用严格命名方式来区别不同对象,例如:

varPersonSchema;//Person的文本属性varPersonModel;//Person的数据库模型varPersonEntity;//Person实体

2.SchemaModelEntity的关系请牢记,Schema生成ModelModel创造EntityModelEntity都可对数据库操作造成影响,但ModelEntity更具操作性。

1.2 准备工作

1.首先你必须安装MongoDBNodeJS

2.在项目只能够创建一个数据库连接,如下:

var mongoose =require('mongoose');//引用mongoose模块var db = mongoose.createConnection('localhost','test');//创建一个数据库连接

3.打开本机localhosttest数据库时,我们可以监测是否有异常

    db.on('error',console.error.bind(console,'连接错误:'));
    db.once('open',function(){//一次打开记录});

注意

  成功开启数据库后,就可以执行数据库相应操作,假设以下代码都在回调中处理

4.定义一个Schema

varPersonSchema=new mongoose.Schema({
      name:String//定义一个属性name,类型为String});

5.将该Schema发布为Model

varPersonModel= db.model('Person',PersonSchema);//如果该Model已经发布,则可以直接通过名字索引到,如下://var PersonModel = db.model('Person');//如果没有发布,上一段代码将会异常

6.用Model创建Entity

var personEntity =newPersonModel({name:'Krouky'});//打印这个实体的名字看看
    console.log(personEntity.name);//Krouky

7.我们甚至可以为此Schema创建方法

//为Schema模型追加speak方法PersonSchema.methos.speak =function(){
      console.log('我的名字叫'+this.name);}varPersonModel= db.model('Person',PersonSchema);var personEntity =newPersonModel({name:'Krouky'});
    personEntity.speak();//我的名字叫Krouky

8.Entity是具有具体的数据库操作CRUD

    personEntity.save();//执行完成后,数据库就有该数据了

9.如果要执行查询,需要依赖Model,当然Entity也是可以做到的

PersonModel.find(function(err,persons){//查询到的所有person});

注意

  1. 具体的如何配置SchemaModel以及ModelEntity的相关操作,我们会在后面进行

  2. ModelEntity都有能影响数据库的操作,但仍有区别,后面我们也会做解释

二、新手指引

  如果您还不清楚Mongoose是如何工作的,请参看第一章快速通道快速浏览他的用法吧

1. Schema——纯洁的数据库原型

1.1 什么是Schema

  • 我理解Schema仅仅只是一断代码,他书写完成后程序依然无法使用,更无法通往数据库端
  • 他仅仅只是数据库模型在程序片段中的一种表现,或者是数据属性模型

1.2 如何定义Schema

varBlogSchema=newSchema({
      title:String,
      author:String//new Schema()中传入一个JSON对象,该对象形如 xxx:yyyy ,/xxx是一个字符串,定义了属性,yyy是一个Schema.Type,定义了属性类型});

1.3 什么是Schema.Type

  Schema.Type是由Mongoose内定的一些数据类型,基本数据类型都在其中,他也内置了一些Mongoose特有的Schema.Type。当然,你也可以自定义Schema.Type,只有满足Schema.Type的类型才能定义在Schema内。

1.4 Schema.Types

  NodeJS中的基本数据类型都属于Schema.Type,另外Mongoose还定义了自己的类型

//举例:varExampleSchema=newSchema({
      name:String,
      binary:Buffer,
      living:Boolean,
      updated:Date,
      age:Number,
      mixed:Schema.Types.Mixed,//该混合类型等同于nested
      _id:Schema.Types.ObjectId,//主键
      _fk:Schema.Types.ObjectId,//外键
      array:[],
      arrOfString:[String],
      arrOfNumber:[Number],
      arrOfDate:[Date],
      arrOfBuffer:[Buffer],
      arrOfBoolean:[Boolean],
      arrOfMixed:[Schema.Types.Mixed],
      arrOfObjectId:[Schema.Types.ObjectId]
      nested:{
        stuff:String,}});

1.5 关于Buffer

  BufferArrayBufferNodejs两种隐藏的对象,相关内容请查看NodeJS-API

1.6 关于Mixed

  Schema.Types.MixedMongoose定义个混合类型,该混合类型如果未定义具体形式。因此,如果定义具体内容,就直接使用{}来定义,以下两句等价

varAnySchema=newSchema({any:{}});varAnySchema=newSchema({any:Schema.Types.Mixed});

  混合类型因为没有特定约束,因此可以任意修改,一旦修改了原型,则必须调用markModified()

    person.anything ={x:[3,4,{y:'change'}]}
    person.markModified('anything');//传入anything,表示该属性类型发生变化
    person.save();

1.7 关于ObjectId

  主键,一种特殊而且非常重要的类型,每个Schema都会默认配置这个属性,属性名为_id,除非自己定义,方可覆盖

var mongoose =require('mongoose');varObjectId= mongoose.Schema.Types.ObjectId;varStudentSchema=newSchema({});//默认会有_id:ObjectIdvarTeacherSchema=newSchema({id:ObjectId});//只有id:ObjectId

  该类型的值由系统自己生成,从某种意义上几乎不会重复,生成过程比较复杂,有兴趣的朋友可以查看源码。

1.8 关于Array

  ArrayJavaScript编程语言中并不是数组,而是集合,因此里面可以存入不同的值,以下代码等价:

varExampleSchema1=newSchema({array:[]});varExampleSchema2=newSchema({array:Array});varExampleSchema3=newSchema({array:[Schema.Types.Mixed]});varExampleSchema4=newSchema({array:[{}]});

1.9 附言

  Schema不仅定义了文档结构使用性能,还可以有扩展插件实例方法静态方法复合索引文档生命周期钩子

  Schema可以定义插件,并且插件具有良好的可拔插性,请有兴趣的读者继续往后阅读或者查阅官方资料。

2. Schema的扩展

2.1 实例方法

  有的时候,我们创造的Schema不仅要为后面的ModelEntity提供公共的属性,还要提供公共的方法。

  下面例子比快速通道的例子更加高级,可以进行高级扩展:

varPersonSchema=newSchema({name:String,type:String});//查询类似数据PersonSchema.methods.findSimilarTypes =function(cb){returnthis.model('Person').find({type:this.type},cb);}

  使用如下:

varPersonModel= mongoose.model('Person',PersonSchema);var krouky =newPersonSchema({name:'krouky',type:'前端工程师'});
    krouky.findSimilarTypes(function(err,persons){//persons中就能查询到其他前端工程师});

2.2 静态方法

  静态方法在Model层就能使用,如下:

PersonSchema.statics.findByName =function(name,cb){this.find({name:newRegExp(name,'i'),cb});}varPersonModel= mongoose.model('Person',PersonSchema);PersonModel.findByName('krouky',function(err,persons){//找到所有名字叫krouky的人});

2.3 索引

  索引或者复合索引能让搜索更加高效,默认索引就是主键索引ObjectId,属性名为_id索引会作为一个专题来讲解

2.4 虚拟属性

  Schema中如果定义了虚拟属性,那么该属性将不写入数据库,例如:

varPersonSchema=newSchema({
      name:{
        first:String,last:String}});varPersonModel= mongoose.model('Person',PersonSchema);var krouky =newPersonModel({
      name:{first:'krouky',last:'han'}});

  如果每次想使用全名就得这样

    console.log(krouky.name.first +' '+ krouky.name.last);

  显然这是很麻烦的,我们可以定义虚拟属性

PersonSchema.virtual('name.full').get(function(){returnthis.name.first +' '+this.name.last;});

  那么就能用krouky.name.full来调用全名了,反之如果知道full,也可以反解firstlast属性

PersonSchema.virtual('name.full').set(function(name){var split = name.split(' ');this.name.first = split[0];this.name.last= split[1];});varPersonModel= mongoose.model('Person',PersonSchema);var krouky =newPersonModel({});
    krouky.name.full ='krouky han';//会被自动分解
    console.log(krouky.name.first);//krouky

2.5 配置项

  在使用new Schema(config)时,我们可以追加一个参数options来配置Schema的配置,形如:

varExampleSchema=newSchema(config,options);

  或者使用

varExampleSchema=newSchema(config);ExampleSchema.set(option,value);

  可供配置项有:safestrictcappedversionKeyautoIndex

2.5.1 safe——安全属性(默认安全)

  一般可做如下配置:

newSchema({...},{safe:true});

  当然我们也可以这样

newSchema({...},{safe:{j:1,w:2,wtimeout:10000}});

  j表示做1份日志,w表示做2个副本(尚不明确),超时时间10秒

2.5.2 strict——严格配置(默认启用)

  确保Entity的值存入数据库前会被自动验证,如果你没有充足的理由,请不要停用,例子:

varThingSchema=newSchema({a:String});varThingModel= db.model('Thing',SchemaSchema);var thing =newThing({iAmNotInTheThingSchema:true});
    thing.save();//iAmNotInTheThingSchema这个属性将无法被存储

  如果取消严格选项,iAmNotInTheThingSchema将会被存入数据库

  该选项也可以在构造实例时使用,例如:

varThingModel= db.model('Thing');var thing1 =newThingModel(doc,true);//启用严格var thing2 =newThingModel(doc,false);//禁用严格

注意:

  strict也可以设置为throw,表示出现问题将会抛出错误

2.5.3 shardKey

  需要mongodb做分布式,才会使用该属性

2.5.4 capped——上限设置

  如果有数据库的批量操作,该属性能限制一次操作的量,例如:

newSchema({...},{capped:1024});//一次操作上线1024条数据

  当然该参数也可是JSON对象,包含size、max、autiIndexId属性

newSchema({...},{capped:{size:1024,max:100,autoIndexId:true}});
2.5.5 versionKey——版本锁

  版本锁是Mongoose默认配置(__v属性)的,如果你想自己定制,如下:

newSchema({...},{versionKey:'__someElse'});

  此时存入数据库的版本锁就不是__v属性,而是__someElse,相当于是给版本锁取名字。

  具体怎么存入都是由MongooseMongoDB自己决定,当然,这个属性你也可以去除

newSchema({...},{versionKey:false});

  除非你知道你在做什么,并且你知道这样做的后果

2.5.6 autoIndex——自动索引

  该内容将在索引章节单独讲解

3. Documents

  Document是与MongoDB文档一一对应的模型,Document可等同于Entity,具有属性和操作性

注意:

  Document的`CRUD都必须经过严格验证的,参看2.5.2 Schema的strict严格配置

3.1 查询

  查询内容过多,专题讲解

3.2 更新

  有许多方式来更新文件,以下是常用的传统方式:

PersonModel.findById(id,function(err,person){
      person.name ='MDragon';
      person.save(function(err){});});

  这里,利用Model模型查询到了person对象,该对象属于Entity,可以有save操作,如果使用Model`操作,需注意:

PersonModel.findById(id,function(err,person){
      person.name ='MDragon';var _id = person._id;//需要取出主键_iddelete person._id;//再将其删除PersonModel.update({_id:_id},person,function(err){});//此时才能用Model操作,否则报错});

  update第一个参数是查询条件,第二个参数是更新的对象,但不能更新主键,这就是为什么要删除主键的原因。

  当然这样的更新很麻烦,可以使用$set属性来配置,这样也不用先查询,如果更新的数据比较少,可用性还是很好的:

PersonModel.update({_id:_id},{$set:{name:'MDragon'}},function(err){});

  需要注意,DocumentCRUD操作都是异步执行,callback第一个参数必须是err,而第二个参数各个方法不一样,updatecallback第二个参数是更新的数量,如果要返回更新后的对象,则要使用如下方法

Person.findByIdAndUpdate(_id,{$set:{name:'MDragon'}},function(err,person){
      console.log(person.name);//MDragon});

  类似的方法还有findByIdAndRemove,如同名字,只能根据id查询并作update/remove操作,操作的数据仅一条

3.3 新增

  如果是Entity,使用save方法,如果是Model,使用create方法

//使用Entity来增加一条数据var krouky =newPersonModel({name:'krouky'});
    krouky.save(callback);//使用Model来增加一条数据varMDragon={name:'MDragon'};PersonModel.create(MDragon,callback);

  两种新增方法区别在于,如果使用Model新增时,传入的对象只能是纯净的JSON对象,不能是由Model创建的实体,原因是:由Model创建的实体krouky虽然打印是只有{name:'krouky'},但是krouky属于Entity,包含有Schema属性和Model数据库行为模型。如果是使用Model创建的对象,传入时一定会将隐藏属性也存入数据库,虽然3.x追加了默认严格属性,但也不必要增加操作的报错

3.4 删除

  和新增一样,删除也有2种方式,但EntityModel都使用remove方法

4.Sub Docs

  如同SQL数据库中2张表有主外关系,Mongoose将2个Document的嵌套叫做Sub-Docs(子文档)

  简单的说就是一个Document嵌套另外一个Document或者Documents:

varChildSchema1=newSchema({name:String});varChildSchema2=newSchema({name:String});varParentSchema=newSchema({
      children1:ChildSchema1,//嵌套Document
      children2:[ChildSchema2]//嵌套Documents});

  Sub-Docs享受和Documents一样的操作,但是Sub-Docs的操作都由父类去执行

varParentModel= db.model('Parent',parentSchema);var parent =newParentModel({
      children2:[{name:'c1'},{name:'c2'}]});
    parent.children2[0].name ='d';
    parent.save(callback);

  parent在执行保存时,由于包含children2,他是一个数据库模型对象,因此会先保存chilren2[0]chilren2[1]

  如果子文档在更新时出现错误,将直接报在父类文档中,可以这样处理:

ChildrenSchema.pre('save',function(next){if('x'===this.name)returnnext(newError('#err:not-x'));next();});var parent =newParentModel({children1:{name:'not-x'}});
    parent.save(function(err){
      console.log(err.message);//#err:not-x});

4.1 查询子文档

  如果childrenparent的子文档,可以通过如下方法查询到children

var child = parent.children.id(id);

4.2 新增、删除、更新

  子文档是父文档的一个属性,因此按照属性的操作即可,不同的是在新增父类的时候,子文档是会被先加入进去的。

  如果ChildrenSchema是临时的一个子文档,不作为数据库映射集合,可以这样:

varParentSchema=newSchema({
      children:{
        name:String}});//其实就是匿名混合模式

5.Model

5.1 什么是Model

  Model模型,是经过Schema构造来的,除了Schema定义的数据库骨架以外,还具有数据库行为模型,他相当于管理数据库属性、行为的类

5.2 如何创建Model

  你必须通过Schema来创建,如下:

//先创建SchemavarTankSchema=newSchema({
      name:'String',
      size:'String'});//通过Schema创建ModelvarTankModel= mongoose.model('Tank',TankSchema);

5.2 操作Model

  该模型就能直接拿来操作,具体查看API,例如:

var tank ={'something',size:'small'};TankModel.create(tank);

注意:

  你可以使用Model来创建EntityEntity实体是一个特有Model具体对象,但是他并不具备Model的方法,只能用自己的方法。

//通过Model创建Entityvar tankEntity =newTankModel('someother','size:big');
  tankEntity.save();

6.Query

  查询是数据库中运用最多也是最麻烦的地方,这里对Query解读的并不完善,仅仅是自己的一点领悟而已。

6.1 查询的方式

  通常有2种查询方式,一种是直接查询,一种是链式查询(2种查询都是自己命名的)

6.1.1 直接查询

  在查询时带有回调函数的,称之为直接查询,查询的条件往往通过API来设定,例如:

PersonModel.findOne({'name.last':'dragon'},'some select',function(err,person){//如果err==null,则person就能取到数据});

  具体的查询参数,请查询API

6.1.2 链式查询

  在查询时候,不带回调,而查询条件通过API函数来制定,例如:

var query =PersonModel.findOne({'name.last':'dragon'});
    query.select('some select');
    query.exec(function(err,pserson){//如果err==null,则person就能取到数据});

  这种方式相对直接查询,分的比较明细,如果不带callback,则返回queryquery没有执行的预编译查询语句,该query对象执行的方法都将返回自己,只有在执行exec方法时才执行查询,而且必须有回调。

  因为query的操作始终返回自身,我们可以采用更形象的链式写法

Person.find({ occupation:/host/}).where('name.last').equals('Ghost').where('age').gt(17).lt(66).where('likes').in(['vaporizing','talking']).limit(10).sort('-occupation').select('name occupation').exec(callback);

7.Validation

  数据的存储是需要验证的,不是什么数据都能往数据库里丢或者显示到客户端的,数据的验证需要记住以下规则:

  • 验证始终定义在SchemaType
  • 验证是一个内部中间件
  • 验证是在一个Document被保存时默认启用的,除非你关闭验证
  • 验证是异步递归的,如果你的SubDoc验证失败,Document也将无法保存
  • 验证并不关心错误类型,而通过ValidationError这个对象可以访问

7.1 验证器

  1. required 非空验证
  2. min/max 范围验证(边值验证)
  3. enum/match 枚举验证/匹配验证
  4. validate 自定义验证规则

  以下是综合案例:

varPersonSchema=newSchema({
      name:{
        type:'String',
        required:true//姓名非空},
      age:{
        type:'Nunmer',
        min:18,//年龄最小18
        max:120//年龄最大120},
      city:{
        type:'String',enum:['北京','上海']//只能是北京、上海人},
      other:{
        type:'String',
        validate:[validator,err]//validator是一个验证函数,err是验证失败的错误信息}});

7.2 验证失败

  如果验证失败,则会返回err信息,err是一个对象该对象属性如下

    err.errors                //错误集合(对象)
    err.errors.color          //错误属性(Schema的color属性)
    err.errors.color.message  //错误属性信息
    err.errors.path             //错误属性路径
    err.errors.type             //错误类型
    err.name                //错误名称
    err.message                 //错误消息

  一旦验证失败,ModelEntity都将具有和err一样的errors属性

8.Middleware中间件

8.1 什么是中间件

  中间件是一种控制函数,类似插件,能控制流程中的init、validatesaveremove`方法

8.2 中间件的分类

  中间件分为两类

8.2.1 Serial串行

  串行使用pre方法,执行下一个方法使用next调用

var schema =newSchema(...);
    schema.pre('save',function(next){//做点什么next();});
8.2.2 Parallel并行

  并行提供更细粒度的操作

var schema =newSchema(...);
    schema.pre('save',function(next,done){//下一个要执行的中间件并行执行next();
      doAsync(done);});

8.3 中间件特点

  一旦定义了中间件,就会在全部中间件执行完后执行其他操作,使用中间件可以雾化模型,避免异步操作的层层迭代嵌套

8.4 使用范畴

  1. 复杂的验证
  2. 删除有主外关联的doc
  3. 异步默认
  4. 某个特定动作触发异步任务,例如触发自定义事件和通知

  例如,可以用来做自定义错误处理

    schema.pre('save',function(next){var err =newEerror('some err');next(err);});
    entity.save(function(err){
      console.log(err.message);//some err});

http://cnodejs.org/topic/504b4924e2b84515770103dd