中间准绳:
1、代码必需分红差别的功用模块——效劳和模块,防止把一切的代码都放在一个$( document ).ready()里。
2、不要反复代码。辨认差别功用模块内里的雷同代码并提掏出来用继续的要领来防止反复。
3、只管jquery是以DOM为中间,但javascript不是悉数关于DOM的,不是一切的功用块须要或应该有一个DOM示意。
4、松耦合。代码之间经由过程 custom event,pub/sub完成音讯通报。
封装
代码构造的第一步就是把代码分红差别的部份。
运用对象举行封装
长处:处置惩罚消弭匿名函数,以设置参数为中间,更方便去重构和重用。比方对事宜处置惩罚函数,定义为_开首的函数,隐含其为东西函数或私有函数,一个简朴的实例:
// An object literal
var myFeature = {
myProperty: "hello",
myMethod: function() {
console.log( myFeature.myProperty );
},
init: function( settings ) {
myFeature.settings = settings;
},
readSettings: function() {
console.log( myFeature.settings );
}
};
myFeature.myProperty === "hello"; // true
myFeature.myMethod(); // "hello"
myFeature.init({
foo: "bar"
});
myFeature.readSettings(); // { foo: "bar" }
上面例子就是经由过程赋值给一个对象来举行封装的,这个对象有几个属性和要领,一切的属性和要领都是大众的。
怎样将对象应用在Jquery编写的顺序中,一个典范的Jquery顺序以下:
// Clicking on a list item loads some content using the
// list item's ID, and hides content in sibling list items
$( document ).ready(function() {
$( "#myFeature li" ).append( "<div>" ).click(function() {
var item = $( this );
var div = item.find( "div" );
div.load( "foo.php?item=" + item.attr( "id" ), function() {
div.show();
item.siblings().find( "div" ).hide();
});
});
});
针对上面的代码,最少能够优化几点:
将和功用无关的部份自力,能够把url作为设置参数,末了链式操纵也能够优化。
// Using an object literal for a jQuery feature
var myFeature = {
init: function( settings ) {
myFeature.config = {
items: $( "#myFeature li" ),
container: $( "<div class='container'></div>" ),
urlBase: "/foo.php?item="
};
// Allow overriding the default config
$.extend( myFeature.config, settings );
myFeature.setup();
},
setup: function() {
myFeature.config.items
.each( myFeature.createContainer )
.click( myFeature.showItem );
},
createContainer: function() {
var item = $( this );
var container = myFeature.config.container
.clone()
.appendTo( item );
item.data( "container", container );
},
buildUrl: function() {
return myFeature.config.urlBase + myFeature.currentItem.attr( "id" );
},
showItem: function() {
myFeature.currentItem = $( this );
myFeature.getContent( myFeature.showContent );
},
getContent: function( callback ) {
var url = myFeature.buildUrl();
myFeature.currentItem.data( "container" ).load( url, callback );
},
showContent: function() {
myFeature.currentItem.data( "container" ).show();
myFeature.hideContent();
},
hideContent: function() {
myFeature.currentItem.siblings().each(function() {
$( this ).data( "container" ).hide();
});
}
};
$( document ).ready( myFeature.init );
改完今后,能够看到:
1、我们把功用分红了很小的要领。今后假如我们想转变内容的展现,它是明白的,转变它。在原代码中,是很难做到的。
2、消弭了匿名函数的运用。
3、将设置选项从代码的主体中移动,并将它们放在中间位置。
4、消弭了外链的束缚,使得代码更轻易重构。
模块形式
模块形式克服了对象封装的一些局限性,为变量和函数供应了隐私,同时公开了一个大众接口。
// The module pattern
var feature = (function() {
// Private variables and functions
var privateThing = "secret";
var publicThing = "not secret";
var changePrivateThing = function() {
privateThing = "super secret";
};
var sayPrivateThing = function() {
console.log( privateThing );
changePrivateThing();
};
// Public API
return {
publicThing: publicThing,
sayPrivateThing: sayPrivateThing
};
})();
feature.publicThing; // "not secret"
// Logs "secret" and changes the value of privateThing
feature.sayPrivateThing();
在上面的例子中,我们自我实行一个匿名函数,返回一个对象。在函数的内部,我们定义了一些变量。由于变量被定义在函数的内部,除非我们把它们放在返回对象中,不然我们就无法接见它们。这意味着函数之外的任何代码无法接见的变量privateThing或变量changePrivateThing。但是,sayprivatething能够接见并取得privatething和changeprivatething,由于都是在雷同的范围内定义为sayprivatething。
这类形式是壮大的,由于你能够从变量称号中网络,它能够给你私家的变量和函数,同时暴露一个有限的API构成的返回的对象的属性和要领。
下面是一个修订版的前面的例子,展现了怎样我们能够运用模块的款式:
// Using the module pattern for a jQuery feature
$( document ).ready(function() {
var feature = (function() {
var items = $( "#myFeature li" );
var container = $( "<div class='container'></div>" );
var currentItem = null;
var urlBase = "/foo.php?item=";
var createContainer = function() {
var item = $( this );
var _container = container.clone().appendTo( item );
item.data( "container", _container );
};
var buildUrl = function() {
return urlBase + currentItem.attr( "id" );
};
var showItem = function() {
currentItem = $( this );
getContent( showContent );
};
var showItemByIndex = function( idx ) {
$.proxy( showItem, items.get( idx ) );
};
var getContent = function( callback ) {
currentItem.data( "container" ).load( buildUrl(), callback );
};
var showContent = function() {
currentItem.data( "container" ).show();
hideContent();
};
var hideContent = function() {
currentItem.siblings().each(function() {
$( this ).data( "container" ).hide();
});
};
items.each( createContainer ).click( showItem );
return {
showItemByIndex: showItemByIndex
};
})();
feature.showItemByIndex( 0 );
});