Day 24: 使用Yeoman自动构建Ember项目

简介: 到目前为止,我们这个系列讨论了Bower、AngularJS、GruntJS、PhoneGap、Meteor、Ember和TimelineJS等JavaScript技术。今天的《30天学习30种新技术》,我决定学习前端开发的效率工具Yeoman。本文将首先介绍Yeoman的基本情况,接着我们会使用Yeoman开发一个Ember应用。本文不会介绍EmberJS的基本知识,所以请参考day 19。

编者注:我们发现了有趣的系列文章《30天学习30种新技术》,正在翻译,一天一篇更新,年终礼包。下面是第 天的内容。


到目前为止,我们这个系列讨论了BowerAngularJSGruntJSPhoneGapMeteorEmberTimelineJS等JavaScript技术。今天的《30天学习30种新技术》,我决定学习前端开发的效率工具Yeoman。本文将首先介绍Yeoman的基本情况,接着我们会使用Yeoman开发一个Ember应用。本文不会介绍EmberJS的基本知识,所以请参考day 19

image.png

Yeoman是什么?

Yeoman按照官方说法,它不只是一个工具,还是一个工作流。它其实包括了三个部分yo、grunt、bower,分别用于项目的启动、文件操作、包管理。

  1. Yo: Yo是一个项目初始化工具,可以生成一套启动某类项目必需的项目文件。
  2. GruntJS: GruntJS是基于JavaScript的命令行构建工具,它可以帮助开发者们自动化重复性的工作。阅读day 5获取更多信息。
  3. Bower: Bower是一个客户端技术的软件包管理器,它可用于搜索、安装和卸载如JavaScript、HTML、CSS之类的网络资源。阅读day 1获取更多信息。


我为什么关心Yeoman

如果你需要说服自己学习Yeoman,你可以读读Yeoman网站上的whyyeoman


安装

使用npm安装:

npm install -g yeoman

安装Yeoman Ember生成器

Yeoman依赖生成器为web项目提供支架。所有的现代JavaScript MV* 框架都有相应的生成器。本文使用Ember:

npm install -g generator-ember

我们将开发一个社交化书签应用,允许用户提交和分享链接。你可以在这里查看这个应用。这个应用和我们day 19开发的一样。


Github仓库

今天的示例应用代码可从Github取得。


创建Ember应用

现在开始应用开发。首先创建项目目录,接着运行yo ember命令,它会询问你是否使用Twitter Bootstrap。我习惯在自己的项目中使用Bootstrap,所以我选了是。

; mkdir getbookmarks

; cd getbookmarks

; yo ember

    _-----_

   |       |

   |--(o)--|   .--------------------------.

  ---------  |    Welcome to Yeoman,    |

   ( __ )   |   ladies and gentlemen!  |

   /___A___\   '__________________________'

    |  ~  |

  __'.___.'__

[?] Would you like to include Twitter Bootstrap for Sass? Yes

之后Yeoman会创建一个Ember应用,自动使用bowernpm安装依赖。

现在让我们看看Yeoman生成的Ember应用。应用有三个顶层目录:appnode_modulestest。还有一些配置文件:.bowerrc.gitignore.jshintrcGruntfile.jspackage.json。目录结构如下所示。

image.png

所有的应用相关代码都在app目录下。目录结构遵循Ember的最佳实践。

image.png

  1. bower_components目录包括了客户端依赖,例如Ember、Twitter Bootstrap,等等。Bower在所有文件夹内安装所有依赖。
  2. image目录包括了应用相关的图像。Yeoman会优化image目录内的图片。
  3. index.html包含了所有的ember.js依赖,所有的bootstrap依赖,以及build注释(Gruntfile.js可以据此替换或移除引用的未优化的脚本和样式表)。
  4. scripts目录包含了Ember应用的controller、view、model和route。
  5. styles目录包含了应用相关的css文件。
  6. templates目录包含了应用的handlebar模板。


现在我们可以启动预览服务器了:

grunt server


这会使用系统默认浏览器打开应用:

image.png

生成Story Model

我们在day19中开发的GetBookmarks应用中创建了一个Ember Model:Story。Yeoman的次级生成器可以用来构建项目的部分,包括model。运行如下命令生成Story model:

yo ember:model Story

命令的输出如下:

  create app/scripts/models/story_model.js

  invoke   ember:controller:/usr/local/lib/node_modules/generator-ember/model/index.js

  create     app/scripts/controllers/stories_controller.js

  create     app/scripts/controllers/story_edit_controller.js

  create     app/scripts/routes/stories_route.js

  create     app/scripts/routes/story_route.js

  create     app/scripts/routes/story_edit_route.js

  invoke       ember:view:/usr/local/lib/node_modules/generator-ember/controller/index.js

  create         app/scripts/views/story_view.js

  create         app/scripts/views/story_edit_view.js

  create         app/scripts/views/stories_view.js

  create         app/templates/story.hbs

  create         app/templates/story_edit.hbs

  create         app/templates/stories.hbs

  create         app/scripts/views/bound_text_field_view.js

  invoke       ember:router:/usr/local/lib/node_modules/generator-ember/controller/index.js

