成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

jQuery Deferred對象

baoxl / 2147人閱讀

摘要:給普通的操作指定回調(diào)函數(shù)對象的最大優(yōu)點,就是它把這一套回調(diào)函數(shù)接口,從操作擴展到了所有操作。方法用于指定對象狀態(tài)為已失敗時的回調(diào)函數(shù)。執(zhí)行完畢執(zhí)行成功執(zhí)行失敗接收一個或多個對象作為參數(shù),為其指定回調(diào)函數(shù)。

什么是deferred對象

開發(fā)網(wǎng)站的過程中,我們經(jīng)常遇到某些耗時很長的javascript操作。其中,既有異步的操作(比如ajax讀取服務器數(shù)據(jù)),也有同步的操作(比如遍歷一個大型數(shù)組),它們都不是立即能得到結(jié)果的。

通常的做法是,為它們指定回調(diào)函數(shù)(callback)。即事先規(guī)定,一旦它們運行結(jié)束,應該調(diào)用哪些函數(shù)。

簡單說,deferred對象就是jQuery的回調(diào)函數(shù)解決方案。在英語中,defer的意思是"延遲",所以deferred對象的含義就是"延遲"到未來某個點再執(zhí)行。

它解決了如何處理耗時操作的問題,對那些操作提供了更好的控制,以及統(tǒng)一的編程接口。它的主要功能,可以歸結(jié)為四點。

ajax的鏈式寫法

我們來看一個$.ajax請求的例子:

$.ajax({
    url: "test.jspx",
    success: function(data) {
        // 請求成功了
        // TODO
    },
    error: function(error) {
        // 請求失敗了
        // TODO
    }
});
    

上面的代碼再常見不過了,不過下面的寫法你也一定看過:

$.ajax("test.jspx")
    .done(function(data) {
        // 請求成功了
        // TODO
    })
    .fail(function(error) {
        // 請求失敗了
        // TODO
    });
    
$.ajax({
    url: "test.jspx",
    type:"POST",
    data: data
}).done(function(data) {
    // 請求成功了
    // TODO
}).fail(function(error) {
    // 請求失敗了
    // TODO
});
    

其實在1.5.0版本的之前的jquery是不支持鏈式寫法的,只能使用第一種寫法,原因是此版本之前的jquery的ajax操作返回的是一個XHR (XMLHttpRequest) 對象,這個對象沒有像donefail這樣的回調(diào)方法。

之后的版本返回的是一個deferred對象用promise方法包裝過的對象,可以進行鏈式操作,使用鏈式寫法后,代碼可讀性大大提高。

為一個操作指定多個回調(diào)函數(shù)

如果要在一個ajax請求成功后再執(zhí)行別的回調(diào)函數(shù),該怎么辦呢? 直接在加在后面就可以了:

$.ajax("test.jspx")
    .done(function(data) {
        // 請求成功了
        // TODO
    }).fail(function(error) {
        // 請求失敗了
        // TODO
    }).done(function(data) {
        // 請求成功了
        // then TODO
    });

這種寫法可以支持無數(shù)個回調(diào)函數(shù),這寫回調(diào)函數(shù)將按照添加順序依次執(zhí)行。

為多個操作指定回調(diào)函數(shù)

如果一個回調(diào)函數(shù)需要在幾個ajax請求都成功后才能執(zhí)行該怎么辦呢?是不是不好控制呢?其實jQuery提供了這樣一個方法$.when() 它可以接收任意個deferred對象,只有所有的deferred對象都狀態(tài)都為成功時才執(zhí)行done回調(diào),否則執(zhí)行fail回調(diào)。

$.when($.ajax("test1.html"), $.ajax("test2.html"))
    .done(function() {
        // 兩個操作都請求都成功
        // TODO
    }).fail(function() {
        // 任意一個失敗
        // TODO
    });

上面代碼中,只有兩個請求都成功后才會執(zhí)行done回調(diào),只要有一個失敗就執(zhí)行fail回調(diào)。

給普通的操作指定回調(diào)函數(shù)

deferred對象的最大優(yōu)點,就是它把這一套回調(diào)函數(shù)接口,從ajax操作擴展到了所有操作。也就是說,任何一個操作----不管是ajax操作還是本地操作,也不管是異步操作還是同步操作----都可以使用deferred對象的各種方法,指定回調(diào)函數(shù)。

var wait = function() {
    var dtd = $.Deferred();     // 新建一個deferred對象
        
    var tasks = function() {      
        alert("執(zhí)行完畢!");      
        dtd.resolve();          // 此操作完成后改變deferred對象的執(zhí)行狀態(tài)                          
    };      
    setTimeout(tasks, 5000);    
    return dtd;  
};

// 綁定回調(diào)函數(shù)                 
$.when(wait())
    .done(function() {
        alert("執(zhí)行成功了!");
    })
    .fail(function() {
        alert("出錯啦!");
    });

上面代碼的中的wait方法模擬了一個很耗時的操作,之后給這個操作指定了回調(diào)函數(shù)donefail。一旦wait執(zhí)行完畢就會立即調(diào)用done這個回調(diào)函數(shù)。

Deferred對象的常用方法

上面已經(jīng)對deferred對象有所了解了,下面介紹一下deferred對象的常用方法。

deferred.resolve()

在jQuery的deferred對象中,規(guī)定了它有三種狀態(tài):

未完成 繼續(xù)等待

已完成 立即調(diào)用done回調(diào)

已失敗 立即調(diào)用fail回調(diào)

resolve方法的作用就是設(shè)置deferred對象狀態(tài)為已完成,deferred對象立刻調(diào)用done()方法指定的回調(diào)函數(shù)

deferred.reject()

reject方法的作用是設(shè)置deferred對象狀態(tài)為已失敗,deferred對象立刻調(diào)用fail()方法指定的回調(diào)函數(shù)

deferred.done()

done方法用于指定deferred對象狀態(tài)為已完成時的回調(diào)函數(shù)。

deferred.fail()

done方法用于指定deferred對象狀態(tài)為已失敗時的回調(diào)函數(shù)。

deferred.then()

then方法接收一到三個參數(shù),分別指定deferred對象狀態(tài)為已成功、已失敗和繼續(xù)等待的回調(diào)函數(shù)。

deferred.always()

always方法用于指定deferred對象狀態(tài)為已成功或已失敗時的回調(diào)函數(shù)。

即無論這個deferred對象是成功還是失敗,只要執(zhí)行完畢都會調(diào)用此方法指定的回調(diào)。

由于此方法指定的回調(diào)函數(shù)的參數(shù)是不確定的(比如ajax請求成功和失敗返回的信息不同,成功時為返回的數(shù)據(jù),失敗則為錯誤信息),最好只使用它的行為,而不檢查其參數(shù)。如果要執(zhí)行的操作和參數(shù)有關(guān),請顯示地指定donefail回調(diào)。如下所示:

$.ajax("test1.html")
    .always(function() {
        // 不管請求是否成功,只要請求完畢就執(zhí)行
        // TODO
        console.log("已請求完畢,狀態(tài)未知");
    });

$.ajax("test1.html")
    .done(function(data) {
        // 請求成功時執(zhí)行
        // TODO
        console.log("請求已成功,返回數(shù)據(jù)為:");
        console.log(data);
    })
    .fail(function(error) {
        // 請求失敗時執(zhí)行
        // TODO
        console.log("請求已失敗,錯誤信息:");
        console.log(error.status, error.statusText);
    });

deferred.progress()

progress方法用于指定deferred對象狀態(tài)為等待中的回調(diào)函數(shù)。但是它僅在deferred對象生成了進度通知時才會被調(diào)用。

請看下面例子:

var wait = function() {
    var dtd = $.Deferred(); // 新建一個deferred對象
        
    var tasks = function() {      
        alert("執(zhí)行完畢!");      
        dtd.resolve(); // 此操作完成后改變deferred對象的執(zhí)行狀態(tài)                           
    };    
    setTimeout(tasks, 5000);    
    return dtd;  
};

// 綁定回調(diào)函數(shù)                 
$.when(wait())
    .done(function() {
        alert("執(zhí)行成功了!");
    })
    .fail(function() {
        alert("出錯啦!");
    })
    .progress(function(){
        console.log("正在執(zhí)行中..."); // 此處不會有任何輸出
    });

上面雖然指定了progress回調(diào),但是卻為沒有任何作用的原因是由于在deferred對象沒有生成進度通知,所以其不會被調(diào)用。

想要progress回調(diào)能執(zhí)行,需要在deferred對象上調(diào)用此回調(diào)。notify方法的作用就是根據(jù)給定的 args參數(shù) 調(diào)用Deferred對象上進行中的progress回調(diào)。

var wait = function() {
    var dtd = $.Deferred(); // 新建一個deferred對象    
    var i = 1,
        timer,
        percent; // 記錄進度


    var tasks = function() {
        if (i == 11) {
            alert("執(zhí)行完畢!");
            dtd.resolve(); // 此操作完成后改變deferred對象的執(zhí)行狀態(tài)
        } else {
            percent = (i * 500) / 5000 * 100 + "%";
            dtd.notify(percent); // 調(diào)用progress回調(diào)
            i++;
            setTimeout(tasks, 500);
        }
    };
    setTimeout(tasks, 1000);
    return dtd;
};
// 綁定回調(diào)函數(shù)
$.when(wait())
    .done(function() {
        alert("執(zhí)行成功了!");
    })
    .fail(function() {
        alert("出錯啦!");
    })
    .progress(function(data) {
        console.log("執(zhí)行中,已完成", data);
    });
// 執(zhí)行中,已完成 10%
// 執(zhí)行中,已完成 20%
// 執(zhí)行中,已完成 30%
// 執(zhí)行中,已完成 40%
// 執(zhí)行中,已完成 50%
// 執(zhí)行中,已完成 60%
// 執(zhí)行中,已完成 70%
// 執(zhí)行中,已完成 80%
// 執(zhí)行中,已完成 90%
// 執(zhí)行中,已完成 100%
// 之后彈出 執(zhí)行完畢!和 執(zhí)行成功了!

這個方法給上傳文件或者耗時操作生成進度條提供了一種可能。

jQuery3.0以上版本對when方法做了大幅調(diào)整。向promise/A+靠齊,上面的寫法中notify是觸發(fā)不了when中的progress回調(diào)的,需要使用promise來給對象部署deferred接口或使用$.Deferred()傳入函數(shù)名。

簡而言之,3.0以以上版本中,上面代碼中progress回調(diào)是不會進去的,應使用以下寫法:

1、promise給一個對象部署Deferred接口:

var dtd = $.Deferred(); // 新建一個deferred對象
var wait = function(dtd) {
    var i = 1,
        timer,
        percent; // 記錄進度
    var tasks = function() {
        if (i == 11) {
            alert("執(zhí)行完畢!");
            dtd.resolve(); // 此操作完成后改變deferred對象的執(zhí)行狀態(tài)
        } else {
            percent = (i * 500) / 5000 * 100 + "%";
            dtd.notify(percent); // 調(diào)用progress回調(diào)
            i++;
            setTimeout(tasks, 500);
        }
    };
    setTimeout(tasks, 1000);        
};
// 在wait對象上部署Deferred接口,此后就可以直接在wait上使用deferred對象promise后的方法了
dtd.promise(wait);
// 在wait對象上使用deferred對象的方法指定回調(diào)。
wait.done(function() {
    alert("執(zhí)行成功了!");
})
.fail(function() {
    alert("出錯啦!");
})
.progress(function(data) {
    console.log("執(zhí)行中,已完成", data);
});
// 執(zhí)行
wait(dtd);

2、使用$.Deferred傳入函數(shù)名:

var wait = function(dtd) {
    var i = 1,
        timer,
        percent; // 記錄進度

    var tasks = function() {
        if (i == 11) {
            alert("執(zhí)行完畢!");
            dtd.resolve(); // 此操作完成后改變deferred對象的執(zhí)行狀態(tài)
        } else {
            percent = (i * 500) / 5000 * 100 + "%";
            dtd.notify(percent); // 調(diào)用progress回調(diào)
            i++;
            setTimeout(tasks, 500);
        }
    };
    setTimeout(tasks, 1000);
    return dtd;
};    
// 綁定回調(diào)函數(shù)
$.Deferred(wait)
    .done(function() {
        alert("執(zhí)行成功了!");
    })
    .fail(function() {
        alert("出錯啦!");
    })
    .progress(function(data) {
        console.log("執(zhí)行中,已完成", data);
    });
deferred.promise()

promise方法的作用是在原來的deferred對象上返回另一個deferred對象,后者只開放與改變執(zhí)行狀態(tài)無關(guān)的方法(比如done()方法和fail()方法),屏蔽與改變執(zhí)行狀態(tài)有關(guān)的方法(比如resolve()方法和reject()方法),從而使得執(zhí)行狀態(tài)不能被改變。

                  
        var dtd = $.Deferred(); // 新建一個Deferred對象
          
        var wait = function(dtd) {    
            var tasks = function() {      
                alert("執(zhí)行完畢!");      
                dtd.resolve(); // 改變Deferred對象的執(zhí)行狀態(tài)            
            };    
            setTimeout(tasks, 5000);    
            return dtd;  
        };  
        $.when(wait(dtd))  
            .done(function() {
                alert("執(zhí)行成功!");
            })  
            .fail(function() {
                alert("出錯啦!");
            });
        dtd.reject(); // 改變狀態(tài)為失敗,將立即觸發(fā)fail 5s后完成再出發(fā)done


如果我們把deferred對象定義在了函數(shù)外部,那么我們設(shè)置deferred對象的狀態(tài)就會導致調(diào)用對應的回調(diào)。上面代碼中,最后調(diào)用reject方法,會導致立即調(diào)用了fail回調(diào),5s之后又彈出執(zhí)行完畢和執(zhí)行成功。這將會導致不必要的混亂。使用promise方法就是一種解決方案。(之前寫的將var dtd = $.Deferred()放在函數(shù)內(nèi)部,使得外部訪問不到也是一種解決方案)。

var dtd = $.Deferred(); // 新建一個Deferred對象
  
var wait = function(dtd) {    
    var tasks = function() {
        alert("執(zhí)行完畢!");      
        dtd.resolve(); // 改變Deferred對象的執(zhí)行狀態(tài)
    };    
    setTimeout(tasks, 5000);    
    return dtd.promise(); // 返回promise對象
      
};  
var d = wait(dtd); // 新建一個d對象,改為對這個對象進行操作
  
$.when(d)
    .done(function() {
        alert("哈哈,成功了!");
    }).fail(function() {
        alert("出錯啦!");
    });  
d.resolve(); // d.resolve is not a function 經(jīng)過promise后沒有resolve方法了

我們看一下Deferred對象和它promise之后的區(qū)別。

promise返回的對象上已經(jīng)去掉了和改變狀態(tài)有關(guān)的方法。notifynotifyWith是調(diào)用progress回調(diào),resolvereject用于設(shè)置其狀態(tài),帶with的方法可指定上下文環(huán)境。

此方法還可以接收Object類型的參數(shù),deferred.promise()會將事件綁定到該參數(shù)上,然后返回該對象,而不是創(chuàng)建一個新的對象。 這個方法可以用于在已經(jīng)存在的對象上綁定 Promise 行為的情況。示例如下:

var dtd = $.Deferred(); // 生成Deferred對象
  
var wait = function(dtd) {    
    var tasks = function() {      
        alert("執(zhí)行完畢!");      
        dtd.resolve(); // 執(zhí)行完畢后改變Deferred對象的執(zhí)行狀態(tài)
            
    };    
    setTimeout(tasks, 5000);  
};   
// 在wait對象上部署Deferred接口,此后就可以直接在wait上使用deferred對象promise后的方法了
dtd.promise(wait);
// 在wait對象上使用deferred對象的方法指定回調(diào)。
wait.done(function() {
    alert("哈哈,成功了!");
})  .fail(function() {
    alert("出錯啦!");
});  
// 執(zhí)行
wait(dtd);

$.Deferred()

$.Deferred()除了創(chuàng)建一個deferred對象之外,可以接受一個函數(shù)名(注意,是函數(shù)名)作為參數(shù),$.Deferred()所生成的deferred對象將作為這個函數(shù)的默認參數(shù)。

