emberjs學習一(環境和第一個例子)


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.1

它會在當前目錄下建一個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是在Controlleraction中新增的一個屬性,在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群js,html5,jquery,dojo前端群77813547


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM