WordPress的全站Ajax加载(四)完整代码篇(完结)

最近发现小伙伴们对ajax加载比较感兴趣,我之前也写了三篇转门介绍Ajax,自以为已经结束了 写的也比较清楚了。有点懒同学给我提了建议“得把读者都当成小白来看待,不然估计还看不懂”。此文接受建议而出,不过个人还是觉得小伙伴们不要太过把自己当小白,还是要多学会思考总结。本人以前也是小白一个 学的也不是编程。好了 废话不多说 直接进入主题。

这篇部分代码是本人正在使用的代码摘录而出,使用了html5的API来控制历史记录。代码为ajax的核心代码,没有ajax操作时候的一些特效(内容部分会有个简单的半透明渐变处理)。如果你的主题文章部分的DIV是 #content的话 应该可以直接拷过去就用。我说的是应该。

//全局变量
var ajaxBinded = false;
jQuery(document).ready(function() {
//下面三行你可以插入到你的jQuery(document).ready(function()里面,html5的历史记录API
if( history && history.pushState){
//为真就执行Ajaxopt函数
Ajaxopt();
}
})
//Ajaxopt函数
function Ajaxopt(){
//所有不为新窗口打开的链接
$('a[target!=_blank]').live('click',function(event){
var link = event.currentTarget;
var url = link.href;
if ( event.which > 1 || event.metaKey || event.ctrlKey )
return
if ( location.protocol !== link.protocol || location.host !== link.host ){
return;
}
if (link.hash && link.href.replace(link.hash, '') === location.href.replace(location.hash, ''))
return
if (url.indexOf("respond")>0||url.indexOf("/wp-admin/")>0||url.indexOf("wp-login.php")>0||url.indexOf("sitemap.xml")>0)
return
//以上条件语句均为判断链接时候需要ajax加载,下面2句为执行loadDate函数进行ajax操作。
loadData(url,true);
event.preventDefault();
});
}

//loadDate函数
function loadData(url,toPush){
//进行AJAX操作
$.ajax({
url:url,
data: "soz=ajax", //这个可以参考ajax全站加载系列文章第二篇。
dataType: "html",
type: "post",
beforeSend:function(jqXHR, settings){ //加载前操作 #content的DIV变化
$('#content').fadeTo(500,0.3);
}
,
complete:function(){ //加载后操作 #content的DIV变化
$('#content').fadeTo(200,1);
}
,
success:function(message){ //加载成功的操作
var msger = message;
var titl1 = $(message).find("h1:first").text();
var titl2 = $(message).find("h2:first").text();
if (titl1 == "") {
window.document.title = titl2 + " \u2502 SOZ";
}
else {
window.document.title = titl1 + " \u2502 SOZ";
}
//以上几句为组合新页面的标题。下面一句为插入ajax回来的内容到"#content"的DIV容器内。
$("#content").html(msger);
if(toPush){//使用html5的特有API 来改变历史记录数据。
window.history.pushState(null, titl1, url);
}
if(!ajaxBinded){//ajax后重新绑定新加载页面的ajax事件。
ajaxBinded = true;
$(window).bind('popstate', function(e){
loadData(location.href,false);
return false;
});
}
}
,
error: function() {//如果加载失败 报错内容
$("#content").html("

AJAX Error...

");
},
});
}

以上为所有ajax操作的必要步骤,小白同学可以仔细研究。高手可以路过 嗯

From: http://soz.im/wordpress-is-the-stations-ajax-to-load-four-complete-code-articles.html

WordPress的全站Ajax加载(三)改变地址栏

Ajax的优点就是通过局部刷新内容 提高用户体验,但是众所周知的的,ajax后地址栏是不会跟随改变的,URL会一直显示在你第一次进入网站的地址。这样的话 如果用户想分享地址的或者想保存地址的话 就不是当前文章所在的地址。还有返回前进不能使用,这样就造成了很尴尬的局面。这篇文章将介绍2种实现方法,2种各有优缺点。Let’s go~~第一种方法是通过Jquery的一个插件jQuery Address实现的。优点就是兼容低版本的浏览器,缺点呢就是它是通过“#”锚点的方法来改变地址的,如果你直接复制AJAX后带锚点的地址打开的话,浏览器会先加载锚点之前的页面,然后才会执行你写的JS,再通过判断AJAX加载锚点的地址。当然也不能算是个很明显的缺点了。

jQuery Address只有十几K的体积,算是很比较小的插件了。(下载)在AJAX执行之前我们来使用插件做操作地址栏。代码如下

var addresschanged=false;                                                   
$('a[rel="ajax"]').live("click",function(){ 所有rel=ajax的 A链接,
var a=$(this),href=a.attr("href");
_text=a.text();
c=a.attr("title");
if(c==""||c==null)c=_text;
deeplink=href.replace("http://"+location.hostname+"/",""); 设置deeplink
if(deeplink=="")deeplink="!"; 如果deeplink为空或带!
addresschanged=true;
$.address.value(deeplink);
window.document.title=c+;
return false
});
$.address.change(function(event){ 监控地址栏变化
var value=event.value,current=$("#content"),href;
if(value.indexOf("comment")!==1){
if(value=="/"){ 通过几步判断锚点是否需要加载
href=location.href;
}
else {
if(value=="/!"){href="http://"+location.hostname+"";
addresschanged=true
}
else{
href="http://"+location.hostname+""+value+"";
addresschanged=true
}
}
if(addresschanged==true){loadpage(href)} 如果addresschanged为真 执行loadpage函数(loadpage函数就是AJAX加载代码)
}
});

是不是很方便通过锚点变化里进行ajax操作,若是首页地址则变成 http://soz.im/#/! 如果其它页面则变成http://soz.im/#/xxxx.html。想了解更多详细问题可以去 http://www.asual.com/jquery/address/了解。

如果你不想使用jquery插件,并且你只准备到支持html5的浏览器使用的话 可以使用下面的方法。HTML5中引进了2个API:history.pushState, history.replaceState。可以通过pushState和replaceState接口操作浏览器历史,并且改变当前页面的URL。pushState是将指定的URL添加到浏览器历史里,replaceState是将指定的URL替换当前的URL。

var state = {
title: title,
url: options.url,
otherkey: othervalue
};
window.history.pushState(state, document.title, url);

调用方法如上。响应浏览器操作如下

window.addEventListener('popstate', function(e){
if (history.state){
var state = e.state;
//do something(state.url, state.title);
}
}, false);

这样就可以结合ajax和pushState完美的进行无刷新浏览了。

到这里wordpress的全站AJAX加载主要问题已经结束。剩下的应该都是一些根据自己的问题来操作的一些小问题。如果你对JS比较熟悉的话 应该是很简单的问题 当然对我写的这些也会这样认为。想更好的了解这些问题 还是多研究下js和jquery 让你更得心应手。

From: http://soz.im/wordpress-full-ajax-loaded-3-change-of-address-bar.html

WordPress的全站Ajax加载(二)异步加载

上文。通过寥寥几条评论 还是能看出大家比较喜欢这种局部刷新的效果的。今天将带大家进入异步加载的核心部分。另外由于个人不是从事IT相关的工作 有时候比较忙,更新文章不是很勤快,请谅解 呵呵。我也只是上学的时候学过一点C和java后来也无疾而终,这方面的东西也只是爱好。我也只能抽空写点东西,比如上班的时候-,-就是今天。好,不啰嗦 走起。

Ajax其实比较比较泛指,最低层的应该是.ajax(); 基于这个底层方法 JQuery又有多种类型。比如 .load(); .getScprit();  .getJSON(); 等等…想了解的话 可以自己去看API文档。最近单的应该就是.load();方法了。有多简单呢?

$("#contents").load("url #contents");

完了? 对完了。这行代码的意思就是 在页面的#contents DIV内载入地址为URL的页面,并且只取#contents元素内容,其他丢弃。当然只靠这一句代码是完成不了所有动作的,那就需要你的想象力了,请看下面内容:

$('a[target!=_blank]').live('click',function(){                   //所有a链接不为新标签打开的链接 绑定click事件。
var url = $(this).attr("href"); //获取a链接的地址
var title = $(this).attr("title"); //获取新链接的title
$('#contents').fadeTo(500,0.3); //内容部分模糊
#("#contents").load("url #contents",function(){ //开始加载
$('#contents').fadeTo(200,1); //完成后 内容部分重新显示
window.document.title = title; //设置标题
});
})

好了,这样就基本完成基本功能了。以上是使用.load()方法实现的异步加载。是不是很简单,如果你想使用底层的.ajax方法 那就请继续往下看。

在之前一片文章,我们提到过 如果想让ajax彻底不加载head,sidebar,foot等部分 需要传值。当然不加载这部分优缺点都有。优点自然是减少请求数据提高访问速度。缺点就是不执行head部分,你的wordpress插件可能有的地方会失效,还有就是获取不到新页面的关键字 准确的标题等。怎么传值呢?首先你要明白,用户第一次进来的时候 是全部加在的,直到ajax执行了 才不去加载。而搜索引擎是不会去执行你的JS文件的。所以搜索引擎下 就不怕只输出部分内容 影响soe了。 在wordpress中 公用的部分 都是使用  这样来调用的。那么我们可以用下面的方法传值。

另外 get_sidebar(); 和 get_footer(); 也用同样使用上面方法传值。(去掉#号)                                         这样$soz的值就是load。 不等于后面的ajax后 就会加载。这样我们在后面的ajax中 给$soz传值为ajax后。 就不会加载这部分了。详细如下:

$('a[target!=_blank]').live('click',function(){                   //所有a链接不为新标签打开的链接 绑定click事件。
var url = $(this).attr("href"); //获取a链接的地址
var title = $(this).attr("title"); //获取新链接的title
$('#contents').fadeTo(500,0.3);
$.ajax({
url:url,
data: "soz=ajax", //传值
dataType: "html",
type: "post", //使用post方式加载
success:function(message){
var msger = $("message");
window.document.title = ttitle;
$("#content").html(msger);
$('#contents').fadeTo(200,1);
script = jQuery("#afterrun script"); //解决ajax JS运行的问题。
for (var i = 0;i < script.length;i++) eval(jQuery(script[i]).html());
}
,
error: function() {
$("#content").html("AJAX Error...");
} ,
});
})

好了上面代码就是通过底层.ajax方法实现的。和之前的.load方法 差不多。需要注意的就是 js在ajax后 执行的问题。到这里,ajax的核心代码已经完成 。其他动作那就要根据你自己来制定了。不如ajax过程中的动画,啥的小细节。我相信如果你对JQuery比较熟悉的话 应该也是很容易的一件事。

通过上面的方法,你会发现AJAX加载时没什么问题的,但是地址栏的URL是不会改变的。前进后退也不能用。那改怎么解决呢?不要着急,我会在下一篇文章中为大家介绍我使用过的2种方案,欢迎大家来围观。。。

 

From: http://soz.im/wordpress-full-ajax-load-2-asynchronous-loading.html

WordPress的全站Ajax加载(一)扯独自

大家好,经过了大约一年 我终于更新文章了-,- 。至于为什么这么久呢 在这里我也就不多了说,我在about也没也简单介绍过了。今天不是来扯独自的(雾)~。从这篇文章开始我就将分多次向大家介绍全站Ajax的实现。高手请绕行,菜鸟估计也会有点晕,我也尽量从我这个菜鸟角度出发,说的通俗易懂。说道Ajax,也许大家不是很陌生,最常见的应该 就是评论Ajax提交了。如果你还想直观点的了解,你可以点击我的站内随便的链接。(注:你的浏览器支持html5)你会发现head,sidebar,foot部分都不会刷新,只刷新了文章部分。而且地址栏也会做出相应改变,可以使用前进后退按钮。不要被备注迷惑,不是支持Html5的浏览器才能Ajax的。Ajax有什么好处么?当然就如你看到的只加载你需要的部分,提高了网页的用户体验。减少了加载数据。当然也存在缺点,不会改变URL,当然也就不能使用前进后退。对搜索引擎不友好,如果你ajax请求的页面是不存在真实地址的话,就不会被索引到。接下来我会通过其他方式了弥补缺点发扬优点..在Wordpress上合理使用Ajax。

上面说过对搜索引擎的问题,所以这里我们Ajax加载将会采用加载真实地址,不会通过后台函数输出想要的内容。这样搜索引擎会访问到真实的地址,而用户则会ajax加载需要的内容。还有个问题就是ajax真实地址后我们加载的数据跟直接访问会一样 再次加载了不需要的内容。当然我们可以从过在AJax后删除不需要的内容,这些内容也仅仅是Html代码 还不回被真正执行。当时PHP后台还是会浪费资源输出这些。要想真正放弃加载需要内容之外的东西。这里会做个判断,当用户第一次进入网页 会加载head,sidebar,foot。当点击站内链接后。会在加载之前给这几个不需要加载的部分传值。让这些内容不输出。而搜索引擎是不会执行JS代码的,会正常访问页面。

另外个问题就是Ajax后,地址栏变化的问题。我们可以通过Jquery的history插件,或者使用html5自带的API:history.pushState和history.replaceState来实现。这个会在后面为大家详细介绍。

当然AJax的关键代码页很少,内容如下:

$.ajax({
url: ajaxUrl,
type: 'get-or-post',
error: function() {
//抛出错误
},
success: function() {
//抛出完成代码
}

但是比较繁琐的问题是之后的一些问题。这篇文章只是一个预热,我会在接下来的几篇文章为大家一一详细介绍。欢迎有兴趣的朋友围观,说的不好也别拍砖=。=

From:http://soz.im/wordpress-full-ajax-loading-1-alone.html

超棒的视觉效果jQuery插件 – FractionSlider

   应领导要求,在给公司做专题的时候,需要给专题加上slider里文字图片等的飞入飞出淡入淡出等效果,google之,发现FractionSlider ,DEMO请移步http://jacksbox.de/stuff/jquery-fractionslider/

   使用非常简单,先引入css和js,如下:



 

 

 
 

   需要使用动画的元素示例如下:

   调用FractionSlider插件

jQuery(window).load(function(){
 $(‘.slider’).fractionSlider();
});

   下载地址:https://github.com/jacksbox/jquery.fractionslider

   Via:http://leapsoul.com/great-parallax-effects-jquery-plugin-fractionslider/

企鹅手机网幻灯片JQ代码

HTML代码:

  • 6000台企鹅F1
  • 打假
  • 企鹅F2
  • 企鹅F1

JQ插件代码:

(function($) {
    $.fn.slideImg = function(settings) {
        settings = jQuery.extend({
            speed: "normal",
            timer: 1000
        }, settings);
        return this.each(function() {
            $.fn.slideImg.scllor($(this), settings);
        });
    };
           
    $.fn.slideImg.scllor = function($this, settings) {
        var index = 0;
        var scllorer=$this.find(".img-box li");
        var size=scllorer.size();
        var slideH=scllorer.outerHeight();
                   
        var $selItem2=$("
",{"class":"transparent_class"}).appendTo($this); var $selItem=$("
",{ "class":"flash_item", html:function(){ var $selItemHTML=""; if(size==1){ return; }else if(size>1){ for(var i=0;i'+(i+1)+'':$selItemHTML+=''+(i+1)+''; } return $selItemHTML; } } }).appendTo($this); var li = $(".flash_item span"); var showBox = $(".img-box"); var intervalTime=null; li.hover(function() { var that=this; if (intervalTime) { clearInterval(intervalTime); } intervalTime = setTimeout(function() { index = li.index(that); ShowAD(index); }, 200); }, function() { clearInterval(intervalTime); interval(); }); showBox.hover(function() { if (intervalTime) { clearInterval(intervalTime); } }, function() { clearInterval(intervalTime); interval(); }); function interval(){ intervalTime = setInterval(function() { ShowAD(index); index++; if (index == size) { index = 0; } }, settings.timer); } interval(); var ShowAD = function(i) { showBox.animate({ "top": -i * slideH }, settings.speed); // showBox.children().eq(i).slideDown('normal'); // showBox.children().not(showBox.children().eq(i)).slideUp('normal'); $(".flash_item span").eq(i).addClass("on").siblings().removeClass("on"); }; }; })(jQuery);

启用插件JQ:

CSS样式:

.flash_img {
    POSITION: relative; WIDTH: 960px; HEIGHT: 640px; OVERFLOW: hidden; margin-left:auto; margin-right:auto
}
.flash_img .img-box {
    POSITION: absolute
}
.flash_img .img-box LI {
    PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; PADDING-TOP: 0px
}
.transparent_class {
    /*POSITION: absolute; FILTER: alpha(opacity=30); WIDTH: 100%; BOTTOM: -1px; BACKGROUND: #000; HEIGHT: 42px; LEFT: 0px; -moz-opacity: 0.3; -khtml-opacity: 0.3; opacity: 0.3*/
}
.flash_item {
    POSITION: absolute; TEXT-ALIGN: center; BOTTOM: 40px; RIGHT: 40px
}
.flash_item SPAN {
    POSITION: relative; TEXT-ALIGN: center; LINE-HEIGHT: 15px; TEXT-INDENT: -9999px; MARGIN: 0px 0px 0px 8px; WIDTH: 15px; DISPLAY: block; BACKGROUND: #C1C1C1; FLOAT: left; HEIGHT: 15px; CURSOR: pointer
}
.flash_item SPAN.on {
    BACKGROUND: #ff9900; COLOR: #ffffff; FONT-WEIGHT: bold
}

OK!大功告成!

基于jQuery插件的Tab选项卡效果 自由设置切换效果 支持自动播放

TAB(选项卡)效果是网页中常见的页面效果 实现它也有N种方式,在给大家推荐一款 基于jQuery 的TAB插件  其特色是可以较为自由的设置各种选项,达到自己需要的效果。样式没有写,只写了够实现功能的,至于美好就自己去写CSS去美化一下好了。

主要功能:
实现选项卡切换
内置五种切换方式 可以通过参数设置来设定
可以选择触发方式 是点击还是划过
是否自动切换

点击查看DEMO   点击下载JS备用下载

使用方式:

$("#testtab").tab({
   tabId:"#tabtag", //切换控制器的ID
   tabTag:"li",  //切换控制器标签
   conId:"#tabcon", //内容容器ID
   conTag:"div",  //容器标签
   act:"click", //点击触发 也可以不设置 默认就为click 设置为 mouseover则为划过
   effact: "scrolly" //效果为纵向滚动 , scrollx: 横向滚动 , "slow" : slow效果
   auto:true, //自动滚动,默认false
   dft:2 //设置起始显示序列
   })

DOM 结构:

实例:

$("#testtab").tab({
    tabId:"#tabtag", //切换控制器的ID
    tabTag:"li",  //切换控制器标签
    conId:"#tabcon", //内容容器ID
    conTag:"div",  //容器标签
    act:"click", //点击触发 也可以不设置 默认就为click 设置为 mouseover则为划过
    effact: "scrolly" //效果为纵向滚动
    dft:0
    })

插件代码:

function cur(ele,currentClass,tag){ //标记当前函数
        ele= $(ele)? $(ele):ele;
        if(!tag){
            ele.addClass(currentClass).siblings().removeClass(currentClass);
            }else{
                ele.addClass(currentClass).siblings(tag).removeClass(currentClass);
                }
        }
    $.fn.tab=function(options){ //插件开始
    var org={ //原始设置
        tabId:    "",
        tabTag:   "",
        conId:    "",
        conTag:   "",
        curClass: "cur",
        act:      "click",
        dft:      0,
        effact:   null,
        auto:     false,
        autotime: 3000,
        aniSpeed: 500
        }   
                  
    $.extend(org,options); //合并自定义设置
              
    var t=false; //自动开始定时器
    var k=0; //切换序列 默认为0
    var _this=$(this); //取得当前元素
    var tagwrp=$(org.tabId); //切换控制器容器
    var conwrp=$(org.conId); //切换控制器标签
    var tag=tagwrp.find(org.tabTag); //切换容器的容器
    var con=conwrp.find(org.conTag); //切换内容的容器   
    var len=tag.length; //有多少个项目
    var taght=parseInt(tagwrp.css("height")); //得到控制器高度
    var conwh=conwrp.get(0).offsetWidth; //得到控制器宽度
    var conht=conwrp.get(0).offsetHeight; //以及高度
    var curtag=tag.eq(org.dft); //初始控制器标签
    //初始化tab
    cur(curtag,org.curClass); //标记默认序列
    con.eq(org.dft).show().siblings(org.conTag).hide(); //显示默认项目
              
    if(org.effact=="scrollx"){ //如果使用 横向滚动 则准备CSS 条件
        var padding=parseInt(con.css("padding-left"))+parseInt(con.css("padding-right"));                                       
        _this.css({
                  "position"   :"relative",
                  "height"     :taght+conht+"px",
                  "overflow"   :"hidden"
                  });               
                  
        conwrp.css({
                   "width"     :len*conwh+"px",
                   "height"    :conht+"px",
                   "position"  :"absolute",
                   "top"       :taght+"px"
                   });
                  
        con.css({
                "float"        :"left",
                "width"        :conwh-padding+"px",
                "display"      :"block"
                });
        }
                  
    if(org.effact=="scrolly"){ //如果使用 纵向滚动 则准备CSS 条件
        var padding=parseInt(con.css("padding-top"))+parseInt(con.css("padding-bottom"));                                       
        _this.css({
                  "position"   :"relative",
                  "height"     :taght+conht+"px",
                  "overflow"   :"hidden"
                  });
        tagwrp.css({
                   "z-index"   :100
                   })       
        conwrp.css({
                   "width"     :"100%",
                   "height"    :len*conht+"px",
                   "position"  :"absolute",
                   "z-index"   :99                                                
                   })       
        con.css({
                "height"       :conht-padding+"px",
                "float"        :"none",                                           
                "display"      :"block"
                });
        }   
              
    tag.css({"cursor":"pointer"}) //切换控制标签用手性鼠标
        .each(function(i){ //循环切换
        tag.eq(i).bind(org.act,function(){ //绑定到鼠标动作
                cur(this,org.curClass);    //标记当前
                k=i; //传递序列
                switch(org.effact){ //根据设定的切换效果去转换切换方式                   
                    case "slow"    : con.eq(i).show("slow").siblings(org.conTag).hide("slow"); //slow 效果
                    break;
                    case "fast"    : con.eq(i).show("fast").siblings(org.conTag).hide("fast"); //fast 效果
                    break;
                    case "scrollx" : conwrp.animate({left:-i*conwh+"px"},org.aniSpeed); //横向滚动效果
                    break;
                    case "scrolly" : conwrp.animate({top:-i*conht+taght+"px"},org.aniSpeed); //纵向滚动效果
                    break;
                    default        : con.eq(i).show().siblings(org.conTag).hide(); //默认切换
                    break;
                    //End of switch
                    }           
                }       
            )                                     
        })   
              
    if(org.auto){     //自动切换   
        var drive=function(){
            if(org.act=="mouseover"){
                tag.eq(k).mouseover();
                }else if(org.act=="click"){
                tag.eq(k).click();
                }           
            k++;           
            if(k==len) k=0;           
            }
        t=setInterval(drive,org.autotime);   
        }       
    //End of $.fn.tab

Via:http://mengqing.org/archives/jquery-tab-support-auto-play.html

轻量级的jQuery lightbox图片插件 ColorBox

ColorBox 是一个 jQuery Lightbox 插件,轻量级,只有 不到9kb 大小。

支持: 图片,图片群组, slideshow, ajax, inline, 和iframe.

使用方法:
点击下载ColorBox插件,然后将 jquery.colorbox-min.js 和 CSS文件放上去(有4中样式,自己爱好选择)




然后将下面代码复制到  functions.php 文件中:

function colorbox ($content)
{   global $post;
    $pattern = "/]*).(bmp|gif|jpeg|jpg|png)('|\")(.*?)>(.*?)< \/a>/i";
    $replacement = '$7';
    $content = preg_replace($pattern, $replacement, $content);
    return $content;
}
add_filter('the_content', 'colorbox'); //所有图片 加上一个 rel="colorbox"

View Demo:
demo1
demo2
demo3
demo4
demo5

Via:http://mengqing.org/archives/jquery-colorbox.html

学习怎么写jQuery插件

jQuery(以下简称JQ)是一个功能强大而又小巧的JS框架,现在很多网站都在使用JQ,本站也不例外。本文教大家如何写一个属于你自己的JQ插件。
本JQ插件例子是在你网站的文章结尾处添加你的版权。
JQ插件标准的封装代码如下,首先需要闭包:

这是jQuery官方的插件开发规范,这样写是作用是:
1. 避免全局依赖。
2. 避免第三方破坏。
3. 兼容jQuery操作符’$’和’jQuery’

接着给插件加入主体:

OK了,这个插件已经完成了,接下来我们来看看调用的方式。
比如你文章所在的div的id=”article-content”,那么在此div后面(先读取到了该div,该div才可以作为后面的JS的对象)加上JS代码: