摘要:屬性是此次響應(yīng)的文本內(nèi)容。我們可以通過(guò)屬性,指定這個(gè)事件的回調(diào)函數(shù),對(duì)不同狀態(tài)進(jìn)行不同處理。尤其是當(dāng)狀態(tài)變?yōu)榈臅r(shí)候,表示通信成功,這時(shí)回調(diào)函數(shù)就可以處理服務(wù)器傳送回來(lái)的數(shù)據(jù)。由于臨時(shí)的服務(wù)器維護(hù)或者過(guò)載,服務(wù)器當(dāng)前無(wú)法處理請(qǐng)求。
XMLHttpRequest JSON AJAX CORS 四個(gè)名詞來(lái)開會(huì)如何發(fā)請(qǐng)求
在前端的世界里也逛蕩了不少日子了,目前已經(jīng)get到大約5種發(fā)起請(qǐng)求的方式,主流的、非主流的。
何種方式 | 請(qǐng)求方法 | |
---|---|---|
最常見的form表單 | 默認(rèn)GET,多用POST,只此兩種 | 會(huì)刷新頁(yè)面或者新開頁(yè)面 |
a 標(biāo)簽 | GET請(qǐng)求 | 也會(huì)刷新頁(yè)面或者新開頁(yè)面 |
img的src屬性 | GET | 只能以圖片的形式展現(xiàn) |
link標(biāo)簽 | GET | 只能以CSS、favicon的形式展現(xiàn) |
script標(biāo)簽 | GET | 只能以腳本的形式運(yùn)行 |
可是
我們可能想用GET POST PUT DELETE 方法
不想刷新整個(gè)頁(yè)面,想用一種更易于理解的方式來(lái)響應(yīng)
AJAX出現(xiàn) 瀏覽器和服務(wù)器交互模式 V1.0在AJAX未出現(xiàn)之前,瀏覽器想從服務(wù)器獲得資源,注意是獲取資源,會(huì)經(jīng)過(guò)如下一個(gè)過(guò)程
瀏覽器發(fā)起請(qǐng)求->服務(wù)器接到請(qǐng)求響應(yīng)給你HTML文檔->瀏覽器收到資源,刷新頁(yè)面,加載獲得的的HTML。簡(jiǎn)略的過(guò)程
我稱這種交互方式是 V1.0,此時(shí)還是以獲取資源為導(dǎo)向。后來(lái)隨著時(shí)代的發(fā)展,人們?nèi)找嬖鲩L(zhǎng)的文化需求成為了社會(huì)的主要矛盾……有一天,小明看了一篇報(bào)道,他只是想在下面評(píng)論一下,發(fā)表對(duì)實(shí)事的親切問候,問候完了,唉,你給我刷新頁(yè)面干啥,我只是想評(píng)論一下啊。
大概那是網(wǎng)民們第一次對(duì) 良好的用戶體驗(yàn) 提出了要求。后來(lái)的蘋果爸爸,把大家慣壞了,天天嚷著 "你這產(chǎn)品用戶體驗(yàn)太差了"……
彼時(shí),微軟還是對(duì)web做出了很大的貢獻(xiàn)的。
交互模式2.0大約1999年,微軟發(fā)布IE 5.0版本,它允許JavaScript腳本向服務(wù)器發(fā)起HTTP請(qǐng)求。不過(guò)很遺憾,當(dāng)時(shí)也沒有火起來(lái),直到2004年Gmail發(fā)布和2005年Google Map發(fā)布,才引起廣泛重視。2005年,一個(gè)叫Jesse James Garrett的人提出了一個(gè)新術(shù)語(yǔ)----AJAX,它是一系列技術(shù)的組合體,全稱是 Asynchronous JavaScript + XML(異步的JS和XML)可以阻止頁(yè)面整體刷新,只是動(dòng)態(tài)響應(yīng)用戶的操作,快速顯示到局部,用戶就可以很愉快的繼續(xù)上網(wǎng)了。
AJAX
可以看出IE當(dāng)時(shí)還是很猛的,隨著IE 6.0 市場(chǎng)份額進(jìn)一步擴(kuò)大,IE已經(jīng)把火狐整的半死不活,放眼整個(gè)瀏覽器市場(chǎng),微軟是當(dāng)之無(wú)愧的王者,后來(lái)微軟就把瀏覽器團(tuán)隊(duì)解散了……不得不說(shuō)這是一波神操作,能與之媲美的操作大概只有殘血我能反殺 塔下我能秀他了。微軟強(qiáng)行為后續(xù)各家瀏覽器的發(fā)展提供了優(yōu)秀的工程師,尤其是08、09年出生的谷歌瀏覽器,再看如今的IE……
既然AJAX是一系列的技術(shù)的組合體,接下來(lái)認(rèn)識(shí)一下其中的幾位主角
XMLHttpRequestXMLHttpRequest對(duì)象是用來(lái)在瀏覽器和服務(wù)器之間傳輸數(shù)據(jù)的。
古代的操作的是:
瀏覽器構(gòu)造XMLHttpRequest實(shí)例化對(duì)象
用這個(gè)對(duì)象發(fā)起請(qǐng)求
服務(wù)器響應(yīng)一個(gè)XML格式的字符串,是字符串,是字符串,是字符串,也就是說(shuō)響應(yīng)的第四部分是字符串。
JS解析符合XML格式的字符串,更新局部頁(yè)面。
什么是XML,可擴(kuò)展標(biāo)記語(yǔ)言。
以上是最初的用法,用的是XML,前端代碼片段如下
let request = new XMLHttpRequest() //實(shí)例化XMLHttpRequest對(duì)象 request.onreadystatechange = () => { if (request.readyState === 4) { console.log("請(qǐng)求和響應(yīng)都完畢了") if (request.status >= 200 && request.status <= 300) { console.log("說(shuō)明請(qǐng)求成功了") console.log(request.responseText) let parser = new DOMParser() let xmlDoc = parser.parseFromString(request.responseText, "text/xml") //用parser解析request.responseText let c = xmlDoc.getElementsByTagName("body")[0].textContent console.log(c) } else if (request.status >= 400) { console.log("說(shuō)明請(qǐng)求失敗了") } } } request.open("GET", "/xxx") //配置request request.send()
服務(wù)器端的對(duì)應(yīng)代碼片段如下
... response.statusCode = 200 response.setHeader("Content-Type", "text/xml;charset=utf-8") response.write(``) response.end() ... 木木 少少 你好哇 好久不見啊
本地模擬的話,一定要記得開倆不同的端口
例如:
node server.js 8001 node server.js 8002XMLHttpRequest實(shí)例的詳解
正如上面的前端代碼片段寫的一樣,主要用到了open() send()方法, onreadystatechange readyState 屬性。
request.open(method, URL, async)方法。
一般用三個(gè)參數(shù),第一個(gè)參數(shù)是請(qǐng)求的方法,可以用GET POST DELETE PUT等等,URL是用訪問的路徑,async是是否使用同步,默認(rèn)true,開啟異步,不需要做修改即可,所以實(shí)際中只寫前兩個(gè)參數(shù)
如果非要寫false,開啟同步,會(huì)對(duì)瀏覽器有阻塞效應(yīng),而且如果值為false,則send()方法不會(huì)返回任何東西,直到接受到了服務(wù)器的返回?cái)?shù)據(jù)
request.send()方法。
發(fā)送請(qǐng)求. 如果該請(qǐng)求是異步模式(默認(rèn)),該方法會(huì)立刻返回. 相反,如果請(qǐng)求是同步模式,則直到請(qǐng)求的響應(yīng)完全接受以后,該方法才會(huì)返回
readyState屬性。
描述請(qǐng)求的五個(gè)狀態(tài)。
0 === 常量 UNSENT (未打開) open()方法未調(diào)用
1 === OPENED (未發(fā)送) 只是open()方法調(diào)用了
2 === HEADERS_RECEIVED (已獲取響應(yīng)頭) send()方法調(diào)用了,響應(yīng)頭和響應(yīng)狀態(tài)已經(jīng)返回了
3 === LOADING (正在下載響應(yīng)體) 響應(yīng)體下載中,responseText已經(jīng)獲取了部分?jǐn)?shù)據(jù)
4 === DONE (請(qǐng)求完成) 整個(gè)響應(yīng)過(guò)程完畢了。 這個(gè)值是實(shí)際中用到的。
只要不等于4,就表示請(qǐng)求還在進(jìn)行中。
responseText屬性是此次響應(yīng)的文本內(nèi)容。
onreadystatechange屬性。
readyState屬性的值發(fā)生改變,就會(huì)觸發(fā)readyStateChange事件。
我們可以通過(guò)onReadyStateChange屬性,指定這個(gè)事件的回調(diào)函數(shù),對(duì)不同狀態(tài)進(jìn)行不同處理。尤其是當(dāng)狀態(tài)變?yōu)?的時(shí)候,表示通信成功,這時(shí)回調(diào)函數(shù)就可以處理服務(wù)器傳送回來(lái)的數(shù)據(jù)。即前面的代碼片段的處理方式。
其他的方法、屬性、事件詳見阮一峰博客、MDN文檔
習(xí)慣用javaScript的前端是不想和XML打交道的,應(yīng)該用一種符合js風(fēng)格的數(shù)據(jù)格式語(yǔ)言。
JSON后來(lái)一個(gè)美國(guó)程序員道格拉斯·克羅克福特發(fā)明了JSON,解決了上面的問題,這貨還寫了一本蝴蝶書JavaScript語(yǔ)言精粹,還發(fā)明了一個(gè)JS校驗(yàn)器 ----JSLint。
JSON(JavaScript Object Notation) 是一種輕量級(jí)的數(shù)據(jù)交換格式。 易于人閱讀和編寫。同時(shí)也易于機(jī)器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一個(gè)子集。 JSON采用完全獨(dú)立于語(yǔ)言的文本格式,但是也使用了類似于C語(yǔ)言家族的習(xí)慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 這些特性使JSON成為理想的數(shù)據(jù)交換語(yǔ)言。
以上是JSON官網(wǎng)的簡(jiǎn)介,可以看出它是一門全新的語(yǔ)言,不是JavaScript的子集。
JSON很簡(jiǎn)單,數(shù)據(jù)類型和JS有點(diǎn)不同的地方。
JavaScript | JSON |
---|---|
string | "string" 必須寫雙引號(hào) |
number | number |
object | {"object": "name"} 必須雙引號(hào) |
undefined | 沒有 |
null | null |
boolean | 直接寫true false |
array | array |
function | 沒有 |
variable |
瀏覽器的全局對(duì)象window上有JSON對(duì)象,直接使用window.JSON.parse(string)
let string = request.responseText let json = window.JSON.parse(string) //string 要符合JSON的格式
以上是JSON解析部分的代碼。
此時(shí)服務(wù)器端代碼是
response.statusCode = 200 response.setHeader("Content-Type", "text/json;charset=utf-8") response.write(` { "note" : { "to" : "木木", "from" : "少少", "heading" : "你好哇", "content" : "好久不見啊" } } `)
我們?yōu)g覽器有同源政策,不是同協(xié)議 同域名 同端口 的網(wǎng)頁(yè)無(wú)法相互訪問。
4.AJAX恰好是同源政策的擁躉
CORS
如果AJAX向非同源的地址發(fā)起請(qǐng)求,會(huì)報(bào)錯(cuò)。
這種錯(cuò)誤無(wú)法通過(guò)狀態(tài)碼識(shí)別,因?yàn)镠TTP回應(yīng)的狀態(tài)碼有可能是200,也就是說(shuō)即使你看到了200的正確碼,也沒有用
但是form表單無(wú)視同源政策,可以發(fā)起跨域請(qǐng)求。
上述請(qǐng)求響應(yīng)都沒有問題
然而對(duì)于AJAX就不行
... request.open("GET", "http://www.baidu.com") ...
這是為什么呢,因?yàn)?/p>
原頁(yè)面用 form 提交到另一個(gè)域名之后,原頁(yè)面的腳本無(wú)法獲取新頁(yè)面中的內(nèi)容,所以瀏覽器認(rèn)為這是安全的。
而 AJAX 是可以讀取響應(yīng)內(nèi)容的,因此瀏覽器不能允許你這樣做。如果你細(xì)心的話你會(huì)發(fā)現(xiàn),其實(shí)請(qǐng)求已經(jīng)發(fā)送出去了,你只是拿不到響應(yīng)而已。
所以瀏覽器這個(gè)策略的本質(zhì)是,一個(gè)域名的 JS ,在未經(jīng)允許的情況下,不得讀取另一個(gè)域名的內(nèi)容。但瀏覽器并不阻止你向另一個(gè)域名發(fā)送請(qǐng)求。作者:方應(yīng)杭
鏈接:https://www.zhihu.com/questio...
來(lái)源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
那么如何讓AJAX跨域發(fā)起請(qǐng)求呢。
答案是CORS
CORS目前是W3C的標(biāo)準(zhǔn),它允許瀏覽器跨域發(fā)起XMLHttpRequest請(qǐng)求,而且可以發(fā)起多種請(qǐng)求,不像JSONP只能發(fā)起GET請(qǐng)求,全稱是"跨域/源資源共享"(Cross-origin resource sharing)。
如果想要發(fā)起跨域請(qǐng)求 例如: http://wushao.com:8001 要想訪問 http://shaolin.com:8002,可以做如下處理
request.open("GET", "http://wushao.com:8001/xxx") //配置request
服務(wù)器端的代碼需要做如下處理
response.setHeader("Access-Control-Allow-Origin", "http://shaolin.com:8002")
一定要注意是誰(shuí)去訪問誰(shuí),8001去訪問8002,那么8001的前端代碼要告訴8002的后端代碼,咱們是一家人,你和瀏覽器說(shuō)說(shuō)別讓它禁我了。
AJAX一些其他知識(shí)既然可以發(fā)請(qǐng)求,那么請(qǐng)求頭的四部分如何獲得的,響應(yīng)的四部分又是如何獲得呢
獲得請(qǐng)求頭的方法
request.open("GET", "http://shaolin.com:8002/xxx")// 請(qǐng)求的第一部分 request.setRequestHeader("Content-Type", "x-www-form-urlencoded")//請(qǐng)求的第二部分 request.setRequestHeader("wushao", "18") //請(qǐng)求的第二部分 request.send("我要設(shè)置請(qǐng)求的第四部分") //請(qǐng)求的第四部分 request.send("name=wushao&password=wushao") //請(qǐng)求的第四部分
對(duì)應(yīng)的典型的http請(qǐng)求四部分
GET /xxx HTTP/1.1 HOST: http://shaolin.com:8002 Content-Type: x-www-form-urlencoded wushao: 18 name=wushao&password=wushao
獲得響應(yīng)的方法
request.status //響應(yīng)的第一部分 200 request.statusText //響應(yīng)的第一部分 OK request.getAllResponseHeaders //響應(yīng)的第二部分,這個(gè)方法好啊,全部的響應(yīng)頭 request.getResponseHeader("Content-Type") //響應(yīng)的第二部分具體的 request.responseText //響應(yīng)的第四部分
對(duì)應(yīng)的典型的http響應(yīng)的四部分
HTTP/1.1 200 OK Content-Type: text/json;charset=utf-8 { "note" : { "to" : "木木", "from" : "少少", "heading" : "你好哇", "content" : "好久不見啊" } }
回顧一下各個(gè)status對(duì)應(yīng)的意思
100 200 === OK,請(qǐng)求成功 301 === 被請(qǐng)求的資源已永久移動(dòng)到新位置 302 === 請(qǐng)求臨時(shí)重定向,要求客戶端執(zhí)行臨時(shí)重定向 304 === 和上次請(qǐng)求一樣,未改變 403 === 服務(wù)器已經(jīng)理解請(qǐng)求,但是拒絕訪問 404 === 請(qǐng)求失敗,服務(wù)器上沒有這個(gè)資源 502 === 作為網(wǎng)關(guān)或者代理工作的服務(wù)器嘗試執(zhí)行請(qǐng)求時(shí),從上游服務(wù)器接收到無(wú)效的響應(yīng)。 503 === Service Unavailable 由于臨時(shí)的服務(wù)器維護(hù)或者過(guò)載,服務(wù)器當(dāng)前無(wú)法處理請(qǐng)求。
初級(jí)的jq封裝
這是一個(gè)很簡(jiǎn)陋的效果,首先我還是把jq假設(shè)的很簡(jiǎn)單,就是一個(gè)window的屬性,請(qǐng)輕噴……
window.jQuery = function (nodeOrSelector) { let nodes = {} nodes.addClass = function () {} nodes.html = function () {} return nodes } window.jQuery.ajax = function (options) { let url = options.url let method = options.method let headers = options.headers let body = options.body let successFn = options.successFn let failFn = options.failFn let request = new XMLHttpRequest() //實(shí)例化XMLHttpRequest對(duì)象 request.open(method, url) for (let key in headers) { let value = headers[key] request.setRequestHeader(key, value) } request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 300) { successFn.call(undefined, request.responseText) } else if (request.status >= 400) { failFn.call(undefined, request) } } } request.send(body) }
以上就是jq對(duì)ajax的簡(jiǎn)陋的封裝,ajax()方法接受一個(gè)對(duì)象作為參數(shù),這個(gè)對(duì)象有很多鍵。這些鍵就是http請(qǐng)求的頭的各個(gè)部分,以及一個(gè)成功函數(shù)和一個(gè)失敗函數(shù)。
myButton.addEventListener("click", (e) => { window.jQuery.ajax ({ url: "/xxx", method: "POST", headers: { "content-type": "application/x-www-form-urlencoded", "wushao": "18" }, body: "a=1&b=6", successFn: (x) => { ... }, failFn: (x) => { ... } }) })
以上就是簡(jiǎn)化后的使用方法,給button綁定事件的時(shí)候,函數(shù)體直接就是ajax()
目前你會(huì)發(fā)現(xiàn)options這個(gè)對(duì)象傻傻的,因?yàn)榭傆幸恍┯脩舨幌M粋饕粋€(gè)參數(shù)。所以我們稍微改造一下。
let url if (arguments.length === 1) { url = options.url } else if (arguments.length === 2) { url = arguments[0] options = arguments[1] } let method = options.method let headers = options.headers let body = options.body let successFn = options.successFn let failFn = options.failFn
加了一點(diǎn),判斷ajax()的參數(shù)個(gè)數(shù)。
一千個(gè)人有一千零一個(gè)成功或失敗函數(shù)的寫法,所以為了維護(hù)世界和平,大家約定俗成了一套理論 Promise then( )
//Promise這個(gè)對(duì)象呢,大概長(zhǎng)這個(gè)樣子,真實(shí)面目我是沒見過(guò) //簡(jiǎn)單的寫一下promise window.Promise = function (fn) { //...一些其他代碼 return { then: function () {} } }
Promise這個(gè)構(gòu)造函數(shù)呢,又會(huì)返回一個(gè)函數(shù),這個(gè)返回的函數(shù)一個(gè)then屬性,value又是一個(gè)函數(shù)。處處都體現(xiàn)著函數(shù)是第一公民的地位!!!
那我們可以利用這個(gè)強(qiáng)大的Promise對(duì)象搞一些事情了。
//第一步的代碼改造成這樣,第一步用到了ES6的解構(gòu)賦值法 window.jQuery.ajax = function ({url, method, body, headers}) { return new Promise(function (resolve, reject) { let request = new XMLHttpRequest() request.open(method, url) for(let key in headers) { let value = headers[key] request.setRequestHeader(key, value) } request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status >= 200 && request.status <= 300) { resolve.call(undefined, request.responseText) } else if (request.status >= 400) { reject.call(undefined, request) } } } request.send(body) }) }
關(guān)于解構(gòu)賦值:ES6 允許按照一定模式,從數(shù)組和對(duì)象中提取值,對(duì)變量進(jìn)行賦值,這被稱為解構(gòu)(Destructuring)
詳見ES6解構(gòu)賦值
//經(jīng)過(guò)上面這么一折騰,可以很簡(jiǎn)單的使用了 myButton.addEventListener("click", (e) => { let promise = window.jQuery.ajax({ url: "/xxx", method: "get", headers: { "content-type": "application/x-www-form-urlencoded", "wushao": "18" } }) promise.then( (responseText) => { console.log(responseText) }, (request) => { console.log(request) } ) })
注意then可以傳入兩個(gè)函數(shù),第一個(gè)函數(shù)表示成功了執(zhí)行這個(gè),第二個(gè)函數(shù)表示失敗了執(zhí)行這個(gè),而且可以進(jìn)行鏈?zhǔn)秸{(diào)用,一直點(diǎn)下去。
所以實(shí)際上jq的寫法大多是這么寫的
myButton.addEventListener("click", (e) => { $.ajax({ url: "/xxx", type: "GET", }).then( (responseText) => { console.log(responseText) return responseText }, (request) => { console.log("error") return "已經(jīng)處理" } ).then( (responseText) => { console.log(responseText) }, (request) => { console.log(error2) } ) })
鏈?zhǔn)秸{(diào)用的意思就是:成功函數(shù)成功了,就執(zhí)行第二個(gè)then的第一個(gè)函數(shù);成功函數(shù)失敗了,就執(zhí)行第二個(gè)then的第二個(gè)函數(shù)。
完整代碼詳見我的gitHub
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/107111.html
摘要:在通常情況下,為了網(wǎng)站的安全性,對(duì)象只能訪問到與當(dāng)前頁(yè)面位于同一個(gè)域下的資源。由兩部分組成,一部分是回調(diào)函數(shù),一部分是所包含的數(shù)據(jù)。回調(diào)函數(shù)是請(qǐng)求數(shù)據(jù)時(shí)指定,而數(shù)據(jù)則是跨域資源返回的數(shù)據(jù)。 在通常情況下,為了網(wǎng)站的安全性,Ajax對(duì)象只能訪問到與當(dāng)前頁(yè)面位于同一個(gè)域下的資源。但有時(shí)往往需要訪問別的域中的資源,這是就運(yùn)用到了跨域這個(gè)概念,這其中運(yùn)用最廣泛的就是JSONP。JSONP,即J...
摘要:可以說(shuō)同源策略在安全中扮演著及其重要的角色。我把這個(gè)領(lǐng)域的東西寫成了一個(gè)系列,以后還會(huì)繼續(xù)完善下去安全一同源策略與跨域安全二攻擊安全三攻擊 之所以要將同源策略與跨域?qū)懺谝黄穑且驗(yàn)榇嬖跒g覽器的同源策略,才會(huì)存在跨域問題 何為同源策略 同源策略是瀏覽器實(shí)現(xiàn)的一種安全策略,它限制了不同源之間的文檔和腳本交互的權(quán)限。只有同一個(gè)源的腳本才會(huì)具有操作dom、讀寫cookie、session 、a...
摘要:由于瀏覽器的同源策略導(dǎo)致無(wú)法直接通過(guò)拿到后臺(tái)數(shù)據(jù)。目前,如果非同源,共有三種行為受到限制。此處應(yīng)有掌聲參考關(guān)于跨域資源共享和瀏覽器的同源策略限制的具體講解。 工作中,經(jīng)常會(huì)遇到需要跨域請(qǐng)求數(shù)據(jù)的情況。由于瀏覽器的同源策略,導(dǎo)致無(wú)法直接通過(guò)ajax拿到后臺(tái)數(shù)據(jù)。解決這個(gè)問題的方式之一就是JSONP。還有一種方式更高效簡(jiǎn)單——跨域資源共享(Cross-origin Resource Sha...
摘要:方案瀏覽器設(shè)置一級(jí)域名。場(chǎng)景完全不同源的網(wǎng)站,需要窗口通信方案父子窗口互相寫互相監(jiān)聽子窗口寫后跳回同域父窗口讀瀏覽器跨文檔通信場(chǎng)景請(qǐng)求非同源地址方案架設(shè)服務(wù)器代理參考資料瀏覽器同源政策及其規(guī)避方法阮一峰前端常見跨域解決方案全跨域幾種方式 同源 概念:協(xié)議,域名,端口 相同。目的:保證用戶信息的安全,防止惡意的網(wǎng)站竊取數(shù)據(jù)。限制的行為: Cookie、LocalStorage 和 In...
閱讀 1959·2021-09-30 09:46
閱讀 1370·2019-08-30 15:43
閱讀 1129·2019-08-29 13:28
閱讀 1929·2019-08-29 11:24
閱讀 1687·2019-08-26 13:22
閱讀 3929·2019-08-26 12:01
閱讀 1824·2019-08-26 11:33
閱讀 3246·2019-08-23 15:34