有时,使用jQuery会诱使您滥用其功能(至少对我来说是因为其选择器匹配功能).这里和那里的事件处理程序.实用程序功能在这里和任何地方都可以.代码一致性似乎几乎不存在.我想通过实现OOP模式来减轻该问题,但是由于我具有C和python背景,因此在javascript中实现它会使我有点头疼.
下面的代码使用OOP模式,但是我不确定我的实现是否是好的做法.我怀疑自己的实现的原因是因为my last * question中的第三条注释.我知道这只是他所评论的代码中的一个特定细节,但这也使我想知道我正在代码中实现的其他模式.
如果您能指出我的模式中的缺陷和陷阱和/或您有任何建议,我将不胜感激.提前谢谢了.
(这段代码是我正在开发的东西的简化,但是想法很相似)
$(function(){
var stream = new Stream();
});
/* Stream Class
------------------------------------------*/
function Stream(){
// Disables multiple Stream objects
if (this.singleton)
return
else
this.__proto__.singleton = true;
this.elements = jQueryMapping(this.selectors) // Converts a map of selectors to a map of jQuery objects
this.initEvents();
}
Stream.prototype.singleton = false;
Stream.prototype.selectors = {
stream : '#stream',
post_content : '#post-content',
add_post: '#add-post',
// ... more action selectors
}
Stream.prototype.initEvents = function(){
this.elements.add_post.click(this, this.addPost);
// ... more action event-listeners
}
Stream.prototype.addPost = function(e){
var self = e.data;
var post_content = self.elements.post_content.val();
if (post_content)
self.elements.stream.append(new Post(post_content));
}
/* Post Class
------------------------------------------*/
function Post(post_content){
this.$element = $('<li>')
.text(post_content)
.append('<button class="delete-post">Delete</button>');
this.elements = jQueryMapping(this.selectors, this.$element);
this.initEvents();
return this.$element;
}
Post.prototype.selectors = {
delete_post: 'button.delete-post',
// ... more action selectors
}
Post.prototype.initEvents = function(){
this.elements.delete_post.click(this.deletePost);
// ... more action event-listeners
}
Post.prototype.deletePost = function(){
$(this).parent().slideUp();
}
/* Utils
------------------------------------------*/
function jQueryMapping(map, context){
// Converts a map of selectors to a map of jQuery objects
var $map = {};
$.each(map, function(key, value){
$map[key] = (context) ? $(value, context) : $(value);
});
return $map;
}
解决方法:
我相信您的代码设计过度.我已经进行了分解,并简化了它,如here所示.如果您真的想进行繁琐的OOP设置,建议您使用客户端MVC(主干,剔除等)结构来正确执行此操作或使其保持轻量化.
我将对您的代码进行一般性反馈.
/* Stream Class
------------------------------------------*/
function Stream(){
// Disables multiple Stream objects
if (this.singleton)
return
else
this.__proto__.singleton = true;
this.elements = jQueryMapping(this.selectors) // Converts a map of selectors to a map of jQuery objects
this.initEvents();
}
没有理由使用这样的单例.使用.__ proto__也很不好
我会推荐这样的模式.
var Stream = (function() {
var Stream = function() { ... };
// prototype stuff
var stream = new Stream();
return function() {
return stream;
};
})());
不需要在原型上存储像这样的哈希数据.
Stream.prototype.selectors = {
stream : '#stream',
post_content : '#post-content',
add_post: '#add-post',
// ... more action selectors
}
您可以将其作为默认哈希值包含在内.
(function() {
var defaults = {
stream : '#stream',
post_content : '#post-content',
add_post: '#add-post',
// ... more action selectors
}
function Stream() {
...
this.elements = jQueryMapping(defaults);
}
}());
您的效用函数可能会略有优化.
$map[key] = (context) ? $(value, context) : $(value);
这可以重写为
$map[key] = $(value, context)
由于如果上下文是未定义的,则只需传入未定义的参数,这与不传入参数相同.