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/example/test1/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学习一(环境和第一个例子)的更多相关文章
- GLSL着色语言学习。橙皮书第一个例子GLSL+OpenTK+F#的实现。
Opengl红皮书有选择的看了一些,最后的讲着色语言GLSL的部分看的甚为不理解,然后找到Opengl橙皮书,然后就容易理解多了. 在前面,我们或多或少接触到Opengl的处理过程,只说前面一些处理, ...
- CUDA学习,环境配置和简单例子
根据摩尔定律,每18个月,硬件的速度翻一番.纵使CPU的主频会越来越高,但是其核数受到了极大的限制,目前来说,最多只有8个或者9个核.相比之下,GPU具有很大的优势,他有成千上万个核,能完成大规模的并 ...
- ElasticSearch 5学习(5)——第一个例子(很实用)
想要知道ElasticSearch是如何使用的,最快的方式就是通过一个简单的例子,第一个例子将会包括基本概念如索引.搜索.和聚合等,需求是关于公司管理员工的一些业务. 员工文档索引 业务首先需要存储员 ...
- ElasticSearch 5学习(5)——第一个例子
想要知道ElasticSearch是如何使用的,最快的方式就是通过一个简单的例子,第一个例子将会包括基本概念如索引.搜索.和聚合等,需求是关于公司管理员工的一些业务. 员工文档索引 业务首先需要存储员 ...
- Springboot环境搭建_第一个例子
首先创建一个maven项目 maven项目创建完成之后,找到pom.xml配置节点.需要springboot-starter-web ,springboot-starter-test,springbo ...
- MXNet学习~第一个例子~跑MNIST
反正基本上是给自己看的,直接贴写过注释后的代码,可能有的地方理解不对,你多担待,看到了也提出来(基本上对未来的自己说的),三层跑到了97%,毕竟是第一个例子,主要就是用来理解MXNet怎么使用. #导 ...
- MXNet学习-第一个例子:训练MNIST数据集
一个门外汉写的MXNET跑MNIST的例子,三层全连接层最后验证率是97%左右,毕竟是第一个例子,主要就是用来理解MXNet怎么使用. #导入需要的模块 import numpy as np #num ...
- 【转】APUE学习1:迈出第一步,编译myls.c
原文网址:http://blog.csdn.net/sddzycnqjn/article/details/7252444 注:以下写作风格均学习自潘云登前辈 /******************** ...
- supervessel-免费云镜像︱GPU加速的Caffe深度学习开发环境
开发环境介绍 在SuperVessel云上,我们为大家免费提供当前火热的caffe深度学习开发环境.SuperVessel的Caffe有如下优点: 1) 免去了繁琐的Caffe环境的安装配置,即申请即 ...
随机推荐
- WPF自定义控件与样式(12)-缩略图ThumbnailImage /gif动画图/图片列表
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要针对WPF项目 ...
- Office英语学习好帮手
Office提供了强大实用的英语学习助手,它可以自动翻译中英文,还可以显示详尽的解释帮助信息,当然标准的发音也是必不可少的.如何启动屏幕取词翻译功能呢?如何让office自动取词并翻译呢?如何收听单词 ...
- annotation-config vs component-scan – Spring Core--转
原文地址:http://techidiocy.com/annotation-config-vs-component-scan-spring-core/ <context:annotation-c ...
- 百度地图JavaScript API覆盖物旋转时出现偏移
在项目中,调用百度地图JavaScript API,做覆盖物的旋转再添加到地图上,结果出现偏移了. 调试过程中的效果图: 发现图片的旋转并不是按车子的中心来的,而是之外的一个点.最后发现犯了一个很细节 ...
- Testing - Tips
1 --- 冒烟测试.可用性测试和回归测试的区别? 在测试领域中,冒烟测试(smoke test).可用性测试(sanity test)和回归测试(regression test)彼此之间很相似,范围 ...
- Eclipse快捷键(转)
Ctrl+1 快速修复(最经典的快捷键,就不用多说了)Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ 复制当前行到上一行(复制增加)Alt+↓ 当 ...
- Android反编译(三)之重签名
Android反编译(三) 之重签名 [目录] 1.原理 2.工具与准备工作 3.操作步骤 4.装X技巧 5.问题 1.原理 1).APK签名的要点 a.所有的应用程序都必须有数字证书 ,Androi ...
- app令牌的一个token实现
app登陆验证不能使用session来判断了.然后查资料都说用令牌,没找到合适的方法,我的眼界太小.另外,越来越感觉基础的重要,比如,session是什么,我竟无言以对.不知道session是什么,怎 ...
- plsql导入excel时报错:ORA-01036: 非法变量名/编号
导入oracle数据,选择工具->odbc导入->Excel 然后关于日期的插入出错,修改后如下:
- 递归查询树形结构的SQL
最近项目中要递归树形,案例如下: 测试数据: ),PID ),Name )) ',NULL ,'山东省' ','烟台市' ','招远市' ','青岛市' ',NULL ,'四会市' ','清远市' ' ...