var wait = function(dtd) {    
    var tasks = function() {      
        alert("執(zhí)行完畢!"); 
        dtd.resolve();         
    };    
    setTimeout(tasks, 5000);      
};

$.Deferred(wait)
    .done(function() {
        alert("執(zhí)行成功!");
    })
    .fail(function() {
        alert("執(zhí)行失??!");
    });

$.when()

接收一個或多個deferred對象作為參數(shù),為其指定回調(diào)函數(shù)。

見為多個操作指定回調(diào)函數(shù)

deferred.then的傳遞作用

之前我們介紹了,then方法接一到三個參數(shù),分別指定deferred對象狀態(tài)為已成功、已失敗和繼續(xù)等待的回調(diào)函數(shù)。

除此之外,then還可以傳遞遲延對象。我們知道,deferred可以鏈式操作的原因是其返回的仍是deferred對象。then中的回調(diào)函數(shù)如果沒有返回新的deferred對象時,將依然使用最開始的那個deferred對象,如果在其也行返回一個deferred對象時,之后的操作將被轉(zhuǎn)移到在回調(diào)函數(shù)中return出來的新的deferred對象,從而進行傳遞。

我們來看一個例子:

有5個js文件,其內(nèi)容如下:

// perosn.js
var Person = function(name){
    this.name= name;
};

// person.prototype.js
if (Person) {
    Person.prototype.showName = function() {
        return this.name;
    };
} else {
    console.error("Person is undefined!");
}

// zs.js
var zs = new Person("張三");

// ls.js
var ls = new Person("李四");

// introduce.js
var introduceEachOther = function() {
    console.log("張三:你好,我叫" + zs.showName());
    console.log("李四:你好,我叫" + ls.showName());
};

文件內(nèi)容都非常簡單,僅做演示使用,但是其中的依賴關(guān)系非常明顯,person.prototype.js依賴于perosn.js,zs.js和ls.js依賴于person.js,introduce.js依賴于其他所有的js。

要分步加載,并保證可用,就必須保證在加載當前js時,其依賴的js已經(jīng)加載完畢。

使用傳統(tǒng)的寫法,勢必會嵌套多層,不僅邏輯不好處理,而且可讀性很差。

我們用then演示一下如何來傳遞遞延對象來完成這個操作。

$.ajax({
    url: "person.js",
    dataType: "script"
}).then(function() {
    console.log(Person); // person.js已經(jīng)加載成功
    console.log("person.js已經(jīng)加載成功"); 
    return $.ajax({
        url: "person.prototype.js",
        dataType: "script"
    });
}).then(function(data) {
    // 這里的data 上一步請求文件的內(nèi)容 是person.prototype.js而非person.js
    console.log(data);
    console.log(Person.prototype.showName);
    console.log("person.prototype.js已經(jīng)加載成功");
    // person.prototype.js 已經(jīng)加載
    return $.when($.ajax({
        url: "zs.js",
        dataType: "script"
    }), $.ajax({
        url: "ls.js",
        dataType: "script"
    }));
}).then(function(){
    // zs.js 和 ls.js 都加載完成
    console.log(zs,ls);
    console.log("zs.js和zs.js已經(jīng)加載成功");       
    return $.ajax({
        url: "introduce.js",
        dataType: "script"
    });
},function(){
    console.log("zs.js or ls.js failed");
}).then(function(){
    // 到此前面的所有資源都是加載成功的
    console.log("introduce.js已經(jīng)加載成功,且其依賴資源都加載成功了,可以使用了");       
    introduceEachOther();
});

在線地址

以上處理順序只是舉例演示,只要保證person.js最先加載,introduce.js最后加載,person.prototype.js在person.js之后即可。ls.js、zs.js與person.prototype.js的順序可以調(diào)整。

我們每次在then的第一個回調(diào)中返回了而一個新的遞延對象,之后的操作就是基于你返回的那個遞延對象了,第二個then回調(diào)中輸出的data證明了這一點。(如果沒有return出一個新的遞延對象的話,依然使用之前的那個。)

參考鏈接:

本文是照著下面的文章加上自己的學習體會書寫的。

阮一峰:jQuery的deferred對象詳解

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/82273.html

相關(guān)文章

  • jquery 中的 deferred 對象

    摘要:中文文檔簡單說,對象就是的回調(diào)函數(shù)解決方案。為了讓回調(diào)函數(shù)的名字統(tǒng)一,便于在中使用。普通操作的回調(diào)函數(shù)接口對象的最大優(yōu)點,就是它把這一套回調(diào)函數(shù)接口,從操作擴展到了所有操作。指定操作成功時的回調(diào)函數(shù)。 參考鏈接 jQuery API中文文檔 jQuery.Deferred jQuery.when jQuery的deferred對象詳解 jQuery deferred 對象的 prom...

    Meathill 評論0 收藏0
  • $.when().done().then()的用法

    摘要:通常的做法是,為它們指定回調(diào)函數(shù)。指定操作成功時的回調(diào)函數(shù)指定操作失敗時的回調(diào)函數(shù)沒有參數(shù)時,返回一個新的對象,該對象的運行狀態(tài)無法被改變接受參數(shù)時,作用為在參數(shù)對象上部署接口。 jQuery的開發(fā)速度很快,幾乎每半年一個大版本,每兩個月一個小版本。 每個版本都會引入一些新功能。今天我想介紹的,就是從jQuery 1.5.0版本開始引入的一個新功能----deferred對象。 這個功...

    KoreyLee 評論0 收藏0
  • jQuerydeferred對象詳解

    摘要:通常的做法是,為它們指定回調(diào)函數(shù)。簡單說,對象就是的回調(diào)函數(shù)解決方案。指定操作成功時的回調(diào)函數(shù)指定操作失敗時的回調(diào)函數(shù)沒有參數(shù)時,返回一個新的對象,該對象的運行狀態(tài)無法被改變接受參數(shù)時,作用為在參數(shù)對象上部署接口。 轉(zhuǎn)自:阮一峰:http://www.ruanyifeng.com/blo... 一、什么是deferred對象?開發(fā)網(wǎng)站的過程中,我們經(jīng)常遇到某些耗時很長的javascri...

    lei___ 評論0 收藏0
  • 通過 ES6 Promise 和 jQuery Deferred 的異同學習 Promise

    摘要:和和都有和,但是略有不同。實際上返回的是一個對象。和添加的回調(diào),添加的回調(diào)。所以在調(diào)用成功的情況下執(zhí)行添加的回調(diào),調(diào)用失敗時執(zhí)行添加的回調(diào)。,產(chǎn)生對象并,產(chǎn)生對象并,然后繼續(xù)處理,的語法糖,和的差不多但不同。 Deferred 和 Promise ES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同。不過它們的作用可以簡單的用兩句話來描述 Deffere...

    Yujiaao 評論0 收藏0
  • jQuery源碼解析Deferred異步對象

    摘要:回調(diào)隊列對象,用于構(gòu)建易于操作的回調(diào)函數(shù)集合,在操作完成后進行執(zhí)行。對象對象,用于管理回調(diào)函數(shù)的多用途列表。如果傳入一個延遲對象,則返回該對象的對象,可以繼續(xù)綁定其余回調(diào),在執(zhí)行結(jié)束狀態(tài)之后也同時調(diào)用其回調(diào)函數(shù)。 在工作中我們可能會把jQuery選擇做自己項目的基礎(chǔ)庫,因為其提供了簡便的DOM選擇器以及封裝了很多實用的方法,比如$.ajax(),它使得我們不用操作xhr和xdr對象,直...

    Coding01 評論0 收藏0
  • Promise介紹--DeferredjQuery

    摘要:我們稱為回調(diào)對象,它內(nèi)部會維護一個數(shù)組,我們可以向其中添加若干個回調(diào)函數(shù),然后在某一條件下觸發(fā)執(zhí)行。第一次之后,再次新的回調(diào)函數(shù)時,自動執(zhí)行回調(diào)。當前面的回調(diào)函數(shù)返回時,終止后面的回調(diào)繼續(xù)執(zhí)行。 最近懶癌發(fā)作,說好的系列文章,寫了一半,一直懶得寫,今天補上一篇。 Deferred 我們在使用promise對象時,總會提到一個與它關(guān)系密切的對象——Deferred。其實Deferred沒...

    Darkgel 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<