Javascript 的MVC模式(二)

原文:http://www.verydemo.com/demo_c98_i17045.html

这次要和大家深入说的是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()的作用非常简单,它只有一个参数,并且返回一个新的对象,而新对象的原型就是参数对象,好吧,如果你的浏览器不支持这个方法我们也可以自行添加,同时也可以帮助大家理解这个方法的工作原理,非常简单:

....................................................................

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;
    }

那么现在我构建一个简单的模型基本上是完成了,(好辛苦啊,写了这么多)。下一节是讲述如何在模型中引入数据的装载和提交。

你可能感兴趣的:(JavaScript)