摘要:調(diào)用函數(shù),判斷是否含有該指定樣式,若含有的話刪除該。分不同的情況來(lái)調(diào)用函數(shù),并返回對(duì)象。慕課網(wǎng)探索之基礎(chǔ)詳解篇慕課網(wǎng)事件探秘。參考資料事件代理委托事件代理實(shí)現(xiàn)如下事件代理需要進(jìn)行事件代理的父元素。
DOM 添加class、移除class、是否同級(jí)元素、獲取元素位置轉(zhuǎn)載自我的個(gè)人博客
歡迎大家批評(píng)指正
先來(lái)一些簡(jiǎn)單的,在你的util.js中完成以下任務(wù):
// 為element增加一個(gè)樣式名為newClassName的新樣式 function addClass(element, newClassName) { // your implement } // 移除element中的樣式oldClassName function removeClass(element, oldClassName) { // your implement } // 判斷siblingNode和element是否為同一個(gè)父元素下的同一級(jí)的元素,返回bool值 function isSiblingNode(element, siblingNode) { // your implement } // 獲取element相對(duì)于瀏覽器窗口的位置,返回一個(gè)對(duì)象{x, y} function getPosition(element) { // your implement } // your implement思路:
其實(shí)這里可以先定義一個(gè)hasClass函數(shù)。用來(lái)判斷該節(jié)點(diǎn)是否含有某個(gè)className。
addClass添加樣式。調(diào)用hasClass函數(shù),判斷element是否含有待添加的新className,若沒(méi)有則添加,否則什么都不做。
removeClass刪除樣式。調(diào)用hasClass函數(shù),判斷element是否含有該指定樣式,若含有的話刪除該className。沒(méi)有的話什么都不做。
判斷siblingNode和element是否為同一個(gè)父元素下的同一級(jí)的元素。這里直接判斷parentNode就可以了吧
獲取element相對(duì)于瀏覽器窗口的位置,返回一個(gè)對(duì)象{x, y}。
這個(gè)題應(yīng)該是這幾個(gè)中比較復(fù)雜的一個(gè)了。因?yàn)椴荒苤苯邮褂?b>offsetLeft/Top。offsetLeft/Top所獲取的是其相對(duì)父元素的相對(duì)位置。當(dāng)多層定位嵌套時(shí)想要獲取到當(dāng)前元素相對(duì)網(wǎng)頁(yè)的位置就會(huì)不對(duì)。
并且由于在表格和iframe中,offsetParent對(duì)象未必等于父容器,所以也不能直接利用該元素的parent來(lái)獲取位置,因?yàn)槠鋵?duì)于表格和iframe中的元素不適用。
通過(guò)查詢知道有一個(gè)Element.getBoundingClientRect()方法。它返回一個(gè)對(duì)象,其中包含了left、right、top、bottom四個(gè)屬性,分別對(duì)應(yīng)了該元素的左上角和右下角相對(duì)于瀏覽器窗口(viewport)左上角的距離。
但是用該方法獲取到的是元素的相對(duì)位置,在出現(xiàn)滾動(dòng)時(shí),距離會(huì)發(fā)生改變,要獲得絕對(duì)位置時(shí),還需要加上滾動(dòng)的距離。因?yàn)镕irefox或Chrome的不兼容問(wèn)題需要進(jìn)行兼容性處理,參考document.body.scrollTop or document.documentElement.scrollTop
最終根據(jù)兩個(gè)值,得到絕對(duì)位置。
//其實(shí)也簡(jiǎn)單,只需要獲取到兩個(gè)值,取其中的最大值即可。 var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft); var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);實(shí)現(xiàn):
//判斷element中是否含有className為sClass。 function hasClass(element, sClass) { return element.className.match(new RegExp("(s|^)" + sClass + "(s|$)")); } // 為element增加一個(gè)樣式名為newClassName的新樣式 function addClass(element, newClassName) { if (!hasClass(element, newClassName)) { element.className += " " + newClassName; } } // 移除element中的樣式oldClassName function removeClass(element, oldClassName) { if (hasClass(element, oldClassName)) { var reg = new RegExp("(s|^)" + oldClassName + "(s|$)"); element.className = element.className.replace(reg, ""); } } // 判斷siblingNode和element是否為同一個(gè)父元素下的同一級(jí)的元素,返回bool值 function isSiblingNode(element, siblingNode) { return element.parentNode === siblingNode.parentNode } // 獲取element相對(duì)于瀏覽器窗口的位置,返回一個(gè)對(duì)象{x, y} function getPosition(element) { var position = {}; position.x = element.getBoundingClientRect().left + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);//獲取相對(duì)位置+滾動(dòng)距離=絕對(duì)位置. position.y = element.getBoundingClientRect().top + Math.max(document.documentElement.scrollTop, document.body.scrollTop); return position; }
參考資料:(還沒(méi)看完)
阮一峰用Javascript獲取頁(yè)面元素的位置
博客園JavaScript獲取DOM元素位置和尺寸大小
博客園js中的各種寬高以及位置總結(jié)
挑戰(zhàn)mini $接下來(lái)挑戰(zhàn)一個(gè)mini $,它和之前的$是不兼容的,它應(yīng)該是document.querySelector的功能子集,在不直接使用document.querySelector的情況下,在你的util.js中完成以下任務(wù):
// 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Query function $(selector) { } // 可以通過(guò)id獲取DOM對(duì)象,通過(guò)#標(biāo)示,例如 $("#adom"); // 返回id為adom的DOM對(duì)象 // 可以通過(guò)tagName獲取DOM對(duì)象,例如 $("a"); // 返回第一個(gè)對(duì)象 // 可以通過(guò)樣式名稱獲取DOM對(duì)象,例如 $(".classa"); // 返回第一個(gè)樣式定義包含classa的對(duì)象 // 可以通過(guò)attribute匹配獲取DOM對(duì)象,例如 $("[data-log]"); // 返回第一個(gè)包含屬性data-log的對(duì)象 $("[data-time=2015]"); // 返回第一個(gè)包含屬性data-time且值為2015的對(duì)象 // 可以通過(guò)簡(jiǎn)單的組合提高查詢便利性,例如 $("#adom .classa"); // 返回id為adom的DOM所包含的所有子節(jié)點(diǎn)中,第一個(gè)樣式定義包含classa的對(duì)象
實(shí)現(xiàn)思路:
嗯,這個(gè)題思考了很久,網(wǎng)上找了很多資料但還是不怎么會(huì),還達(dá)不到想要的效果,有點(diǎn)鉆牛角尖了。盡量來(lái)寫(xiě)一下吧。(我果然是個(gè)弱雞)。感謝秒味課堂的免費(fèi)課程。
題目要求獲取到所有的節(jié)點(diǎn)中的第一個(gè),所以不需要用數(shù)組來(lái)儲(chǔ)存獲取到的節(jié)點(diǎn)。
額。。想了半天,還是使用函數(shù)包裝來(lái)實(shí)現(xiàn)后代選擇器比較好,所以VQuery函數(shù)返回是獲取到的完整節(jié)點(diǎn)對(duì)象數(shù)組,$函數(shù)用來(lái)達(dá)到題目要求。
所以在VQuery函數(shù)中就不需要考慮空格了,直接使用switch分支,來(lái)判定不同的情況。#、.、[、 [=]。
在$函數(shù)中,判斷字符串中是否含有空格,有空格的話需要分割成數(shù)組,數(shù)組的前一項(xiàng)是為父選擇符,后一項(xiàng)為子選擇符。分不同的情況來(lái)調(diào)用VQuery函數(shù),并返回對(duì)象。
/** * $函數(shù)的依賴函數(shù),選擇器函數(shù) * @param {string} selector CSS方式的選擇器 * @param {object} root 可選參數(shù),selector的父對(duì)象。不存在時(shí),為document * @returns {Array} 返回獲取到的節(jié)點(diǎn)數(shù)組,需要注意的是使用ID選擇器返的也是數(shù)組 */ function VQuery(selector, root) { //用來(lái)保存選擇的元素 var elements = []; //保存結(jié)果節(jié)點(diǎn)數(shù)組 var allChildren = null; //用來(lái)保存獲取到的臨時(shí)節(jié)點(diǎn)數(shù)組 root = root || document; //若沒(méi)有給root,賦值document switch (selector.charAt(0)) { case "#": //id選擇器 elements.push(root.getElementById(selector.substring(1))); break; case ".": //class選擇器 if (root.getElementsByClassName) { //標(biāo)準(zhǔn) elements = root.getElementsByClassName(selector.substring(1)); } else { //兼容低版本瀏覽器 var reg = new RegExp("" + selector.substring(1) + ""); allChildren = root.getElementsByTagName("*"); for (var i = 0, len = allChildren.length; i < len; i++) { if (reg.test(allChildren[i].className)) { elements.push(allChildren[i]); } } } break; case "[": //屬性選擇器 if (selector.indexOf("=") === -1) { //只有屬性沒(méi)有值的情況 allChildren = root.getElementsByTagName("*"); for (var i = 0, len = allChildren.length; i < len; i++) { if (allChildren[i].getAttribute(selector.slice(1, -1)) !== null) { elements.push(allChildren[i]); } } } else { //既有屬性又有值的情況 var index = selector.indexOf("="); //緩存=出現(xiàn)的索引位置。 allChildren = root.getElementsByTagName("*"); for (var i = 0, len = allChildren.length; i < len; i++) { if (allChildren[i].getAttribute(selector.slice(1, index)) === selector.slice(index + 1, -1)) { elements.push(allChildren[i]); } } } break; default: //tagName elements = root.getElementsByTagName(selector); } return elements } /** * 模仿jQuery的迷你$選擇符。 * @param {string} selector CSS方式的選擇器,支持簡(jiǎn)單的后代選擇器(只支持一級(jí)) * @returns {object} 返回獲取到的第一個(gè)節(jié)點(diǎn)對(duì)象,后代選擇器時(shí),返回第一個(gè)對(duì)象中的第一個(gè)符合條件的對(duì)象 */ function $(selector) { //這里trim處理輸入時(shí)兩端出現(xiàn)空格的情況,支持ie9+。但是這個(gè)函數(shù)實(shí)現(xiàn)起來(lái)也特別簡(jiǎn)單,可以參考我task0002(-)前面有trim函數(shù)的實(shí)現(xiàn)。稍微修改一下,這樣就沒(méi)兼容性問(wèn)題了。 if (selector == document) { return document; } selector = selector.trim(); //存在空格時(shí),使用后代選擇器 if (selector.indexOf(" ") !== -1) { var selectorArr = selector.split(/s+/); //分割成數(shù)組,第一項(xiàng)為parent,第二項(xiàng)為chlid。 //這里沒(méi)去考慮特別多的情況了,只是簡(jiǎn)單的把參數(shù)傳入。 return VQuery(selectorArr[1], VQuery(selectorArr[0])[0])[0]; } else { //普通情況,只返回獲取到的第一個(gè)對(duì)象 return VQuery(selector,document)[0]; } }事件 事件綁定、事件移除
我們來(lái)繼續(xù)用封裝自己的小jQuery庫(kù)來(lái)實(shí)現(xiàn)我們對(duì)于JavaScript事件的學(xué)習(xí),還是在你的util.js,實(shí)現(xiàn)以下函數(shù)
// 給一個(gè)element綁定一個(gè)針對(duì)event事件的響應(yīng),響應(yīng)函數(shù)為listener function addEvent(element, event, listener) { // your implement } // 例如: function clicklistener(event) { ... } addEvent($("#doma"), "click", a); // 移除element對(duì)象對(duì)于event事件發(fā)生時(shí)執(zhí)行l(wèi)istener的響應(yīng) function removeEvent(element, event, listener) { // your implement }
這里慕課網(wǎng)的視頻講的特別清楚,就不贅述了。
慕課網(wǎng) DOM探索之基礎(chǔ)詳解篇
慕課網(wǎng) DOM事件探秘。這一部分,主要看這個(gè)。
/** * 事件添加函數(shù) * @param {object} element 需要綁定事件的對(duì)象 * @param {string} event 事件類型 * @param {function} listener 事件觸發(fā)執(zhí)行的函數(shù) */ function addEvent(element, event, listener) { if (element.addEventListener) { //標(biāo)準(zhǔn) element.addEventListener(event, listener, false); } else if (element.attachEvent) { //低版本ie element.attachEvent("on" + event, listener); } else { //都不行的情況 element["on" + event] = listener; } } /** * 事件移除函數(shù) * @param {object} element 需要移除事件的對(duì)象 * @param {string} event 事件類型 * @param {function} listener 需要被移除事件函數(shù) */ function removeEvent(element, event, listener) { // your implement if (element.removeEventListener) { //標(biāo)準(zhǔn) element.removeEventListener(event, listener, false); } else if (element.detachEvent) { //低版本ie element.detachEvent("on" + event, listener); } else { //都不行的情況 element["on" + event] = null; } }click事件、Enter事件
利用上面寫(xiě)好的事件綁定函數(shù)就很簡(jiǎn)單了。
click事件,這個(gè)簡(jiǎn)單,直接函數(shù)封裝一層就行。
Enter事件,這里主要考察的鍵盤(pán)的事件的觸發(fā)。
keydown事件:在鍵盤(pán)按下時(shí)觸發(fā).
keyup事件:在按鍵釋放時(shí)觸發(fā),也就是你按下鍵盤(pán)起來(lái)后的事件
keypress事件:在敲擊按鍵時(shí)觸發(fā),我們可以理解為按下并抬起同一個(gè)按鍵
keyCode屬性:在鍵盤(pán)事件觸發(fā)時(shí),按下的鍵的值。值=13時(shí),為Enter鍵。(需進(jìn)行兼容處理)
// 實(shí)現(xiàn)對(duì)click事件的綁定 function addClickEvent(element, listener) { addEvent(element, "click", listener); } // 實(shí)現(xiàn)對(duì)于按Enter鍵時(shí)的事件綁定 function addEnterEvent(element, listener) { // your implement addEvent(element, "keydown", function (ev) { //兼容性處理。 var oEvent = ev || window.event; if (oEvent.keyCode === 13) { listener(); } }); }
接下來(lái)我們把上面幾個(gè)函數(shù)和$做一下結(jié)合,把他們變成$對(duì)象的一些方法
addEvent(element, event, listener) -> $.on(element, event, listener);
removeEvent(element, event, listener) -> $.un(element, event, listener);
addClickEvent(element, listener) -> $.click(element, listener);
addEnterEvent(element, listener) -> $.enter(element, listener);
//在js中萬(wàn)物皆對(duì)象(原諒我這么淺顯的說(shuō)),所以實(shí)現(xiàn)就特別簡(jiǎn)單了 $.on = function (element, type, listener) { return addEvent(element, type, listener); }; $.un = function (element, type, listener) { return removeEvent(element, type, listener); }; $.click = function (element, listener) { return addClickEvent(element, listener); } $.enter = function (element, listener) { $.enter addEnterEvent(element, listener); };事件代理
接下來(lái)考慮這樣一個(gè)場(chǎng)景,我們需要對(duì)一個(gè)列表里所有的增加點(diǎn)擊事件的監(jiān)聽(tīng)
我們通過(guò)自己寫(xiě)的函數(shù),取到id為list這個(gè)ul里面的所有l(wèi)i,然后通過(guò)遍歷給他們綁定事件。這樣我們就不需要一個(gè)一個(gè)去綁定了。但是看看以下代碼:
function renderList() { $("#list").innerHTML = "
我們?cè)黾恿艘粋€(gè)按鈕,當(dāng)點(diǎn)擊按鈕時(shí),改變list里面的項(xiàng)目,這個(gè)時(shí)候你再點(diǎn)擊一下li,綁定事件不再生效了。那是不是我們每次改變了DOM結(jié)構(gòu)或者內(nèi)容后,都需要重新綁定事件呢?當(dāng)然不會(huì)這么笨,接下來(lái)學(xué)習(xí)一下事件代理,然后實(shí)現(xiàn)下面新的方法:
// 先簡(jiǎn)單一些 function delegateEvent(element, tag, eventName, listener) { // your implement } $.delegate = delegateEvent; // 使用示例 // 還是上面那段HTML,實(shí)現(xiàn)對(duì)list這個(gè)ul里面所有l(wèi)i的click事件進(jìn)行響應(yīng) $.delegate($("#list"), "li", "click", clickHandle);實(shí)現(xiàn)思路:
寫(xiě)到這里,剛好前幾天CSS魔法寫(xiě)的《前端進(jìn)階之路:點(diǎn)擊事件綁定》有提到“事件代理/委托”,不過(guò)是直接使用jQuery來(lái)實(shí)現(xiàn)的。所以地址有興趣的自己搜索吧-_-。
“事件代理” 的本質(zhì)是利用了事件冒泡的特性。當(dāng)一個(gè)元素上的事件被觸發(fā)的時(shí)候,比如說(shuō)鼠標(biāo)點(diǎn)擊了一個(gè)按鈕,同樣的事件將會(huì)在那個(gè)元素的所有祖先元素中被觸發(fā)。這一過(guò)程被稱為事件冒泡;
這個(gè)事件從原始元素開(kāi)始一直冒泡到DOM樹(shù)的最上層。任何一個(gè)事件的目標(biāo)元素都是最開(kāi)始的那個(gè)元素,在我們的這個(gè)例子中也就是按鈕,并且它在我們的元素對(duì)象中以屬性的形式出現(xiàn)。使用事件代理,我們可以把事件處理器添加到一個(gè)元素上,等待一個(gè)事件從它的子級(jí)元素里冒泡上來(lái),并且可以得知這個(gè)事件是從哪個(gè)元素開(kāi)始的。
這里就不細(xì)說(shuō)事件冒泡與事件捕獲了(阻止默認(rèn)行為也會(huì)用到,有興趣去網(wǎng)上找找看),但是要理解事件代理就必須先知道它們。下面這張圖可以先看看。(圖片來(lái)自網(wǎng)絡(luò),侵刪)
理解了這個(gè)之后就沒(méi)那么難了,只需要進(jìn)行一點(diǎn)兼容性處理。
參考資料
javascript事件代理(委托)
JavaScript事件代理
實(shí)現(xiàn)如下:/** * 事件代理 * @param {HTMLElement} element 需要進(jìn)行事件代理的父元素。 * @param {string} tag 需要觸發(fā)事件的標(biāo)簽名 * @param {string} eventName 觸發(fā)的事件類型 * @param {function} listener 事件執(zhí)行的函數(shù) * @returns {[[Type]]} [[Description]] */ function delegateEvent(element, tag, eventName, listener) { // your implement return addEvent(element, eventName, function (ev) { var oEvent = ev || event; //兼容處理 var target = oEvent.target || oEvent.srcElement; //兼容處理 if (target.tagName.toLocaleLowerCase() === tag) { listener.call(target, oEvent); //使用call方法修改執(zhí)行函數(shù)中的this指向,現(xiàn)在this指向觸發(fā)了事件的HTML節(jié)點(diǎn)(可直接使用this.innerHTML返回該節(jié)點(diǎn)內(nèi)容) } }) } $.delegate = function (element, tag, eventName, listener) { return delegateEvent(element, tag, eventName, listener); };封裝改變
估計(jì)有同學(xué)已經(jīng)開(kāi)始吐槽了,函數(shù)里面一堆$看著暈啊,那么接下來(lái)把我們的事件函數(shù)做如下:(這里應(yīng)該是把前面的$.on、$.click、$.un、$.delegate都改寫(xiě)一下。比較簡(jiǎn)單,就拿一個(gè)出來(lái)作例子吧。)
//和上面的函數(shù)一樣,原來(lái)第一個(gè)參數(shù)是傳入獲取到的父HTMLElement對(duì)象,現(xiàn)在直接傳入選擇器名稱就行 $.delegate = function (selector, tag, event, listener) { //這里的`$(selector)`,是用的自己封裝的選擇器函數(shù),愿意的話可以換成標(biāo)準(zhǔn)支持的`document.querySelector()` return delegateEvent($(selector), tag, event, listener); }; // 使用示例: $.delegate("#list", "li", "click", liClicker);
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/91576.html
摘要:獲取下一個(gè)元素節(jié)點(diǎn),存在的話,取消現(xiàn)有選中狀態(tài),設(shè)置下一個(gè)元素節(jié)點(diǎn)為選擇中,調(diào)用運(yùn)動(dòng)框架實(shí)現(xiàn)動(dòng)畫(huà),添加定時(shí)器,調(diào)用該函數(shù),實(shí)現(xiàn)自動(dòng)播放。移出時(shí),開(kāi)啟定時(shí)器,繼續(xù)輪播。輪播間隔時(shí)間單位為毫秒,默認(rèn)為,在內(nèi)部,以下部分進(jìn)行修改或添加。 轉(zhuǎn)載自我的個(gè)人博客 歡迎大家批評(píng)指正 包括5部分: 小練習(xí)1-處理用戶輸入 小練習(xí)2-日期對(duì)象的使用 小練習(xí)3:輪播圖 小練習(xí)4:輸入提示框 小練習(xí)...
摘要:獲取下一個(gè)元素節(jié)點(diǎn),存在的話,取消現(xiàn)有選中狀態(tài),設(shè)置下一個(gè)元素節(jié)點(diǎn)為選擇中,調(diào)用運(yùn)動(dòng)框架實(shí)現(xiàn)動(dòng)畫(huà),添加定時(shí)器,調(diào)用該函數(shù),實(shí)現(xiàn)自動(dòng)播放。移出時(shí),開(kāi)啟定時(shí)器,繼續(xù)輪播。輪播間隔時(shí)間單位為毫秒,默認(rèn)為,在內(nèi)部,以下部分進(jìn)行修改或添加。 轉(zhuǎn)載自我的個(gè)人博客 歡迎大家批評(píng)指正 包括5部分: 小練習(xí)1-處理用戶輸入 小練習(xí)2-日期對(duì)象的使用 小練習(xí)3:輪播圖 小練習(xí)4:輸入提示框 小練習(xí)...
摘要:不過(guò)讓流行起來(lái)的原因應(yīng)該是是目前所有主流瀏覽器上唯一支持的腳本語(yǔ)言。經(jīng)過(guò)測(cè)試,數(shù)字字符串布爾日期可以直接賦值,修改不會(huì)產(chǎn)生影響。再考慮對(duì)象類型為或者的情況。對(duì)于結(jié)果聲明其類型。判斷對(duì)象的類型是還是,結(jié)果類型更改。 轉(zhuǎn)載自我的個(gè)人博客 歡迎大家批評(píng)指正 1. 第一個(gè)頁(yè)面交互 這里最需要學(xué)習(xí)的老師的代碼中,每一部分功能都由函數(shù)控制,沒(méi)有創(chuàng)建一個(gè)全部變量。且最后有一個(gè)函數(shù)來(lái)控制執(zhí)行代碼...
摘要:可以傳遞三個(gè)參數(shù)表示一個(gè)或多個(gè)事件類型,比如。表示綁定到指定元素的處理函數(shù)。我們稱它為簡(jiǎn)寫(xiě)事件。必須在中,并且使用作為事件觸發(fā)元素,不然無(wú)效。和表示鼠標(biāo)移入和移出的時(shí)候觸發(fā)。按下返回按下返回和分別表示光標(biāo)激活和丟失,事件觸發(fā)時(shí)機(jī)是當(dāng)前元素。 轉(zhuǎn)自個(gè)人博客 在JavaScript 有一個(gè)非常重要的功能,就是事件驅(qū)動(dòng)。如果你的網(wǎng)頁(yè)需要與用戶進(jìn)行交互的話,就不可能不用到事件。它在頁(yè)面完全加...
摘要:小練習(xí)輪播圖組件任務(wù)描述在和上一任務(wù)同一目錄下面創(chuàng)建一個(gè)文件,在目錄中創(chuàng)建,并在其中編碼,實(shí)現(xiàn)一個(gè)輪播圖的功能。實(shí)現(xiàn)思路考察對(duì)節(jié)點(diǎn),定時(shí)器,事件的處理。 小練習(xí)3:輪播圖組件 任務(wù)描述在和上一任務(wù)同一目錄下面創(chuàng)建一個(gè)task0002_3.html文件,在js目錄中創(chuàng)建task0002_3.js,并在其中編碼,實(shí)現(xiàn)一個(gè)輪播圖的功能。 圖片數(shù)量及URL均在HTML中寫(xiě)好 可以配置輪播的順...
閱讀 1780·2021-10-19 13:30
閱讀 1355·2021-10-14 09:48
閱讀 1546·2021-09-22 15:17
閱讀 2019·2019-08-30 15:52
閱讀 3286·2019-08-30 11:23
閱讀 2001·2019-08-29 15:27
閱讀 902·2019-08-29 13:55
閱讀 766·2019-08-26 14:05