JavaScript中的View-Model使用介绍_javascript技巧
构成
这是一个十分常见的微博列表页面,类似于新浪微博。上周末,在心无旁骛情况下,一共用了5个对象,产出400行代码,实践出一种代码组织模式。
使任务轻松完成的代码有4个方面的要素组成:
要素 | 组成 |
---|---|
模型 | Reply、Forward |
视图 | CommentEditor、ReplyList、ForwardList |
模板 | jQuery.tmpl |
异步任务 | jQuery.Deferred |
模型
模型只与数据有关,它能够产生、过滤、保存、验证数据,并且仅此而已。
如下例,留言模型在调用保存方法时,只接收JSON参数,并且只返回一个异步任务,实际处理时同步或异步的返回结果并不重要。
在此进行的验证的原因是,它是一个开放的对象,是与服务器交互的最后一道门槛。
另外,它本身也不处理验证失败的情况——由视图调用时选择性地处理,可能会弹出一个消息提示或直接忽略再进行重试。
// 留言模型
var Reply = {
cache : {},
// { sourceid : id,page_size : 10,page_num : 1 }
fetch : function(data) {
return $.post('/ajax/blog/reply/list',data||{}).success(function(resp) {
resp.ok && resp.list &&
$.each(resp.list,function(k,v) {
return Reply.cache[v.id] = v;
});
});
},
// filter('name','king')
filter : function(prop,val) {
return $.grep(this.cache,function(r){ return r[prop] === val });
},
// { content : '想说就说',sourceid : 1001 }
create : function(data) {
// promise
var dfd = $.Deferred(), now = $.now();
if( (now - this.create.timestamp)/1000 dfd.reject({message:'您发表得太快了,休息一下吧',type:'warn'})
}else if(!data || !data.sourceid){
dfd.reject({message:'非法操作',type:'error'})
}else if(!data.content){
dfd.reject({message:'评论内容不能为空',type:'warn'})
}else{
this.create.timestamp = now;
dfd = $.post('/ajax/blog/reply/create',data);
}
return dfd.promise();
}
};
Reply.create.timestamp = Forward.create.timestamp = $.now() - 1e4;
视图
视图是浏览器页面上的可视部分,每个视图对象含有一个关联的 jQuery 对象作为属性(instance.$el),类似于UI组件中的DOM容器。
视图还有两个一致的方法:
render 方法用于从模型获取数据,并且根据定义好的模板将数据渲染到HTML页面上。
activate 方法用于激活视图,同时绑定相关的DOM事件,所有事件至多委托到$el为止。
这个示例中,CommentEditor是父视图,ReplyList和ForwardList是互斥显示的两个子视图,父子视图之间相互保存引用。
// 回复列表视图
var ReplyList = function(options) {
var opt = this.opt = $.extend({
el : '',
parent : null
},options||{});
this.parent = opt.parent;
this.$el = $(opt.el);
this.activate();
};
ReplyList.prototype = {
render : function() {
var self = this;
Reply.fetch({
page_size : 10, page_num : 1,
sourceid : self.parent.getBlogId()
})
.done(function(data) {
self.$el.html( self.$list = $.tmpl(tpl_reply_list,data) );
});
return self;
},
activate : function() {
this.$el.delegate('a.del',$.proxy(this.del,this))
}
// ...
}
// 评论编辑器视图
CommentEditor.prototype = {
activate : function() {
this.$el.delegate('a.save',$.proxy(this.save,this))
},
save : function() {
var self = this, data = { content : self.getContent(),sourceid : self.getBlogId() };
var task_r = Reply.create(data);
var task_f = Forward.create(data);
// 转发、评论同时进行
$.when(task_r,task_f).then(function(t1,t2) {
// 保存成功,更新视图或关闭
},function(data) {
// 模型验证出错,或远程服务器错误
Sys.info(data.message,data.type);
});
return self;
},
switchView : function(type) {
// 切换子视图
var view_opt = {el:this.$sublist.empty(),parent:this};
if(type === 'reply'){
$label.show();
this.$submit.val('评论');
this.sublist = new ReplyList(view_opt).render();
}else{
$label.hide();
this.$submit.val('转发');
this.sublist = new ForwardList(view_opt).render();
}
}
// ...
}
模板
模板可以消除繁琐、丑陋的字符串拼接,它的作用是能够直接由js对象生成HTML片断。
模板中可以直接遍历对象,套用预定义的函数,来对一些数据进行格式化,比如时间函数nicetime:
// 回复列表模板
var tpl_reply_list = ' ';
异步任务
Deferred Object 的直译是延迟对象,但是理解成异步任务更为恰当。异步任务能够消除多层嵌套的回调,让代码书写和阅读更为便利。
从上面的模型和视图的代码中可以明显地看出,使用了异步任务之后,代码变得更加平面化了。
$.Deferred 方法新建的是一个双向任务队列:成功回调函数队列和失败回调函数队列;任务的状态也分为两种:成功和失败,分别可以用isResolved或isRejected来检查任务的当前状态、用resolve或reject修改任务状态。
promise 方法返回任务的只读副本,此副本上不能修改任务状态。毫无疑问,模型应该始终只返回 promise 对象。(注:只读副本仍然可以再次调用 promise 方法再次返回只读副本)
在Reply.create方法中,能够更好地处理自定义的异步任务,而不是直接返回原生的ajax异步任务:
// var dfd = $.Deferred();
$.post('/ajax/blog/reply/create',data)
.success(function(json) {
if(json && json.ok){
dfd.resolve(json.list);
}else{
dfd.reject({message:json.message||'获取失败',type:'error'});
}
})
.fail(function() {
dfd.reject({message:'服务暂时不可用',type:'error'})
});
目的及结论
为什么拆散成这样?
收获:可维护性,清晰的API调用、消除二层以上的if语句、消除二层以上的回调语句、每个函数控制在二十行之内。
结果:没有过多的重复代码,所有的功能都被打包好了。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。
