[Javascript] Backbone.js (二) Model

【如果覺得文章寫的好的話希望能按一下讚或分享喔】

延續上一篇 [Javascript] Backbone.js (一) Hello backbone,本篇來談談 Backbone 當中的 Model

在 MVC 的架構當中,Model 通常被當成資料的容器,在 backbone 當中也不例外,Model 可以承載所有頁面當中常取用的資料,或是 server 回傳的資料等

特別的是,Backbone 當中的 View 採用了 Observer Pattern 的設計,當使用者改變 Model 的值時,對應的事件會被 Trigger,而達成 UI 自動更新或是 Ajax 自動啟動等

 

 

宣告 Model

Model 是用來存放資料的類別,可供 Backbone 的其他類別進行資料的取用,以下程式碼可以宣告一個簡單的 Model :

//Backbone Model
var user = new Backbone.Model({
  firstName: "Jack",
  lastName: "divaka"
});

 

或是你也可以宣告一個 JSON 物件在 Model 當中:

//Backbone Model
model = new Backbone.Model({
    data:[
        { text: "Google", href: "http://google.com" },
        { text: "Facebook", href: "http://facebook.com" },
        { text: "Youtube", href: "http://youtube.com" }
    ]
});

 

取得 Model 資料

如果只是很單純的 Model,只要用逗點即可取得 Model 內容

//較單純的 Model
var user = new Backbone.Model({
  firstName: "Jack",
  lastName: "divaka"
});

//取得 Model 項目
document.write(user.get("firstName"));
document.write("<hr>");
document.write(user.get("lastName"));

 

如果是裡面有一個 Array,則需要靠遞迴將資料取出

//裡面有 json obj 的 Model
jsonModel = new Backbone.Model({
    data:[
        { item: "item1", href: "1.jsp" },
        { item: "item2", href: "2.jsp" }
    ]
});

//取得 Model 項目 (JSON 物件版) - 需要用到遞迴
for(i=0;i<jsonModel.get("data").length;i++){
    document.write("<hr>");
    document.write(jsonModel.get("data")[i].item);
    document.write("│");
    document.write(jsonModel.get("data")[i].href);
}

 

可以到 jsFiddle 上面玩看看

 

新增 Model 資料

如果要新增一筆值,可以用 set 的指令,直接塞進一筆值:

//initial var
var user = new Backbone.Model({
  firstName: "Jack",
  lastName: "divaka"
});

// add data
user.set({birthday: "oct. 1, 1985"});

 

較複雜的也可以直接把整個 array 物件新增進 Model 當中:

//Backbone Model
APPListModel = new Backbone.Model({
    data:[
        { item: "item1", href: "1.jsp" },
        { item: "item2", href: "2.jsp" }
    ]
});

// data
var x = [
    { item: "item3", href: "3.jsp" }
];

//insert data
APPListModel.set({data:x});

 

刪除 Model 資料

基本的 attribute 可用 unset 方法來移除:

//initial var
var user = new Backbone.Model({
  firstName: "Jack",
  lastName: "divaka"
});

// add data
user.set({birthday: "oct. 1, 1985"});
user.unset("firstName");
user.unset("lastName");

// print model result
alert(JSON.stringify(user));

 

如果是裡面有複雜的 JSON 物件,則可利用遞迴條件清除某筆資料,或是用 unset 直接拿掉某個子元素

此範例有 JSfiddle demo:http://jsfiddle.net/divaka/5Kacs/6/

//initial model 1
var user = new Backbone.Model({
  firstName: "Jack",
  lastName: "divaka"
});

// reset data
user.set({birthday: "oct. 1, 1985"});
user.unset("firstName");
user.unset("lastName");

// print model result
document.write("基本:"+JSON.stringify(user));
document.write("<hr>");

////////////////////////////////////////////////////////////

//Backbone Model
m = new Backbone.Model({
    data:[
        { text: "Google", href: "http://google.com" },
        { text: "Facebook", href: "http://facebook.com" },
        { text: "Youtube", href: "http://youtube.com" }
    ]
});

//拿掉其中一筆值
var a = m.get("data");
for(i=0;i<a.length;i++){
    var b = a[i].text;
    if(b=="Facebook"){
        a.splice(i,1);
    }
}
document.write("拿掉陣列:"+JSON.stringify(m));
document.write("<hr>");

// 清空整個 model
m.unset("data");
document.write("拿掉整個model"+JSON.stringify(m));
document.write("<hr>");​

 

設定 Model 更新事件監聽

Model 可以綁定 change event ,當 model 的資料改變時,自動執行某些程式碼

例如:

// binding event
APPListModel.bind('change:data',function(){
    alert("event fired");
});

 

或是你也可以設定 model 更新時,自動呼叫 (callback) 某個函式:

// binding event
APPListModel.bind('change:data',function(){
    updateContainer(APPListModel );
});

 

動態設定 Model 的值

官方的範例有一個是可以動態設定 Model 內容的,以下的 code 可以詢問使用者一個顏色,並動態將 color 設定進 Model 裡面,更新成背景的顏色。

var BodyColor= Backbone.Model.extend({
  promptColor: function() {
    var cssColor = prompt("Please enter a CSS color:");
    this.set({color: cssColor});
  }
});

window.bg= new BodyColor;

bg.on('change:color', function(model, color) {
  $('body').css({background: color});
});

bg.set({color: 'white'});

bg.promptColor();​

 

也可以玩看看 jsFiddle 的範例

 

Model Extend (繼承)

backbone 的 Model 也可以讓你自訂 class,但是一定要從原本的 backbone model 繼承

如果要 override 一些 class 屬性,則需要利用以下語法,將自訂的 property 傳進去

var MyModelClass=Backbone.Model.extend(properties)

 

以下範例宣告了一個 Model instance,並繼承自訂的 Model 類別

//自訂 Backbone Model 類別
window.Item = Backbone.Model.extend({
    
    //起始化
    initialize:function(){
        document.write("instance is initialized");
        document.write("<hr>");                
    },
    
    //自訂類別成員
    intro:"This is a backbone model instance"

});

//用自訂類別宣告一個實體
var item = new Item();

//呼叫類別成員
document.write(item.intro);
document.write("<hr>");

//設定 Model 的屬性
item.set("anotherAttr","新增的屬性");
document.write(item.get("anotherAttr"));
document.write("<hr>");
​

 

jsFiddle 如下:

 

 

Model 與 UI 互動完整範例

以下程式碼建立一個簡單的 Model 與 View 互動範例,目標達成:

(1) Model 初始就有資料

(2) 註冊一個 Button,設定當 Button 點擊時,新增某個 Model data

(3) 註冊另一個 Button,設定當 Button 點擊時,刪除 Model data

(4) 當 Model data 改變時,View 就會自動 ajax 更新

 

以下介紹其程式碼

HTML 部份

html 這邊只設定了三個 Button ,然後在最後面安排一個 container 來放內容

<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.1/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>

<button id="triggerAddEvent">新增 item3</button>
<button id="triggerDeleteEvent">刪除 item3</button>
<button id="triggerDeletelastItemEvent">刪除最後一個 item</button>

<div id="container"></div>


​

 

JS 部份

JS 部份在一開始先建立了一個  itemModel,做為整體內容容器

設定了一個 updateContainer 的 function,負責重繪 UI

畫面當中則安排了三個按鈕

(1) 第一個是新增一個 item3

(2) 第二個是移除一個 item3

(3) 第三個是移除 model 裡面的最後一個 element

 

由於以下程式碼已經替 itemModel binding 一個「change」的事件,所以當 model 內容改變,就會呼叫 updateContainer function

itemModel.bind(‘change:data’,function(){
       updateContainer(this);
});

 

至於 Model 元素的新增與刪除,似忽沒有既有方法可以使用 (如果讀者知道麻煩告訴我一下 ! 謝謝)

所以我設定了一個 temp 的物件,然後用 temp.push(x); 加入一筆資料,或是設定條件,用來裝每次 loop 過濾所要留下來的元素,以完成 remove element 的實做

最後,則呼叫 itemModel.set({ data:temp }); ,用 temp 取代原本的 Model 內容

並自動呼叫 updateContainer 以完成 UI 的重繪

 

這邊有 jsfiddle 的 demo:http://jsfiddle.net/divaka/qcG5J/4/

 

以下為 JS 的程式碼:

// Model 
itemModel = new Backbone.Model({
    data:[
        { item: "item1"},
        { item: "item2"}
    ]
});

// 先 update 一次
updateContainer(itemModel);

// binding event
itemModel.bind('change:data',function(){
    updateContainer(this);
});


// trigger add event
$("#triggerAddEvent").click(function(){

    // new data
    var x = { item: "item3"};
    
    
    var temp = [];
    var data = itemModel.get("data");
    for(i=0;i<data.length;i++){
        temp.push(data[i]);
    }
    
    // import the new data
    temp.push(x);
    
    // set the new data
    itemModel.set({ data:temp });
    
    
});

// trigger delete event
$("#triggerDeleteEvent").click(function(){
    
    //delete a data
    var temp=[];
    var data = itemModel.get("data");
    for(i=0;i<data.length;i++){
        var b = data[i].item;
        
        //刪除條件
        if(b!="item3"){
            temp.push(data[i]);
        }
    }
    
    // set the new data
    itemModel.set({ data:temp });
    
});

// trigger delete the last item event
$("#triggerDeletelastItemEvent").click(function(){
    
    //delete a data
    var temp=[];
    var data = itemModel.get("data");
    for(i=0;i<data.length;i++){
        
        //刪除條件
        if(i!=data.length-1){
            temp.push(data[i]);
        }
    }
    
    // set the new data
    itemModel.set({ data:temp });
    
});

//更新顯示
function updateContainer(model){

    //empty container
    $("#container").html("");
    
    //re-render UI
    var data = model.get('data');
    for (var i=0, l=data.length; i<l; i++) {
        $("#container").append(data[i].item+" , ");
    }    
    
}
​

Related Posts Plugin for WordPress, Blogger...
【如果覺得文章寫的好的話希望能按一下讚或分享喔】

彭其捷

想要做出很棒的產品,所以我寫程式,也研究介面 (UI) 與使用者經驗 (UX),並思考管理的法則。

【Profile】http://about.me/divaka

twitter facebookgooglepluslinkedinbloggertumblrflickryoutubedribbblerssemail


Fatal error: Uncaught Exception: 12: REST API is deprecated for versions v2.1 and higher (12) thrown in /home/content/63/7692663/html/blog/wp-content/plugins/seo-facebook-comments/facebook/base_facebook.php on line 1273