您的位置:首页 > Web前端 > JavaScript

Javascript 的MVC模式(二)

2012-07-16 13:10 134 查看
这次要和大家深入说的是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等等的复杂概念,推荐/article/5602151.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;
}


那么现在我构建一个简单的模型基本上是完成了,(好辛苦啊,写了这么多)。下一节是讲述如何在模型中引入数据的装载和提交。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: