Javascript 的MVC模式(二)


這次要和大家深入說的是MODEL,個人認為也是比較難於理解的一個概念,所以希望可以和大家一同去探討。

引入MVC模式中,我們把數據的管理歸類進了模型,即我們應該把數據操作和行為相關的邏輯都放進模型中。

在實際的操作中我們最好通過命名空間的方法來進行管理,如下:

var User={
record:[]
}

那么我們User的記錄就可以存放在User.record中了,如果你想為User增加一些CRUD的方法也可以,如下:

var User={
record:[],
update:function(){},
delete:function(){}
}

好的,你可以看到我們通過命名空間的方法可以很優雅地(OK,我有時候感覺用“優雅”這個詞特別裝逼,就像一些翻譯工具譯過來,但是用着用着就覺得這個詞語形容得特別有程序猿的范兒,見笑)把一些方法集成到User中。當然有時候我們想刪除某個user是想以以下這種方式操作:

user.delete() //通過類似的綁定實例刪除

而並非:

User.delete(id) //你需要傳入一個ID來標示刪除的到底是哪個用戶

所以這個時候,你就應該意識到我們應該把User構建成一個類,並且通過構建user實例進行實例的操作,如下:

var User=function(){
this.record=[];
}

User.prototype.delete=function(){
/*具體的刪除實例操作*/
}

var user=new User;

 接下來我們需要利用Object.create()的來構建我們的ORM(根據《軟件程序設計與藝術》一書的“無緒”一詞,不需要過分了解細節的含義,我們只需要知道ORM就是包裝了一些數據的對象,其中它是抽象的,類似接口的概念,你們意會一下吧,作為一名程序猿需要有豐富的想象力!!!),其中Object.create()的作用非常簡單,它只有一個參數,並且返回一個新的對象,而新對象的原型就是參數對象,好吧,如果你的瀏覽器不支持這個方法我們也可以自行添加,同時也可以幫助大家理解這個方法的工作原理,非常簡單:

引用自:http://javascript.crockford.com/prototypal.html

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}
newObject = Object.create(oldObject);//注意這里傳入的是一個對象,並非函數

可以說整個繼承是基於原型的(當然,我剛剛發現了一種JS面向對象的另外一種模仿方法,並且摒棄了原型,this等等的復雜概念,推薦http://www.cnblogs.com/cloudlee/archive/2012/07/15/2592849.html,接下來我們要來利用Object.create()來創建Model對象:

var Model={
    inherited:function(){},
    created:function(){},
    prototype:{
        init:function(){
        }
        },
    create:function(){//創建具體的模型
        var object=Object.create(this);//創建新模型對象,繼承ORM的所有方法
        object.parent=this;//this這時指向的是ORM,以ORM作為新模型的父類
        object.prototype=Object.create(this.prototype);//新模型原型繼承ORM prototype里面的方法init,即讓新模型的實例擁有這個init方法
     object.created(); return object;//返回新模型 }, init:function(){ var instance=Object.create(this.prototype);//創建新實例,注意該實例是有新模型創建的,所以這里的this是指新模型,實例繼承新模型的prototype方法,即init() instance.parent=this;//實例父類指向為新模型,這個很容易理解 instance.init.apply(instance,arguments);//實例調用所繼承的init() return instance;//返回實例 } } var User=Model.create() var user=User.init()

事實上,我認為這段代碼還是比較難理解的,它需要你比較了解整個原型鏈的機制,所以我特地都標上了注釋,希望大家能看懂。事實上在我看的書上有關於增加這個ORM的一些方法和屬性的操作,但是由於我們構建這個ORM的目的就是為了抽象需求,所以我們利用一些方法來擴展它而不采用硬編碼進ORM體內。

    include:function(obj){//由Model調用,把方法屬性添加進ORM中,讓新模型的原型繼承,即讓新模型的實例繼承
            $.extend(this.prototype,obj)
        },
    extend:function(obj){//由Model調用,把方法屬性添加進ORM中,讓新模型繼承
            $.extend(this,obj)
        }    

看到這,大家應該知道我采用了jQuery,為了減輕我們的工作量,之后的一些代碼我們都會利用到jQuery(我相信你不會介意的),然后我們把這個方法寫進去以后可以直接通過Model調用:

Model.include({
    init:function(attributes){//重寫新模型實例的初始方法,傳入參數后調用新加入方法load()
        if(attributes)this.load(attributes);
        },
    load:function(attributes){//該方法把所傳入對象的屬性方法加入到實例中
        jQuery.extend(this,attributes);
        }
    
    })

接下來我們要做的就是對實例的一個持久化,就說是你創建了一個實例需要保存它的信息,不僅僅是每個實例的詳細信息,還要知道我們整個新模型里到底有多少個實例等,於是乎我們加入以下的一些方法來完成這個工作:

Model.include({
    newRecord:true,
    init:function(attributes){
        if(attributes)this.load(attributes);
        },
    load:function(attributes){
        jQuery.extend(this,attributes);
        },
    create:function(){
        this.newRecord=false;
        this.parent.records[this.id]=this;
        },
    destory:function(){
        delete this.parent.records[this.id];
        },
    update:function(){
        this.parent.records[this.id]=this;
        },
    save:function(){
        this.newRecord?this.create():this.update();
},
    })
    
Model.extend({
    created:function(){
        this.records={} //重寫created(),為新模型創建一個records對象記錄實例
        },
    find:function(id){
        return this.records[id]||"找不到相應的記錄";
        }
    })

var User=Model.create();
var user=User.init();

var User2=Model.create();
var user2=User2.init();

user.name="chiu";
user.id=1;
user.save();

user2.name="chiu2";
user2.id=2;
user2.save();

//以下說明兩個模型的記錄是分離的
console.log(User.records);
console.log(User2.records);

通過這種方法就可以把我們新建的實例進行一系列的操作,同時父類模型也會對它們進行記錄。現在我們再來觀察下整個程序的一個問題:

console.log(User.find(1).name);//輸出chiu
User.find(1).name="john";
console.log(User.find(1).name);//輸出john

我們不應該能修改查找的數據從而修改實例的屬性,所以我們應該把查找的結果作一個備份返回,當然具體的實現這里就不說了,你們應該也會知道如何操作。還有另外一個問題是當創建實例的時候我們都需要手動創建id,這樣的方法既麻煩,又容易出錯(需要保持沒有重復的id值),因此我們可以通過CUID的方法來生成一個唯一的id:

網上有很多這類的代碼可以直接套過來,以下是其中一種

guid:function(){
function G() {return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)}
return (guid = (G() + G() + "-" + G() + "-" + G() + "-" + G() + "-" + G() + G() + G()).toUpperCase());
}

生成guid的代碼你可以隨便放哪里都可以,我個人是讓新模型給繼承了,然后我們再重寫一下實例create()的方法

create:function(){
    this.newRecord=false;
    if(!this.id)this.id=this.parent.guid();
    this.parent.records[this.id]=this;
    }

那么現在我構建一個簡單的模型基本上是完成了,(好辛苦啊,寫了這么多)。下一節是講述如何在模型中引入數據的裝載和提交。


免責聲明!

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



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