emberjs初学记要
code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}
code, pre tt {
background-color: transparent;
border: none;
}
-->
初学emberjs
博客:http://www.cnblogs.com/xiangbing/p/emberjs-test.html
案例:http://www.lovewebgames.com/emberjs/test/index.html
源码:https://github.com/tianxiangbing/emberjs-test
准备工作
首页我们要做的是从网上下载下来emberjs相关的文件,目前在1.x的版本中,ember是要依赖jquery(v1.7.1~2.2.0) 和handlebars(v1.x)的,有一个比较好的方式来得到这些资源,那就是用bower.bower的安装很简单:
- npm install -g bower
装完bower就可以使用bower来下载资源了,比如我们要下载jquery 1.9.1版本的,我们可以这样写
- bower install jquery#1.9.
它会在当前目录下建一个bower_components的目录,把jquery的文件下载到jquery文件目录下.我们也可以把git上的项目发布到bower上,然后再从bower安装到本地,具体方法可以看这里http://blog.fens.me/nodejs-bower-intro/
我的案例已经发布在bower上,你可以直接用以下命令获取
- bower install emberjs-test
点开bower_components下的test1目录,执行
- npm install
安装grunt-watch,方便开发
再下载ember相关的资源
bower.json:
- "dependencies": {
- "jquery": "~1.9.1",
- "ember": "~1.13.10",
- "handlebars":"~1.3.0",
- "ember-data":"~1.13.11"
- }
执行 bower install
查看资源列表 bower list
如图所示
开始一个例子
然后我们要根据这些文件做一个简单的例子,我们新建一个html页面index.html,引用js文件,代码如下:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>emberjs 初学记要</title>
- <script type="text/javascript" src="http://localhost:9090/livereload.js"></script>
- </head>
- <body>
- <script type="text/javascript" src="bower_components/jquery/jquery.min.js"></script>
- <script type="text/javascript" src="bower_components/handlebars/handlebars.min.js"></script>
- <script type="text/javascript" src="bower_components/ember/ember.min.js"></script>
- </body>
- </html>
这里看到我在head里多引入了一个livereload.js
,这个文件是使用grunt watch
时生成的,可以动态的改变页面,你可以使用chrome的插件livereload.
好了,准备工作做好了之后 ,我们就可以编写首页的模板了,在页面添加如下代码:
- <script type="text/x-handlebars">
- 首页
- </script>
然后新建一个js文件,这里命名为app.js,放在js目录下,引入.
- window.App = Ember.Application.create();
这时会发现页面上什么都没有,然后在console里还报了一个错:
- Uncaught Error: Cannot call `compile` without the template compiler loaded. Please load `ember-template-compiler.js` prior to calling `compile`.
这个错误的大致意思好像是说我没有ember-template-compiler.js文件,但奇了怪的是,所以解析模板时出错了;但是在更早期的版本里是不需要的,可能是后期为了移除handlebars所以独立出来了吧,在bower_components/ember
中还真有这么个文件,好吧,引入它.
- <script type="text/javascript" src="bower_components/jquery/jquery.min.js"></script>
- <script type="text/javascript" src="bower_components/handlebars/handlebars.min.js"></script>
- <script type="text/javascript" src="bower_components/ember/ember-template-compiler.js"></script>
- <script type="text/javascript" src="bower_components/ember/ember.min.js"></script>
- <script type="text/javascript" src="js/app.js"></script>
好了,页面终于出现内容了,然后我们在模板中加入outlet
,这是一个其他模块的入口,然后我们在app.js中加入其他的模块路由.
- App.Router.map(function(){
- this.resource('add',{path:'add'});
- });
这里可以使用resource也可以直接用route
- this.route('add')
据说它们间的区别就是resource可以有子路由,但route已经是最小的路由了,所以可以理解为,大的类目时用recource,终极时用route,你开心就好。 然后我们添加add的模板,这里add的模板id要和link-to的参数一致,并且跟resource或route的第一个参数一样,path参数指的是url里的hash值.
- <script type="text/x-handlebars" id="add">
- <table>
- <tr>
- <td>标题</td>
- <td><input type="text" /></td>
- </tr>
- <tr>
- <td>内容</td>
- <td><textarea></textarea></td>
- </tr>
- <tr>
- <td></td>
- <td><input type="button" value="确认"></td>
- </tr>
- </table>
- </script>
这里有一个操作,所以应该有个Controller,我们先在app.js里加上这个controller.
- App.AddController=Ember.Controller.extend({
- actions:{
- new:function(){
- console.log('new')
- var title = $('#title').val();
- var content = $('#content').val();
- //do save
- }
- }
- });
它的命名规则是单词首字母大写,然后ember会把它注册到add这个模块里,这样你就可以在add模板中使用这个控制器了。把按钮改掉
- <input type="button" value="确认" {{action "new"}}>
由于我们现在还没有使用localStorage这类本地存储,所以我们可以使用变量来临时的保存一下,但实际的应用中,似乎更多的是与服务器的交互。 它义数组var data=[];
然后再action/new
下加入
- data.push({title:title,content:content});
- this.transitionToRoute('index');
transitionToRoute
的意思就是转到另一个路由去。我们这里转到首页去,然后我们看到一片空白的首页,还不知道是什么情况,因为还没有写代码让刚才加入的记录显示出来,好,我们在首页的模板中把记录each出来.
- <script type="text/x-handlebars" id="index">
- <ol>
- {{#each model}}
- <li>{{title}}</li>
- {{/each}}
- </ol>
- </script>
这里each
的是model
,如果直接each .
会导致不更新。然后我们添加一个IndexRoute来返回一个数据集.
- App.IndexRoute = Ember.Route.extend({
- model: function() {
- return data
- }
- });
这里的IndexRoute就会默认在路由到index首页时调用。
我们在添加一个查看的按钮查看详情,为了能找到当前记录,我们给每条记录加一个index属性记录当前索引:
- data.push({
- title: title,
- content: content,
- index:data.length
- });
- <li>{{title}}{{#link-to "info" this}}查看{{/link-to}}</li>
不知道为什么在这里不能直接取@index
索引,所以只能我们在每条记录里加个唯一值。然后在路由中加上resouce
- this.resource('index', {
- path: '/'
- }, function() {
- this.resource('info', {
- path: 'info/:index'
- })
- })
这里我们把info的路由放在了index的下面,这样,就可以达到index和info同时存在了。这里要在index的模板中加上一个{{outlet}}
才行。
- {{model.title}}
- {{model.content}}
同样的情况出现了,我要加上model才行,不明白的为什么{{title}}
可以取出来content一定要{{model.content}}
才行。在InfoRoute中返回当前的数组值
- App.InfoRoute = Ember.Route.extend({
- model: function(param) {
- console.log(data[param.index].content)
- return data[param.index]
- }
- });
在详情模板中加入编辑按钮,我们根据一个值来判断是显示“编辑”还是“保存”.
- <div style="float:left;">
- <h1>{{model.title}}</h1>
- <p>
- {{model.content}}
- </p>
- {{#if isEditing}}
- <button {{action "save"}}>保存</button>
- {{else}}
- <button {{action "edit"}}>编辑</button>
- {{/if}}
- </div>
这里的isEditing是在Controller
的action
中新增的一个属性,在actions
中新增save和edit方法
- App.InfoController = Ember.ObjectController.extend({
- actions: {
- isEditing: false,
- edit: function() {
- this.set('isEditing',true);
- },
- save:function(){
- this.set('isEditing',false);
- }
- }
- });
这里的值都要使用set方法来改变,否则不会导致页面的刷新模板.然后我们加入一个子模板来显示编辑的内容。
- <script type="text/x-handlebars" id="post/edit">
- <table>
- <tr>
- <td>标题</td>
- <td>{{input type="text" value=title}}</td>
- </tr>
- <tr>
- <td>内容</td>
- <td>{{textarea value=model.content}}</td>
- </tr>
- <tr>
- <td></td>
- <td><input type="button" value="确认" {{action "save"}}></td>
- </tr>
- </table>
- </script>
这里用的是{{input}}
方式的控件,这样就可以实现传说中的双向绑定了,它是基于Ember.TextField
类的,所以也是可以自定义一个Input控件的。如下官方例子所示input api:
- Todos.EditTodoView = Ember.TextField.extend({
- didInsertElement: function() {
- this.$().focus();
- }
- });
- Ember.Handlebars.helper('edit-todo', Todos.EditTodoView);
然后就莫名其妙地完成了保存操作,好吧,我以为我还要save一下,官方的例子是使用的model,所以要对先this.get('model).save()
一下才会有用。
最后我们要做的就是删除了,先加一个action为del的链接按钮:
- {{#each model}}
- <li>{{title}}{{#link-to "info" this}}查看{{/link-to}} <a href="javascript:void(0)" {{action "del" index}}>删除</a></li>
- {{/each}}
然后在IndexController中新增del的action
- App.IndexController = Ember.ArrayController.extend({
- actions: {
- del: function(index) {
- var d = this.get('model');
- console.log(d)
- var obj = d.findBy('index',index)
- d.removeObject(obj)
- }
- }
- });
这里的问题是,我们要对model进行操作,才能实时的反应到页面上,看了下model的方法,可以使用findBy
找出该元素,再进行removeObject
最终,我们就完成了一整个的增删改操作了。因为我也是在学习过程中,如果有什么不对的地方,请指出纠正吧!也欢迎加入我的Q群77813547
emberjs初学记要的更多相关文章
- emberjs学习一(环境和第一个例子)
code { margin: 0; padding: 0; white-space: pre; border: none; background: transparent; } code, pre t ...
- emberjs学习二(ember-data和localstorage_adapter)
emberjs学习二(ember-data和localstorage_adapter) 准备工作 首先我们加入ember-data和ember-localstorage-adapter两个依赖项,使用 ...
- DDD初学指南
去年就打算总结一下,结果新换的工作特别忙,就迟迟没有认真动手.主要内容是很多初学DDD甚至于学习很长时间的同学没有弄明白DDD是什么,适合什么情况.这世界上没有银弹,抛开了适合的场景孤立的去研究DDD ...
- gulp初学
原文地址:gulp初学 至于gulp与grunt的区别,用过的人都略知一二,总的来说就是2点: 1.gulp的gulpfile.js 配置简单而且更容易阅读和维护.之所以如此,是因为它们的工作方式不 ...
- 初学seaJs模块化开发,利用grunt打包,减少http请求
原文地址:初学seaJs模块化开发,利用grunt打包,减少http请求 未压缩合并的演示地址:demo2 学习seaJs的模块化开发,适合对seajs基础有所了解的同学看,目录结构 js — —di ...
- 初学Vue2.0--基础篇
概述: 鉴于本人初学,使用的编译器是webStorm,需添加对VUE的支持,添加方法可以参考 http://www.jianshu.com/p/142dae4f8b51. 起步: 1. 扎实的 Jav ...
- 初学Python
初学Python 1.Python初识 life is short you need python--龟叔名言 Python是一种简洁优美语法接近自然语言的一种全栈开发语言,由"龟叔&quo ...
- Javascript初学篇章_5(对象)
对象 Javascript是一种面向对象的语言,因此可以使用面向对象的思想来进行javascript程序设计对象就是由一些彼此相关的属性和方法集合在一起而构成的一个数据实体.举个例子,一只猫是个对象, ...
- 初学Objective-C语言需要了解的星星点点
其实大多数开发初学者都有一些相同的特点,可以说是一种“职业病”.Most有其他平台开发基础的初学者,看到Xcode就想摩拳擦掌:看到Interface Builder就想跃跃欲试:而 ...
随机推荐
- [Z] 关于c++ typename的另一种用法
在看c++ primer的时候见到了一下这种用法: typedef typename std::vector<int>::size_type size_type; 觉得这里面的typena ...
- python-redis 入门
redis官网http://redis.io Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. Redis是一 ...
- HTML5[6]:多行文本显示省略号
CSS3新增text-overflow: ellipse; 只支持单行文本 如果是多行文本, 在无法完全显示的情况下,可以按下面这样写: overflow:hidden; display: -webk ...
- zepto - toggle
<input type="text" value="123456789" /> <div id="too_long"> ...
- linux rdate
检查服务器时间,发现服务器时间与当前时间错了很多.于是调整. 使用ntpdate ,不管如何设置,包括关闭防火期,设置ntp.conf,结果都不成功. 随即使用网上提供的另外一种方法,临时先解决一下燃 ...
- Lua中的require
lua中的require机制 为了方便代码管理,通常会把lua代码分成不同的模块,然后在通过require函数把它们加载进来.现在看看lua的require的处理流程.1.require机制相关 ...
- ReflectionToStringBuilder
1. 使用背景 后台接口需要在接口调用的初期,记录下面查询(修改)对象的参数. 2. 使用方法 通过Apache 工具类 输出entity对象所有属性值 <dependency> < ...
- Android 学习笔记之Volley开源框架解析(三)
学习内容: 1.CacheDispatcher缓存请求调度... 2.Cache缓存数据的保存... 3.DiskBasedCache基于磁盘的缓存类实现方式... 前面说到使用Volley发 ...
- (翻译)为你的MVC应用程序创建自定义视图引擎
Creating your own MVC View Engine For MVC Application 原文链接:http://www.codeproject.com/Articles/29429 ...
- UWP开发入门(十一)——Attached Property的简单应用
UWP中的Attached Property即附加属性,在实际开发中是很常见的,比如Grid.Row: <Grid Background="{ThemeResource Applica ...