最q有人问我学?/span>Spring
一 一?/font>首先Java的基、面向对象的基础和设计模式的基础知识是必不可的?/span>
如果q这些基知道都不够扎实的话,我徏议还是先去补补课。关于设计模式我觉得不用学太多,但以下三个模式是学习Spring必不可少的:factory模式Q包括简单工厂和抽象工厂Q,Strategy模式Q?/span>Template method模式。如果不掌握q些你就Ҏ没法领悟Spring的精髓,只能依样画葫芦地照搬Q这是很可怕的事?/span>
关于q方面的书的已经够多的,我就不说了。我q里强烈的书可能让h有点意外Q那是Expert one on one J2EE design and development的第四章Q这一章不仅仅?/span>Spring初学者,而是M?/span>Java开发的人必ȝ一章。经典!
二、接下可以看一?/span>Spring的入门书c?/span>
其实我自己没怎么看过q方面的书,我当时只看过Spring?/span>referenceQ不q现在这斚w的书好象多的是,?/span>Spring reference看v来还是有些吃力的?/span>JavaEye上很多h夏昕?/span>Spring开发指?/span>Q据说入门很Ҏ。另外的入门书应该是Spring live?/span>Spring in action。我大概扫了一下,Spring live是一本只讲怎么做而不讲ؓ什么的书,我不太喜Ƣ(偶尔参考一下倒不错)Q不q有些h特别喜欢q样的书Q看自己的个人爱好吧?/span>
三、研I几个用Spring做的开源项?/span>
四、开始做实际的项?/span>
在上q这些都完备以后Q我觉得应该要去实际目中锻g。当然ƈ不是每h都有q样的机会的Q这时只能自己做个玩具项目啦。项目的ȝ是非常关键的Q其实每个h都清楚,我就不重复了?/span>
五、l深入学?/span>
l过目的锤|?/span>Spring的用法和原理有了一定的了解的时候,才有可能真正掌握Spring的精髓。这时要ȝ书才?/span>Rod Johnson的三本经典名著,分别是:
Expert one on one J2ee design and development
Expert one on one J2ee without EJB
Professional Java Development with SpringFramework
前两本书的经典程度我׃说了Q只有读了它们,才能真正了解Spring的设计意图,掌握Spring的精髓?/span>
W三本书是我强烈不徏议初学者读的书。里面的东西深入而全Q但是原理讲解得又不够深Q很Ҏ让初学者犯qL。但是却?/span>Spring的高U用户必ȝ一本书Q还有一?/span>pro Spring据说也不错,不过我没读过Q。我q几天会写一下这本书的书评?/span>
当然q个阶段与第四阶D|交错的,边读书边做项目学到的东西才会更多的?/span>
六、分析源代码Q扩?/span>Spring
有h认ؓ没有必要分析Spring的源代码Q因是很累h又不计好的事。但是要x?/span>Spring的高U用Pq是必经的阶Dc在学习的过E中Q我们学到的不仅?/span>SpringQ更重要的是他的设计思想。不怎样Q看牛h的源代码是绝Ҏ好处的。不q这是一个很累h的过E,要有思考准备哦Q?/span>
七、等我到q个阶段的时候再告诉你吧Q哈?/span>
设计模式解读之一Q?{略模式
1. 模式定义
把会变化的内容取出ƈ装hQ以便以后可以轻易地改动或扩充部分,而不影响不需要变化的其他部分Q?br />
2. 问题~v
当涉及至代码l护ӞZ复用目的而用承,l局q不完美。对父类的修改,会媄响到子类型。在类中增加的ҎQ会D子类型有该方法,甚至q那些不该具备该Ҏ的子cd也无法免除。示例,一个鸭子类型:
public abstract class Duck {
//所有的鸭子均会叫以及游泻I所以父cM处理q部分代?br />
public void quack() {
System.out.println("Quack");
}
public void swim() {
System.out.println("All ducks float, even decoys.");
}
//因ؓ每种鸭子的外观是不同的,所以父cM该方法是抽象的,由子cd自己完成?br />
public abstract void display();
}
public class MallardDuck extends Duck {
//野鸭外观昄为绿?br />
public void display() {
System.out.println("Green head.");
}
}
public class RedHeadDuck extends Duck {
//U头鸭显CZؓU头
public void display() {
System.out.println("Red head.");
}
}
public class RubberDuck extends Duck {
//皮鸭叫Cؓ吱吱叫,所以重写父cM改写行ؓ
public void quack() {
System.out.println("Squeak");
}
//皮鸭显CZؓ黄头
public void display() {
System.out.println("Yellow head.");
}
}
上述代码Q初始实现得非常好。现在我们如果给Duck.java中加入fly()Ҏ的话Q那么在子类型中均有了该ҎQ于是我们看C 会飞的橡皮鸭子,你看q吗Q当Ӟ我们可以在子cM通过I实现重写该Ҏ以解册Ҏ对于子类型的影响。但是父cM再增加其它的Ҏ呢?
通过l承在父cM提供行ؓQ会D以下~点Q?br />
a. 代码在多个子cM重复;
b. q行时的行ؓ不容易改变;
c. 改变会牵一发动全nQ造成部分子类型不惌的改变;
好啦Q还是刚才鸭子的例子Q你也许惛_使用接口Q将飞的行ؓ、叫的行为定义ؓ接口Q然后让Duck的各U子cd实现q些接口。这时侯代码cM于:
public abstract class Duck {
//变化的行ؓ fly() 以及quake()从DuckcM分离出去定义形成接口Q有需求的子类中自行去实现
public void swim() {
System.out.println("All ducks float, even decoys.");
}
public abstract void display();
}
//变化?fly() 行ؓ定义形成的接?br />
public interface FlyBehavior {
void fly();
}
//变化?quack() 行ؓ定义形成的接?br />
public interface QuackBehavior {
void quack();
}
//野鸭子会飞以及叫Q所以实现接?nbsp; FlyBehavior, QuackBehavior
public class MallardDuck extends Duck implements FlyBehavior, QuackBehavior{
public void display() {
System.out.println("Green head.");
}
public void fly() {
System.out.println("Fly.");
}
public void quack() {
System.out.println("Quack.");
}
}
//U头鸭子会飞以及叫,所以也实现接口 FlyBehavior, QuackBehavior
public class RedHeadDuck extends Duck implements FlyBehavior, QuackBehavior{
public void display() {
System.out.println("Red head.");
}
public void fly() {
System.out.println("Fly.");
}
public void quack() {
System.out.println("Quack.");
}
}
//皮鸭不会飞Q但会吱吱叫Q所以只实现接口QuackBehavior
public class RubberDuck extends Duck implements QuackBehavior{
//皮鸭叫Cؓ吱吱?br />
public void quack() {
System.out.println("Squeak");
}
//皮鸭显CZؓ黄头
public void display() {
System.out.println("Yellow head.");
}
}
上述代码虽然解决了一部分问题Q让子类型可以有选择地提供一些行?例如 fly() Ҏ不会出现在皮鸭中).但我们也看到Q野鸭子MallardDuck.java和红头鸭子RedHeadDuck.java的一些相同行Z码不能得到重复用。很大程度上q是从一个火坑蟩到另一个火坑?br />
在一D늨序之后,让我们从l节中蟩出来Q关注一些共性问题。不用什么语aQ构Z么应用,在Y件开发上Q一直伴随着的不变的真理是:需要一直在变化。不当初Y件设计得多好Q一D|间之后,L需要成长与改变Q否则Y件就会死亡?br />
我们知道Q承在某种E度上可以实C码重用,但是父类(例如鸭子cDuck)的行为在子类型中是不断变化的Q让所有子cd都有q些行ؓ是不恰当的。我们可以将q些行ؓ定义为接口,让Duck的各U子cdd玎ͼ但接口不h实现代码Q所以实现接口无法达C码复用。这意味着Q当我们需要修Ҏ个行为,必须往下追tƈ在每一个定义此行ؓ的类中修改它Q一不小心,会造成新的错误?br />
设计原则Q把应用中变化的地方独立出来Q不要和那些不需要变化的代码混在一赗这样代码变化引L不经意后果变,pȝ变得更有Ҏ?br />
按照上述设计原则Q我们重新审视之前的Duck代码?br />
1) 分开变化的内容和不变的内?br />
DuckcM的行?fly(), quack(), 每个子类型可能有自己Ҏ的表玎ͼq就是所谓的变化的内宏V?br />
DuckcM的行?swim() 每个子类型的表现均相同,q就是所谓不变的内容?br />
我们变化的内容从Duck()cM剥离出来单独定义形成接口以及一pd的实现类型。将变化的内容定义Ş成接口可实现变化内容和不变内容的剥离。其实现cd可实现变化内容的重用。这些实现类qDuck.java的子cdQ而是专门的一l实现类Q称之ؓ"行ؓc?。由行ؓc而不是Duck.java的子cd来实现接口。这P才能保证变化的行为独立于不变的内宏V于是我们有Q?br />
变化的内容:
//变化?fly() 行ؓ定义形成的接?br />
public interface FlyBehavior {
void fly();
}
//变化?fly() 行ؓ的实现类之一
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I'm flying.");
}
}
//变化?fly() 行ؓ的实现类之二
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("I can't fly.");
}
}
-----------------------------------------------------------------
//变化?quack() 行ؓ定义形成的接?br />
public interface QuackBehavior {
void quack();
}
//变化?quack() 行ؓ实现cM一
public class Quack implements QuackBehavior {
public void quack() {
System.out.println("Quack");
}
}
//变化?quack() 行ؓ实现cM?br />
public class Squeak implements QuackBehavior {
public void quack() {
System.out.println("Squeak.");
}
}
//变化?quack() 行ؓ实现cM?br />
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("<< Slience >>");
}
}
通过以上设计Qfly()行ؓ以及quack()行ؓ已经和Duck.java没有什么关p,可以充分得到复用。而且我们很容易增加新的行? 既不影响现有的行为,也不影响Duck.java。但是,大家可能有个疑问Q就是在面向对象中行Z是体CؓҎ吗?Z么现在被定义形成c?例如Squeak.java)Q在OO中,cM表的"东西"一般是既有状?实例变量Q又有方法。只是在本例中碰?东西"是个行ؓ。既使是行ؓQ也有属性及ҎQ例如飞行行为,也需要一些属性记录飞行的状态,如飞行高度、速度{?br />
2) 整合变化的内容和不变的内?br />
Duck.java?fly()以及quack()的行为委拖给行ؓcd理?br />
不变的内容:
public abstract class Duck {
//行为类声明为接口类型,降低对行为实现类型的依赖
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void performFly() {
//不自行处理fly()行ؓQ而是委拖l引用flyBehavior所指向的行为对?br />
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
public void swim() {
System.out.println("All ducks float, even decoys.");
}
public abstract void display();
}
Duck.java不关心如何进?fly()以及quack(), q些l节交由具体的行为类完成?br />
public class MallardDuck extends Duck{
public MallardDuck() {
flyBehavior=new FlyWithWings();
quackBehavior=new Quack();
}
public void display() {
System.out.println("Green head.");
}
}
试c:
public class DuckTest {
public static void main(String[] args) {
Duck duck=new MallardDuck();
duck.performFly();
duck.performQuack();
}
}
在Duck.java子类型MallardDuck.java的构造方法中Q直接实例化行ؓcdQ在~译的时侯便指定具体行ؓcd。当Ӟ我们可以Q?br />
1) 我们可以通过工厂模式或其它模式进一步解?可参考后l模式讲?;
2) 或做到在q行时动态地改变行ؓ?br />
3) 动态设定行?br />
在父cDuck.java中增加设定行为类型的setterҎQ接受行为类型对象的参数传入。ؓ了降藕,行ؓ参数被声明ؓ接口cd。这P既便在运行时Q也可以通过调用q二个方法以改变行ؓ?br />
public abstract class Duck {
//在刚才Duck.java中加入以下二个方法?br />
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior=flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior=quackBehavior;
}
//其它Ҏ同,省略...
}
试c:
public class DuckTest {
public static void main(String[] args) {
Duck duck=new MallardDuck();
duck.performFly();
duck.performQuack();
duck.setFlyBehavior(new FlyNoWay());
duck.performFly();
}
}
如果Q我们要加上火箭助力的飞行行为,只需再新建FlyBehavior.java接口的实现类型。而子cd可通过调用setQuackBehavior(...)Ҏ动态改变。至此,在Duck.java增加新的行ؓl我们代码所带来的困l已不复存在?br />
该是ȝ的时侯了Q让我们从代码的水中出来,做一只在水面上自由游动的鸭子?
3. 解决Ҏ
MallardDuck l承 Duck抽象c; -> 不变的内?br />
FlyWithWings 实现 FlyBehavior接口Q?nbsp; -> 变化的内?行ؓ或算?br />
在Duck.java提供setterҎ以装配关p; -> 动态设定行?br />
以上是{略模式的实C步曲。接下来Q让我们透过步骤看本?
1) 初始Q我们通过l承实现行ؓ的重用,D了代码的l护问题?nbsp; -> l承, is a
2) 接着Q我们将行ؓ剥离成单独的cdq声明ؓ不变内容的实例变量ƈ通过 -> l合, has a
setterҎ以装配关p;
l承Q可以实现静态代码的复用Q组合,可以实现代码的弹性维护;使用l合代替l承Q可以代码更好地适应软g开发完后的需求变化?br />
{略模式的本质:用l承Q多用组?/p>
此文以实例ؓ基础一步步说明了jQuery的工作方式。现以中文翻译(d我的补充说明Q如下。如有相x见或请麻烦到我的 BLOG 写个回复或?EMAIL 告知?/p>
英文原版Q?a >http://jquery.bassistance.de/jquery-getting-started.html Q感谢原文作?Jörn Zaefferer
本文发布已征求原作者同意?/strong>
另外我认为在学习q程?有两个API文档你要打开随时查看:
q个指南是一个对jQuery库的说明Q要求读者了解HTML(DOM)和CSS的一些常识。它包括了一个简单的Hello World的例子,选择器和事g基础QAJAX、FX的用法,以及如何制作jQuery的插件?q个指南包括了很多代码,你可以copy它们Qƈ试着修改它们Q看看生的效果?
一开?我们需要一个jQuery的库,最新的下蝲可以?a >q里扑ֈ。这个指南提供一个基本包含实例的包供下蝲.
下蝲Q?a class="download" >jQuery Starterkit
(译者Keel?一定要下蝲q个包,光看文章不实践肯定是不行的?
下蝲后解压羃Q然后用你最喜欢的文本编辑器打开starterkit.html和custom.jsq两个文件?span class="log">(译者Keel?q两个就是例子文?所有的例子都用q两个例子作?custom.js写jQuery代码,starterkit.html观察效果.用editPlus打开)
现在,我们已l做好了一切准备来q行q个著名?Hello world"例子.
在做所有事情之?我们要让jQueryd和处理文档的DOM,必须可能快地在DOM载入后开始执行事?所?我们用一个ready事g作ؓ处理HTML文档的开?看看我们打开的custom.jsq个文g,里面已经准备好了:
$(document).ready(function() { // do stuff when DOM is ready });
放一个简单的alert事g在需要等DOM完成载入,所以我们把dE稍变复杂一?在点MQ何一个链接时昄一个alert.
$(document).ready(function() { $("a").click(function() { alert("Hello world!"); }); });
q样在你点击面的一个链接时都会触发q个"Hello world"的提C?/p>
(译者Keel?L此代码修改custom.jsq保?然后用浏览器打开starterkit.html观察效果?
让我们看一下这些修Ҏ什么含义?("a") 是一个jQuery选择?selector),在这里,它选择所有的a标签Q译者Keel注:?lt;a></a>Q?/span>Q?h jQuery “c?#8221;(jQuery "class")的一个别Uͼ因此$()构造了一个新的jQuery 对象(jQuery object)。函?click() 是这个jQuery对象的一个方法,它绑定了一个单M件到所有选中的标{?q里是所有的a标签),q在事g触发时执行了它所提供的alertҎ.
q里有一个拟行相似功能的代码:
<a href="#" onclick="alert('Hello world')">Link</a>
不同之处很明?用jQuery不需要在每个a标签上写onclick事g,所以我们拥有了一个整z的l构文档(HTML)和一个行为文?JS),辑ֈ了将l构与行为分开的目?像我们使用CSSq求的一?
下面我们会更多地了解到选择器与事g.
jQuery提供两种方式来选择html的elementsQ第一U是用CSS和Xpath选择器联合v来Ş成一个字W串来传送到jQuery的构造器Q如Q?("div > ul a")Q;W二U是用jQuery对象的几个methods(Ҏ)。这两种方式q可以联合v来合用?/p>
Z试一下这些选择器,我们来试着在我们starterkit.html中选择q修改第一个ordered list.
一开始,我们需要选择q个list本nQ这个list有一个ID?#8220;orderedlist”Q通常的javascript写法是document.getElementById("orderedlist").在jQuery中,我们q样做:
$(document).ready(function() { $("#orderedlist").addClass("red"); });
q里starterkit中的一个CSS样式red附加Corderedlist?span class="log">(译者Keel注:参考测试包中的css目录下的core.cssQ其中定义了red样式)。因此,在你h了starterkit.html后,你将会看到第一个有序列?ordered list )背景色变成了U色Q而第二个有序列表没有变化.
现在Q让我们d一些新的样式到list的子节点.
$(document).ready(function() { $("#orderedlist > li").addClass("blue"); });
q样Q所有orderedlist中的li都附加了样式"blue"?/p>
现在我们再做个复杂一点的Q当把鼠标放在li对象上面和移开时进行样式切换,但只在list的最后一个element上生效?/p>
$(document).ready(function() { $("#orderedlist li:last").hover(function() { $(this).addClass("green"); }, function() { $(this).removeClass("green"); }); });
q有大量的类似的CSS?a class="doc" title="Documentation for XPath selectors" >XPath例子Q更多的例子和列表可以在q里扑ֈ?span class="log">Q译者Keel注:入门看此文,修行在个人,要想在入门之后懂更多Q所以这D话的几个链接迟早是要必看的Q不会又要翻译吧...^_^!Q?/span>
每一个onXXX事g都有效,如onclick,onchange,onsubmit{,都有jQuery{h表示ҎQ译者Keel注:jQuery不喜ƢonXXXQ所以都Ҏ了XXXQ去掉了onQ?/span>?a class="doc" title="Documentation for advanced events" >其他的一些事?/a>Q如ready和hover,也提供了相应的方法?/p>
你可以在Visual jQuery扑ֈ全部的事件列表,在Events栏目? 用这些选择器和事g你已l可以做很多的事情了Q但q里有一个更强的好东东! find() 让你在已l选择的element中作条g查找,因此 $("#orderedlist).find("li") 像 $("#orderedlist li")一栗each()Ҏq代了所有的liQƈ可以在此基础上作更多的处理?大部分的Ҏ,如addClass(), 都可以用它们自己?each() 。在q个例子? html()用来获取每个li的html文本, q加一些文字,q将之设|ؓli的html文本?span class="log">Q译者Keel注:从这个例子可以看?html()Ҏ是获取对象的html代码Q?html('xxx')是设|?xxx'为对象的html代码Q?/span> 另一个经常碰到的d是在没有被jQuery覆盖的DOM元素上call一些方法,惛_一个在你用AJAX方式成功提交后的resetQ?/p>
Q译者Keel注:q里作者将form的id也写成了formQ源文g?lt;form id="form">Q这是非怸好的写法Q你可以这个IDҎform1或者testFormQ然后用$("#form1")或?("#testForm")来表C它Q再q行试。) q个代码选择了所有ID?form"的元素,q在其第一个上call了一个reset()。如果你有一个以上的formQ你可以q样做: Q译者Keel注:h意一定要亲自这些代码写在custom.js中ƈ在starterkit.html上测试效果才能有所体会Q必要时要观察starterkit.html的html代码Q?/p>
q样你在点击Reset链接后,选择了文档中所有的form元素Qƈ对它们都执行了一ơreset()?/p>
q有一个你可能要面对的问题是不希望某些特定的元素被选择。jQuery 提供了filter() 和not() Ҏ来解册个问题?filter()以过滤表辑ּ来减不W合的被选择? not()则用来取消所有符合过滤表辑ּ的被选择? 考虑一个无序的listQ你惌选择所有的没有ul子元素的li元素?/p>
q个代码选择了所有的li元素Q然后去除了没有ul子元素的li元素。刷新浏览器后,所有的li元素都有了一个边框,只有ul子元素的那个li元素例外?/p>
Q译者Keel注:h意体会方便之极的css()ҎQƈ再次提醒请务必实际测试观察效果,比方说换个CSS样式呢?再加一个CSS样式呢?像这P$("li").not("[ul]").css("border", "1px solid black").css("color","red");Q?/p>
上面代码中的[expression] 语法是从XPath而来Q可以在子元素和属?elements and attributes)上用作过滤器Q比如你可能想选择所有的带有name属性的链接: q个代码l所有带有name属性的链接加了一个背景色?span class="log">Q译者Keel注:q个颜色太不明显了,写成$("a[@name]").background("red");Q?/span> 更常见的情况是以name来选择链接Q你可能需要选择一个有特点href属性的链接Q这在不同的览器下对href的理解可能会不一_所以我们的部分匚w("*=")的方式来代替完全匚w("=")Q?/p>
到现在ؓ止,选择器都用来选择子元素或者是qo元素。另外还有一U情冉|选择上一个或者下一个元素,比如一个FAQ的页面,{案首先会隐藏,当问题点LQ答案显C出来,jQuery代码如下Q?/p>
q里我们用了一些链式表达法来减代码量Q而且看上L直观更容易理解。像'#faq' 只选择了一ơ,利用end()ҎQ第一ơfind()Ҏ会结?undone)Q所以我们可以接着在后面lfind('dt')Q而不需要再?('#faq').find('dt')?/p>
在点M件中的,我们?$(this).next() 来找到dt下面紧接的一个dd元素Q这让我们可以快速地选择在被点击问题下面的答案?/p>
Q译者Keel注:q个例子真是太酷了,FAQ中的{案可以收羃Q从利用next()的思\到实现这些效果都有很多地斚w要我们消化,注意 if (answer.is(':visible'))用法Q注意answer.slideUp();不懂的地方赶紧查我在最开始提到的两个必看API文档Q?/p>
除了选择同别的元素外,你也可以选择父的元素。可能你惛_用户鼠标Ud文章某段的某个链接时Q它的父U元?-也就是文章的q一D늪出显C,试试q个Q?/p>
试效果可以看到Q移到文章某D늚链接Ӟ它所在的D全用上highlight样式Q移C后又恢复原样?/p>
Q译者Keel注:highlight是core.css中定义的样式Q你也可以改变它Q注意这里有W二个function()q是hoverҎ的特点,请在API文档中查阅hoverQ上面也有例子说明)
在我们l之前我们先来看看这一步: jQuery会让代码变得更短从而更Ҏ理解和维护,下面?(document).ready(callback)的羃写法Q?/p>
应用到我们的Hello world例子中,可以q样: 现在Q我们手上有了这些基的知识,我们可以更进一步的探烦其它斚w的东西,׃AJAX开始!$(document).ready(function() {
$("#orderedlist").find("li").each(function(i) {
$(this).html( $(this).html() + " BAM! " + i );
});
});
$(document).ready(function() {
// use this to reset a single form
$("#reset").click(function() {
$("#form")[0].reset();
});
});
$(document).ready(function() {
// use this to reset several forms at once
$("#reset").click(function() {
$("form").each(function() {
this.reset();
});
});
});
$(document).ready(function() {
$("li").not("[ul]").css("border", "1px solid black");
});
$(document).ready(function() {
$("a[@name]").background("#eee");
});
$(document).ready(function() {
$("a[@href*=/content/gallery]").click(function() {
// do something with all links that point somewhere to /content/gallery
});
});
$(document).ready(function() {
$('#faq').find('dd').hide().end().find('dt').click(function() {
var answer = $(this).next();
if (answer.is(':visible')) {
answer.slideUp();
} else {
answer.slideDown();
}
});
});
$(document).ready(function() {
$("a").hover(function() {
$(this).parents("p").addClass("highlight");
}, function() {
$(this).parents("p").removeClass("highlight");
});
});
$(function() {
// code to execute when the DOM is ready
});
$(function() {
$("a").click(function() {
alert("Hello world!");
});
});
本章的相关链?
在这一部分我们写了一个小的AJAX应用Q它能够rate一些东?span class="log">Q译Keel注:是Ҏ些东西投)Q就像在youtube.com上面看到的一栗?/p>
首先我们需要一些服务器端代码,q个例子中用C一个PHP文gQ读取rating参数然后q回ratingL和^均数。看一?a >rate.php代码.
虽然q些例子也可以不使用AJAX来实玎ͼ但显C我们不会那么做Q我们用jQuery生成一个DIV容器QID?rating".
$(document).ready(function() { // generate markup var ratingMarkup = ["Please rate: "]; for(var i=1; i <= 5; i++) { ratingMarkup[ratingMarkup.length] = "<a href='#'>" + i + "</a> "; } // add markup to container and applier click handlers to anchors $("#rating").append( ratingMarkup.join('') ).find("a").click(function(e) { e.preventDefault(); // send requests $.post("rate.php", {rating: $(this).html()}, function(xml) { // format result var result = [ "Thanks for rating, current average: ", $("average", xml).text(), ", number of votes: ", $("count", xml).text() ]; // output result $("#rating").html(result.join('')); } ); }); });
q段代码生成?个链接,q将它们q加到id?rating"容器中,当其中一个链接被点击Ӟ该链接标明的分数׃以rating参数形式发送到rate.phpQ然后,l果以XML形式会从服务器端传回来,d到容器中Q替代这些链接?/p>
如果你没有一个安装过PHP的webserverQ你可以看看q个在线的例?/a>.
不用javascript实现的例子可以访?softonic.de 点击 "Kurz bewerten!"
更多的AJAXҎ可以?a class="doc" title="Documentation for AJAX methods" >q里 扑ֈQ或者看?a >API文档 下面的AJAX filed under AJAX.
Q译者Keel注:q个在线实例从国内访问还是比较慢的,点击后要{一会儿才能看到l果Q可以考虑对它q行修改Q比如加上loadingQ投后加上再投的q回链接{。此外,q个例子中还是有很多需要进一步消化的地方Q看不懂的地方请参考API文档。)
一个在使用AJAX载入内容时经常发生的问题是:当蝲入一个事件句柄到一个HTML文档Ӟq需要在载入内容上应用这些事Ӟ你不得不在内容加载完成后应用q些事g句柄Qؓ了防止代码重复执行,你可能用到如下一个function:
// lets use the shortcut $(function() { var addClickHandlers = function() { $("a.clickMeToLoadContent").click(function() { $("#target").load(this.href, addClickHandlers); }); }; addClickHandlers(); });
现在QaddClickHandlers只在DOM载入完成后执行一ơ,q是在用hơ点d有clickMeToLoadContent q个样式的链接ƈ且内容加载完成后.
h意addClickHandlers函数是作Z个局部变量定义的Q而不是全局变量(如:function addClickHandlers() {...})Q这样做是ؓ了防止与其他的全局变量或者函数相冲突.
另一个常见的问题是关于回?callback)的参数。你可以通过一个额外的参数指定回调的方法,单的办法是将q个回调Ҏ包含在一个其它的function?
// get some data var foobar = ...; // specify handler, it needs data as a paramter var handler = function(data) { ... }; // add click handler and pass foobar! $('a').click( function(event) { handler(foobar); } ); // if you need the context of the original handler, use apply: $('a').click( function(event) { handler.apply(this, [foobar]); } );
用到单的AJAX后,我们可以认ؓ已经非常?#8220;web2.0”了,但是到现在ؓ止,我们q缺一些酷炫的效果。下一节将会谈到这些效?
一些动态的效果可以使用 show()
?hide()
来表?
$(document).ready(function() { $("a").toggle(function() { $(".stuff").hide('slow'); }, function() { $(".stuff").show('fast'); }); });
你可以与 animate()
联合h创徏一些效?如一个带渐显的滑动效?
$(document).ready(function() { $("a").toggle(function() { $(".stuff").animate({ height: 'hide', opacity: 'hide' }, 'slow'); }, function() { $(".stuff").animate({ height: 'show', opacity: 'show' }, 'slow'); }); });
很多不错的效果可以访?a >interface plugin collection. q个站点提供了很多demos和文?/p>
q些效果插g是位于jQuery插g列表的前面的Q当然也有很多其他的插gQ比如我们下一章讲到的表格排序插g?/p>
q个表格排序插g能让我们在客L按某一列进行排序,引入jQuery和这个插件的js文gQ然后告诉插件你惌哪个表格拥有排序功能?/p>
要测试这个例子,先在starterkit.html中加上像下面q一行的代码Q?/p>
<script src="lib/jquery.tablesorter.js" type="text/javascript"></script>
然后可以q样调用不着:
$(document).ready(function() { $("#large").tableSorter(); });
现在点击表格的第一行head区域Q你可以看到排序的效果,再次点击会按倒过来的序q行排列?/p>
q个表格q可以加一些突出显C的效果Q我们可以做q样一个隔行背景色Q斑马线Q效?
$(document).ready(function() { $("#large").tableSorter({ stripingRowClass: ['odd','even'], // Class names for striping supplyed as a array. stripRowsOnStartUp: true // Strip rows on tableSorter init. }); });
关于q个插g的更多例子和文档可以?tablesorter首页扑ֈ.
几乎所有的特g都是q样用的:先include插g的js文g,然后在某些元素上使用插g定义的方?当然也有一些参数选项是可以配|的
l常更新的插件列表可以从jQuery官方?on the jQuery site扑ֈ.
当你更经常地使用jQuery?你会发现你自己的代码打包成插g是很有用处的,它能方便地让你的公司或者其他hq行重用.下一章我们将谈到如何构徏一个自q插g.
写一个自qjQuery插g是非常容易的,如果你按照下面的原则来做,可以让其他h也容易地l合使用你的插g.
jQuery.fn.foobar = function() { // do something };
jQuery.fooBar = { height: 5, calculateBar = function() { ... }, checkDependencies = function() { ... } };
你现在可以在你的插g中用这些帮助函C:
jQuery.fn.foobar = function() { // do something jQuery.foobar.checkDependencies(value); // do something else };
jQuery.fn.foobar = function(options) { var settings = { value: 5, name: "pete", bar: 655 }; if(options) { jQuery.extend(settings, options); } };
现在可以无需做Q何配|地使用插g?默认的参数在此时生效:
$("...").foobar();
或者加入这些参数定?
$("...").foobar({ value: 123, bar: 9 });
如果你release你的插g, 你还应该提供一些例子和文档,大部分的插g都具备这些良好的参考文?
现在你应该有了写一个插件的基础,让我们试着用这些知识写一个自q插g.
很多着控制所有的radio或者checkbox是否被选中,比如:
$("input[@type='checkbox']").each(function() { this.checked = true; // or, to uncheck this.checked = false; // or, to toggle this.checked = !this.checked; });
无论何时候,当你的代码出现eachӞ你应该重写上面的代码来构造一个插?很直接地:
$.fn.check = function() { return this.each(function() { this.checked = true; }); };
q个插g现在可以q样?
$("input[@type='checkbox']").check();
现在你应该还可以写出uncheck()和toggleCheck()?但是先停一?让我们的插g接收一些参?
$.fn.check = function(mode) { var mode = mode || 'on'; // if mode is undefined, use 'on' as default return this.each(function() { switch(mode) { case 'on': this.checked = true; break; case 'off': this.checked = false; break; case 'toggle': this.checked = !this.checked; break; } }); };
q里我们讄了默认的参数,所以将"on"参数省略也是可以?当然也可以加?on","off", ?"toggle",?
$("input[@type='checkbox']").check(); $("input[@type='checkbox']").check('on'); $("input[@type='checkbox']").check('off'); $("input[@type='checkbox']").check('toggle');
如果有多于一个的参数讄会稍E有点复?在用时如果只想讄W二个参?则要在第一个参C|写入null.
从上一章的tablesorter插g用法我们可以看到,既可以省略所有参数来使用或者通过一?key/value Ҏ重新讄每个参数.
作ؓ一个练?你可以试着?W四?/a> 的功能重写ؓ一个插?q个插g的骨架应该是像这L:
$.fn.rateMe = function(options) { var container = this; // instead of selecting a static container with $("#rating"), we now use the jQuery context var settings = { url: "rate.php" // put more defaults here // remember to put a comma (",") after each pair, but not after the last one! }; if(options) { // check if options are present before extending the settings $.extend(settings, options); } // ... // rest of the code // ... return this; // if possible, return "this" to not break the chain });
如果你想做更好的javascript开?你用一个叫 FireBug的firefox插g. 它提供了断点调试(比alert强多?、观察DOM变化{很多漂亮的功能
如果你还有未解决的问题,或者新的想法与Q你可以使用jQuery的邮件列?jQuery mailing list.