编者注:我们发现了有趣的系列文章《30天学习30种新技术》,正在翻译,一天一篇更新,年终礼包。下面是第 天的内容。
到目前为止,我们这个系列讨论了Bower、AngularJS、GruntJS、PhoneGap、Meteor、Ember和TimelineJS等JavaScript技术。今天的《30天学习30种新技术》,我决定学习前端开发的效率工具Yeoman。本文将首先介绍Yeoman的基本情况,接着我们会使用Yeoman开发一个Ember应用。本文不会介绍EmberJS的基本知识,所以请参考day 19。
Yeoman是什么?
Yeoman按照官方说法,它不只是一个工具,还是一个工作流。它其实包括了三个部分yo、grunt、bower,分别用于项目的启动、文件操作、包管理。
Yo: Yo是一个项目初始化工具,可以生成一套启动某类项目必需的项目文件。
GruntJS: GruntJS是基于JavaScript的命令行构建工具,它可以帮助开发者们自动化重复性的工作。阅读day 5获取更多信息。
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应用,自动使用bower
和npm
安装依赖。
现在让我们看看Yeoman生成的Ember应用。应用有三个顶层目录:app
、node_modules
和test
。还有一些配置文件:.bowerrc
、.gitignore
、.jshintrc
、Gruntfile.js
和package.json
。目录结构如下所示。
所有的应用相关代码都在app
目录下。目录结构遵循Ember的最佳实践。
bower_components
目录包括了客户端依赖,例如Ember、Twitter Bootstrap,等等。Bower在所有文件夹内安装所有依赖。image
目录包括了应用相关的图像。Yeoman会优化image
目录内的图片。index.html
包含了所有的ember.js
依赖,所有的bootstrap依赖,以及build
注释(Gruntfile.js可以据此替换或移除引用的未优化的脚本和样式表)。scripts
目录包含了Ember应用的controller、view、model和route。styles
目录包含了应用相关的css文件。templates
目录包含了应用的handlebar模板。
现在我们可以启动预览服务器了:
grunt server
这会使用系统默认浏览器打开应用:
生成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
页面,添加依赖:
同时更新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
:
现在,访问 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 = new Date();
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
,为每个报道的标题添加链接:
{{outlet}}
应用的用户界面会刷新。
查看单独的报道
最后要添加的功能是,用户访问 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
:
{{title}}
by {{fullname}} {{submittedOn}}
{{#each tagnames}}
{{this}}
{{/each}}
{{excerpt}}
为生产环境构建
最后,我们运行grunt build
命令创建一个可分发的应用。grunt build
命令将app
目录下的源文件转换成dist
目录下的可分发的应用。
grunt build
今天就这些。保持反馈。
原文 Day 24: Yeoman Ember--The Missing Tutorial
翻译 SegmentFault