conflict         app/scripts/router.js

[?] Overwrite app/scripts/router.js? overwrite

   force         app/scripts/router.js

这会在app/scripts/models目录下生成story_model.js,同时会生成相应的view、controller和route。

修改下story_model

Emberapp.Story = DS.Model.extend({

 url : DS.attr('string'),

   tags : DS.attr('string'),

   fullname : DS.attr('string'),

   title : DS.attr('string'),

   excerpt : DS.attr('string'),

   submittedOn : DS.attr('date')

});

重新启动Grunt server以便改动生效。


安装Ember LocalStorage适配器

我们将使用HTML 5 LocalStorage来存储数据。使用bower安装适配器。

bower install --save ember-localstorage-adapter

然后更新index.html页面,添加依赖:

<scriptsrc="bower_components/ember-localstorage-adapter/localstorage_adapter.js"></script>

同时更新app/scripts/store.js,配置应用使用LSAdapter:

Getbookmarks.Store = DS.Store.extend();

Getbookmarks.ApplicationAdapter = DS.LSAdapter.extend({

 namespace: 'stories'

});

更新路由

修改router.js:

Getbookmarks.Router.map(function () {

 this.resource('index',{path : '/'});

 this.resource('story', { path: '/story/:story_id' });

 this.resource('story_edit', { path: '/story/new' });

});

提交新报道

我们首先添加用户访问#/story/new后会出现的表单。修改app/templates/story_edit.hbs

<formclass="form-horizontal"role="form">

     <divclass="form-group">

       <labelfor="title"class="col-sm-2 control-label">Title</label>

       <divclass="col-sm-10">

         <inputtype="title"class="form-control"id="title"name="title"placeholder="Title of the link"required>

       </div>

     </div>

     <divclass="form-group">

       <labelfor="excerpt"class="col-sm-2 control-label">Excerpt</label>

       <divclass="col-sm-10">

         <textareaclass="form-control"id="excerpt"name="excerpt"placeholder="Short description of the link"required></textarea>

       </div>

     </div>

     <divclass="form-group">

       <labelfor="url"class="col-sm-2 control-label">Url</label>

       <divclass="col-sm-10">

         <inputtype="url"class="form-control"id="url"name="url"placeholder="Url of the link"required>

       </div>

     </div>

     <divclass="form-group">

       <labelfor="tags"class="col-sm-2 control-label">Tags</label>

       <divclass="col-sm-10">

         <textareaid="tags"class="form-control"name="tags"placeholder="Comma seperated list of tags"rows="3"required></textarea>

       </div>

     </div>

     <divclass="form-group">

       <labelfor="fullname"class="col-sm-2 control-label">Full Name</label>

       <divclass="col-sm-10">

         <inputtype="text"class="form-control"id="fullname"name="fullname"placeholder="Enter your Full Name like Shekhar Gulati"required>

       </div>

     </div>

     <divclass="form-group">

       <divclass="col-sm-offset-2 col-sm-10">

         <buttontype="submit"class="btn btn-success"{{action'save'}}>Submit Story</button>

       </div>

     </div>

 </form>

现在,访问 http://localhost:9000/#/story/new 可以看到提交报道的表单。

更新StoryEditController,将数据持续化入本地存储:

Getbookmarks.StoryEditController = Ember.ObjectController.extend({

 save: function(){

   var url = $('#url').val();

       var tags = $('#tags').val();

       var fullname = $('#fullname').val();

       var title = $('#title').val();

       var excerpt = $('#excerpt').val();

       var submittedOn = newDate();

       var store = this.get('store');

       console.log('Store .. '+store);

       var story = store.createRecord('story',{

           url : url,

           tags : tags,

           fullname : fullname,

           title : title,

           excerpt : excerpt,

           submittedOn : submittedOn

       });

   story.save();

   this.transitionToRoute('index');

 }

});

列出所有报道

接下来我们要实现的功能是在侧边栏展示报道列表。

application_route.js,我们从本地存储获取所有的报道。

Getbookmarks.ApplicationRoute = Ember.Route.extend({

   model : function(){

       var stories = this.get('store').findAll('story');

       return stories;

   }

});

接着我们更新application.hbs,为每个报道的标题添加链接:

<div>

   <navclass="navbar navbar-default navbar-fixed-top"role="navigation">

       <divclass="navbar-header">

           <buttontype="button"class="navbar-toggle"data-toggle="collapse"data-target=".navbar-ex1-collapse">

               <spanclass="sr-only">Toggle navigation</span>

               <spanclass="icon-bar"></span>

               <spanclass="icon-bar"></span>

               <spanclass="icon-bar"></span>

           </button>

           <aclass="navbar-brand"href="#">GetBookmarks</a>

       </div>

       <divclass="collapse navbar-collapse navbar-ex1-collapse">

           <ulclass="nav navbar-nav pull-right">

               <li>{{#link-to'story_edit'}}<spanclass="glyphicon glyphicon-plus"></span> Submit Story{{/link-to}}</li>

           </ul>

       </div>

   </nav>

   <divclass="container"id="main">

       <divclass="row">

           <div>

               <divclass="col-md-3">

                   <divclass="well sidebar-nav">

                       <tableclass='table'>

                         <thead>

                           <tr><th>Recent Stories</th></tr>

                         </thead>

                         {{#each controller}}

                           <tr><td>

                           {{#link-to'story' this}}

                             {{title}}

                           {{/link-to}}

                           </td></tr>

                         {{/each}}

                       </table>

                   </div>

               </div>

               <divclass="col-md-9">

                   {{outlet}}

               </div>

           </div>

       </div>

   </div>

</div>

应用的用户界面会刷新。


查看单独的报道

最后要添加的功能是,用户访问 http://localhost:9000/#/story/:id 的时候可以查看单独的报道。:id对应于story id。修改story_routejs

Getbookmarks.StoryRoute = Ember.Route.extend({

 model : function(params){

       var store = this.get('store');

       return store.find('story',params.story_id);

 }

});

修改app/templates/story.hbs

<h1>{{title}}</h1>

<h2> by {{fullname}}<smallclass="muted">{{submittedOn}}</small></h2>

{{#each tagnames}}

 <spanclass="label label-primary">{{this}}</span>

{{/each}}

<hr>

<pclass="lead">

     {{excerpt}}

</p>

为生产环境构建

最后,我们运行grunt build命令创建一个可分发的应用。grunt build命令将app目录下的源文件转换成dist目录下的可分发的应用。

grunt build

今天就这些。保持反馈。

相关文章
|
编解码 算法 搜索推荐
淘宝人生里的虚拟人像渲染技术
全程干货,淘宝人生里的虚拟人像是如何实现的?
淘宝人生里的虚拟人像渲染技术
|
8月前
|
存储 人工智能 供应链
中国CRM系统推荐:如何选择最适合企业的客户管理工具?
在数字化转型中,CRM系统成为企业提升销售效率与客户体验的关键工具。中国CRM市场虽增长迅速,但企业选型常遇功能冗余、数据安全及移动化能力不足等问题。本文分析主流CRM如销售易(腾讯旗下)、红圈营销、EC六度人和的核心优势及适用场景,并提出从需求匹配、成本评估到数据合规的决策维度。未来,AI赋能与行业垂直化将成趋势,适配的CRM不仅是工具,更是战略资产。
|
机器学习/深度学习 搜索推荐 大数据
大数据与教育:学生表现分析的工具
【10月更文挑战第31天】在数字化时代,大数据成为改善教育质量的重要工具。本文探讨了大数据在学生表现分析中的应用,介绍学习管理系统、智能评估系统、情感分析技术和学习路径优化等工具,帮助教育者更好地理解学生需求,制定个性化教学策略,提升教学效果。尽管面临数据隐私等挑战,大数据仍为教育创新带来巨大机遇。
|
Java
什么是java回调函数
什么是java回调函数
558 1
什么是java回调函数
|
算法 数据可视化 Java
数学建模常用算法:启发式优化算法合辑(内含多种智能优化算法,使用java实现算法、详细注释、并进行结果可视化)
数学建模常用算法:启发式优化算法合辑(内含多种智能优化算法,使用java实现算法、详细注释、并进行结果可视化)
1314 2
|
Prometheus Kubernetes 监控
快速部署 Prometheus 社区版
Prometheus 是一个开源的系统监控和报警系统,最初由 SoundCloud 开发,并在 2012 年作为开源项目发布。它现在是 Cloud Native Computing Foundation(CNCF)的一部分,与 Kubernetes 等其他知名项目一起,成为云原生生态系统的重要组成部分。本文介绍通过计算巢快速部署 Prometheus 社区版。
快速部署 Prometheus 社区版
|
存储 Kubernetes 容器
k8s创建NFS动态存储
k8s创建NFS动态存储
|
弹性计算 关系型数据库 MySQL
阿里云服务器经济型e实例2核2G3M带宽99元搭建网站图文教程参考
经济型e实例2核2G,3M固定带宽,40G ESSD Entry云盘,价格只要99元,这是阿里云精心为开发者和普通企业用户推出的一款上云首选必备产品,可用于中小型的web应用以及企业应用。本文为大家展示使用这款云服务器搭建网站的相关教程,以供参考。
阿里云服务器经济型e实例2核2G3M带宽99元搭建网站图文教程参考
|
缓存 前端开发 JavaScript
【专栏:HTML与CSS移动端开发篇】移动端网页性能优化策略
【4月更文挑战第30天】本文探讨了移动端网页性能优化的重要性,并提出了优化策略。HTML方面,建议精简结构、使用语义化标签、异步加载脚本和压缩文件;CSS优化包括精简样式、使用CSS3动画、媒体查询和压缩文件。其他策略涉及图片和字体压缩、缓存利用、数据压缩、减少HTTP请求及根据网络状态调整加载。综合运用这些策略能提升网页性能和用户体验。
316 6