摘要:級事件規(guī)定的事件流包括三個(gè)階段事件捕獲階段處于目標(biāo)階段和事件冒泡階段。對象只存在于事件處理程序執(zhí)行期間,一旦執(zhí)行完畢,立即被銷毀。焦點(diǎn)事件焦點(diǎn)事件會(huì)在頁面元素獲得或失去焦點(diǎn)時(shí)觸發(fā)。
JavaScript DOM 事件初探
原文鏈接
事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特定的交互瞬間,比如單擊、雙擊、鼠標(biāo)懸浮等。
事件流
事件流描述的是從頁面中接收事件的順序,或者說是事件在頁面中傳播的順序。
IE的事件流叫做事件冒泡(event bubbling):由最具體的元素開始執(zhí)行事件,然后逐級向上傳播到 window 對象。
網(wǎng)景團(tuán)隊(duì)提出的事件流叫做事件捕獲(event capturing):由最外層的 window 對象開始執(zhí)行事件,然后逐漸向下傳播到最具體的元素。
下面我們做個(gè)小實(shí)驗(yàn)來說明這兩種事件流的不同之處:
// html 文檔事件流 實(shí)驗(yàn) 點(diǎn)我點(diǎn)我,我是div
// 事件冒泡 var div = document.getElementById("test"); div.addEventListener("click",function(){ console.log("i am div"); }, false); document.body.addEventListener("click",function(){ console.log("i am body"); }, false); document.documentElement.addEventListener("click",function(){ console.log("i am html"); }, false); document.addEventListener("click",function(){ console.log("i am document"); }, false); window.addEventListener("click",function(){ console.log("i am window"); }, false);
點(diǎn)擊div,控制端會(huì)打印如下:
i am div
i am body
i am html
i am document
i am window
// 事件捕獲 var div = document.getElementById("test"); div.addEventListener("click",function(){ console.log("i am div"); }, true); document.body.addEventListener("click",function(){ console.log("i am body"); }, true); document.documentElement.addEventListener("click",function(){ console.log("i am html"); }, true); document.addEventListener("click",function(){ console.log("i am document"); }, true); window.addEventListener("click",function(){ console.log("i am window"); }, true);
圖片經(jīng)過二次處理,略丑,請見諒!
點(diǎn)擊div,控制端會(huì)打印如下:
i am window
i am document
i am html
i am body
i am div
可以看出,事件冒泡和事件捕獲是兩種完全相反的事件流。
平時(shí),一般都是在使用事件冒泡,只在特殊情況下使用事件捕獲。
DOM2級事件規(guī)定的事件流包括三個(gè)階段:事件捕獲階段、處于目標(biāo)階段和事件冒泡階段。
// 事件冒泡和事件捕獲混合一下 var div = document.getElementById("test"); div.addEventListener("click",function(){ console.log("i am div"); }, true); document.body.addEventListener("click",function(){ console.log("i am body"); }, false); // 改為在冒泡階段調(diào)用事件處理程序 document.documentElement.addEventListener("click",function(){ console.log("i am html"); }, true); document.addEventListener("click",function(){ console.log("i am document"); }, true); window.addEventListener("click",function(){ console.log("i am window"); }, false); // 改為在冒泡階段調(diào)用事件處理程序
這個(gè)圖片是直接從書上摘得,自己腦補(bǔ)一下,把 window 對象自行添上去吧!
事件處理程序
點(diǎn)擊div,控制端會(huì)打印如下:
i am document
i am html
i am div
i am body
i am window
事件處理程序:指的是響應(yīng)處理某個(gè)事件的函數(shù)
HTML 事件處理程序
某個(gè)元素支持的每種事件,都可以使用一個(gè)與相應(yīng)事件處理程序同名的 HTML 特性來指定。
// 情況一 // 情況二
建議永遠(yuǎn)不要使用這種方式為元素添加事件,因?yàn)檫@種方法有一個(gè)巨大的缺點(diǎn),就是使得 HTML 與 JavaScript 的代碼緊密耦合,不符合網(wǎng)頁設(shè)計(jì)的行為與結(jié)構(gòu)分離。
DOM0 級事件處理程序
每個(gè)元素(包括 window 和 document)都有自己的事件處理程序?qū)傩?/strong>,比如 onclick、onmouseup 等。
把上面的代碼改寫如下:
var button = document.getElementById("test"); button.onclick = function(){ // this 對象指向 button 元素 console.log(this); alert("I am button!"); }; /* 刪除指定的事件處理程序 */ button.onclick = null;
DOM2 級事件處理程序
DOM2 級事件 定義了兩個(gè)方法,用來處理指定和刪除事件處理程序的操作:addEventListener() 和 removeEventListener()。
這兩個(gè)方法都有三個(gè)參數(shù),第一個(gè)參數(shù)是事件名,第二個(gè)參數(shù)是作為事件處理程序的函數(shù),第三個(gè)參數(shù)是一個(gè)布爾值,默認(rèn)值是 false,表示在冒泡階段調(diào)用事件處理程序,如果這個(gè)值是 true,表示在捕獲階段調(diào)用事件處理程序。
繼續(xù)改寫上面的代碼:
var button = document.getElementById("test"); function show(){ // this 對象指向 button 元素 console.log(this); alert("I am button!"); } // 添加事件處理程序 button.addEventListener("click",show, false); button.addEventListener("click",function(){ alert("I am second alert!"); },false); // 刪除事件處理程序 button.removeEventListener("click",show, false); // 刪除成功 button.removeEventListener("click",function(){ // 刪除失敗 alert("I am second alert!"); },false);
使用 DOM2 級方法添加事件處理程序的主要好處是可以為一個(gè)元素添加多個(gè)事件處理程序。
如果 addEventListener() 添加的事件處理函數(shù)是匿名函數(shù),則無法通過 removeEventListener() 刪除這個(gè)事件處理程序。
IE 事件處理程序
IE8 以及更早的 IE 版本,只支持事件冒泡,不支持 addEventListener() 和 removeEventListener(),但是它實(shí)現(xiàn)了與這兩個(gè)方法類似的兩個(gè)方法:attachEvent() 和 detachEvent()。這兩個(gè)方法只有兩個(gè)參數(shù),一個(gè)事件名稱(是 onclick,不是 click),一個(gè)事件處理函數(shù)。
與 addEventListener() 不同,使用attachEvent() 方法的情況下,事件處理函數(shù)會(huì)在全局作用域下運(yùn)行,所以 this 等于 window,這一點(diǎn)需要特別注意。
var button = document.getElementById("test"); button.attachEvent("onclick", function(){ // this 對象指向了全局作用域,即 window console.log(this); alert("I am button!"); }); button.attachEvent("onclick",function(){ alert("I am second alert!"); }); // 上面也是為同一個(gè)按鈕綁定了兩個(gè)事件處理程序 button.detachEvent("onclick",function(){ // 刪除失敗 alert("I am second alert!"); });
除非你想使你的程序兼容至 IE8- 瀏覽器,否則不要使用這兩個(gè)函數(shù)。
瀏覽器默認(rèn)行為對于一些特定的事件,瀏覽器有它默認(rèn)的行為。比如:點(diǎn)擊鏈接會(huì)進(jìn)行跳轉(zhuǎn)到指定的頁面、點(diǎn)擊鼠標(biāo)右鍵會(huì)呼出瀏覽器右鍵菜單、填寫表單時(shí)按回車會(huì)自動(dòng)提交到服務(wù)器等。
默認(rèn)的瀏覽器行為和冒泡行為是獨(dú)立的,取消事件默認(rèn)行為是不會(huì)取消事件冒泡的,反之亦然。同一個(gè)元素的多個(gè)事件處理函數(shù)也是相互獨(dú)立的。
var link = document.getElementById("test"); // 方法一 event.preventDefault() link.onclick = function(event){ console.log("You click!"); event.preventDefault(); }; // 方法二 return false link.onclick = function(event){ console.log("You click!"); return false; };
事件對象 event參考:事件-4. 瀏覽器默認(rèn)行為-宇卿
在觸發(fā) DOM 上的某個(gè)事件時(shí),會(huì)產(chǎn)生一個(gè)事件對象 event,這個(gè)對象中包含著所有與該事件有關(guān)的信息。
event 對象只存在于事件處理程序執(zhí)行期間,一旦執(zhí)行完畢,立即被銷毀。
/* 下列 event 對象的屬性和方法都是只讀的 */ var link = document.getElementById("test"); link.onclick = function(event){ // 判斷當(dāng)前事件是否會(huì)向 DOM 樹上層元素冒泡 console.log(event.bubbles); // 判斷是否可以取消事件的默認(rèn)行為 console.log(event.cancelable); // 使用該方法可以取消事件的默認(rèn)行為(使用前提是 cancelable 屬性的值為 true) event.preventDefault(); // 判斷是否已經(jīng)調(diào)用了 preventDefault() 方法(DOM3級事件新增) console.log(event.defaultPrevented); // 指向事件遍歷 DOM 時(shí),識別事件的當(dāng)前目標(biāo)對象 console.log(event.currentTarget); // 指向觸發(fā)事件的對象 console.log(event.target); // 表示事件流當(dāng)前處于哪一個(gè)階段 // 值為 1 表示在捕獲階段,值為 2 表示處于目標(biāo)階段,值為 3 表示在冒泡階段 console.log(event.eventPhase); // 返回一個(gè)字符串, 表示該事件對象的事件類型 console.log(event.type); // 立即停止當(dāng)前事件在 DOM 層次中的傳播,即取消進(jìn)一步的事件捕獲或冒泡 event.stopPropagation(); };
為了進(jìn)一步說明 event.stopPropagation() 的運(yùn)行效果,借用前面的代碼,更改如下:
// 事件冒泡和事件捕獲混合一下 var div = document.getElementById("test"); div.addEventListener("click",function(){ console.log("i am div"); }, true); document.body.addEventListener("click",function(){ console.log("i am body"); }, false); // 改為在冒泡階段調(diào)用事件處理程序 document.documentElement.addEventListener("click",function(){ console.log("i am html"); event.stopPropagation(); // 立即停止事件在 DOM 中的傳播 }, true); document.addEventListener("click",function(){ console.log("i am document"); }, true); window.addEventListener("click",function(){ console.log("i am window"); }, false); // 改為在冒泡階段調(diào)用事件處理程序
點(diǎn)擊div,控制端會(huì)打印如下:
i am document
i am html
看到了吧,后面元素的事件就不會(huì)被激發(fā)了。
事件類型 UI 事件UI 事件指的是簡單的用戶界面事件
load 事件:當(dāng)頁面所有資源(比如圖像、css文件、js文件等資源)完全加載完畢后,就會(huì)觸發(fā) window 上面的 load 事件。
當(dāng)然,我們也可以多帶帶為某個(gè)元素設(shè)置 load 事件,比如為一個(gè)圖片綁定這個(gè)事件,就可以檢測這個(gè)圖片是否加載完畢了。
var img = document.getElementById("myImg"); img.onload = function(){ alert("Image loaded!"); };
scroll 事件:在文檔被滾動(dòng)期間,重復(fù)觸發(fā)該事件。
window.onscroll = function(){ console.log("Scroll!"); };焦點(diǎn)事件
焦點(diǎn)事件會(huì)在頁面元素獲得或失去焦點(diǎn)時(shí)觸發(fā)。
注意:默認(rèn)情況下,只有部分 html 元素能獲得鼠標(biāo)焦點(diǎn)(如 input,a),很大一部分 html 元素是不能獲得鼠標(biāo)焦點(diǎn)的(如 div,img),這些能夠獲得鼠標(biāo)焦點(diǎn)的元素就是 focusable 元素。
不過,可以通過為這些默認(rèn)沒有焦點(diǎn)事件的元素添加一個(gè) tabindex 屬性,從而使它可以支持焦點(diǎn)事件。
document.activeElement:返回當(dāng)前頁面中獲得焦點(diǎn)的元素,如果沒有某個(gè)元素獲得焦點(diǎn),則該屬性的值為當(dāng)前頁面中的
元素document.hasFocus():判斷當(dāng)前文檔或者當(dāng)前文檔的子節(jié)點(diǎn)是否獲得了焦點(diǎn)
HTMLElement.focus():使得指定的元素獲得焦點(diǎn)(前提是這個(gè)元素是一個(gè)可以獲得焦點(diǎn)的元素)
HTMLElement.blur():移除當(dāng)前元素獲得的焦點(diǎn)
上面是一些 HTML5 中添加的焦點(diǎn)管理 API。下面說焦點(diǎn)事件:
focus 事件:在元素獲得焦點(diǎn)時(shí)觸發(fā),這個(gè)事件不會(huì)冒泡
blur 事件:在元素失去焦點(diǎn)時(shí)觸發(fā),這個(gè)事件不會(huì)冒泡
focusin 事件:在元素獲得焦點(diǎn)時(shí)觸發(fā),與 focus 事件等價(jià),但會(huì)冒泡
focusout 事件:在元素失去焦點(diǎn)時(shí)觸發(fā),與 blur 事件等價(jià),但會(huì)冒泡
var img = document.getElementById("img"); document.body.onscroll = function() { img.blur(); }; img.onfocus = function() { console.log("Img focused!"); }; img.onblur = function() { console.log("Img lose focus!"); }; img.onclick = function() { console.log(document.activeElement); console.log(document.hasFocus()); };
注意: focusin 和 focusout 事件,所有的 Firefox 版本都不支持,看這里。chrome 和 safari 中只有通過 addEventListener 方式綁定這兩個(gè)事件才能正常使用,其他方式綁定都不行。
鼠標(biāo)與滾輪事件說說focus /focusin /focusout /blur 事件(推薦)
(WHATWG)Focus management APIs
DOM3 級事件中定義了9個(gè)鼠標(biāo)事件。
// css div { width: 300px; height: 300px; margin: 50px auto; border: 1px solid #aaa; }
mouseover 事件:鼠標(biāo)指針首次進(jìn)入一個(gè)元素邊界之內(nèi)時(shí)觸發(fā),會(huì)冒泡
mouseout 事件:鼠標(biāo)指針移出這個(gè)元素邊界時(shí)觸發(fā),會(huì)冒泡
var test = document.getElementById("test"); test.onmouseover = function(event){ event.target.style.border = "3px solid #666"; }; test.onmouseout = function(event){ event.target.style.border = "none"; };
mouseenter 事件:鼠標(biāo)指針首次移動(dòng)到元素范圍之內(nèi)時(shí)觸發(fā),不冒泡
mouseleave 事件:鼠標(biāo)指針移動(dòng)到元素范圍之外時(shí)觸發(fā),不冒泡
var test = document.getElementById("test"); test.onmouseenter = function(event){ event.target.style.border = "10px solid #666"; }; test.onmouseleave = function(event){ event.target.style.border = "none"; };
mousemove 事件:當(dāng)鼠標(biāo)在元素內(nèi)部移動(dòng)時(shí)重復(fù)觸發(fā),會(huì)冒泡
// 這里寫一個(gè)鼠標(biāo)在 body 內(nèi)移動(dòng)時(shí),背景顏色隨機(jī)變化的腳本 document.body.onmousemove = function(){ var r = Math.floor(Math.random() * 256) g = Math.floor(Math.random() * 256) b = Math.floor(Math.random() * 256); document.body.style.background = "rgb("+r+","+g+","+b+")"; };
mousedown 事件:用戶通過按下任意鼠標(biāo)按鈕時(shí)觸發(fā)
mouseup 事件:用戶釋放鼠標(biāo)按鈕時(shí)觸發(fā)
click 事件:用戶單擊鼠標(biāo)左鍵時(shí)或按下回車鍵時(shí)觸發(fā)
dblclick 事件:用戶雙擊鼠標(biāo)左鍵時(shí)觸發(fā)
var body = document.body; body.onmousedown = function(){ console.log("Mouse down!"); }; body.onmouseup = function(){ console.log("Mouse up!"); }; body.onclick = function(){ console.log("One click!"); }; body.ondblclick = function(){ console.log("Double click!"); };
// 雙擊 body,控制端打印: Mouse down! Mouse up! One click! Mouse down! Mouse up! One click! Double click!
只有在同一個(gè)元素上相繼觸發(fā) mousedown 和 mouseup 事件,才會(huì)觸發(fā) click 事件,缺一不可。類似地,只有連續(xù)觸發(fā)兩次 click 事件,才會(huì)觸發(fā) dblclick 事件。
獲取點(diǎn)擊坐標(biāo)
clientX 和 clientY:鼠標(biāo)指針在視口中的坐標(biāo)
pageX 和 pageY:鼠標(biāo)指針在頁面中的坐標(biāo)
screenX 和 screenY:鼠標(biāo)指針在屏幕中的坐標(biāo)
在頁面沒有滾動(dòng)的情況下,pageX 和 pageY 的值與 clientX 和 clientY 的值相等。
document.body.onclick = function() { console.log("Client: " + "(" + event.clientX + "," + event.clientY + ")"); console.log("Page: " + "(" + event.pageX + "," + event.pageY + ")"); console.log("Screen: " + "(" + event.screenX + "," + event.screenY + ")"); };鍵盤與文本事件
keydown 事件:當(dāng)用戶按下任意鍵時(shí)觸發(fā),而且如果按住不放的話,會(huì)重復(fù)觸發(fā)此事件
keypress 事件:當(dāng)用戶按下任意字符鍵時(shí)觸發(fā),而且如果按住不放的話,會(huì)重復(fù)觸發(fā)此事件
keyup 事件:當(dāng)用戶釋放鍵盤上的按鍵時(shí)觸發(fā)
在用戶按下一個(gè)字符鍵并且立馬釋放這個(gè)按鍵的過程中,先觸發(fā) keydown 事件,再觸發(fā) keypress 事件,最后觸發(fā) keyup 事件。
window.onkeydown = function() { console.log("on key down"); }; window.onkeyup = function() { if (event.keyCode === 65) { console.log(event.key); } console.log("one key up"); }; window.onkeypress = function() { console.log("one key press"); };
為了知道自己按下的是哪個(gè)按鍵,可以使用 event.which 來獲得你按下按鍵的鍵碼(比如字母 A 的鍵碼為 65)。也可以通過鍵碼屬性(event.keyCode)來對特定的按鍵來進(jìn)行響應(yīng)。鍵碼參考表
發(fā)生 keypress 事件時(shí),會(huì)存在一個(gè) charCode 屬性,返回這個(gè)按鍵代表字符的 ASCII 編碼。ASCII table
event.which 返回一個(gè) keyCode 或 charCode 值,詳情看下面代碼
String.fromCharCode() 靜態(tài)方法可以將 event.which 轉(zhuǎn)化為相應(yīng)的字符。
// 請自行粘貼復(fù)制于瀏覽器控制端測試 // 分別輸入 a 和 A // A和a 的 ASCII碼分別為65,97 window.onkeydown = function(){ if(event.keyCode === 65){ console.log("(keydown keyCode)You press "a" or "A"!"); } if(event.charCode === 65){ console.log("(keydown charCode)You press "A"!"); } console.log("keydown event.which = " + event.which); console.log("(keydown:)" + String.fromCharCode(event.which)); }; window.onkeypress = function(){ if(event.keyCode === 65){ console.log("(keypress keyCode)You press "A"!"); } if(event.charCode === 65){ console.log("(keypress charCode)You press "A",not "a"!"); } console.log("keypress event.which = " + event.which); console.log("(keypress:)" + String.fromCharCode(event.which)); };
變動(dòng)事件在 DOM3 級事件中,做了一些變化,不再推薦使用 keyCode、charCode、which 屬性,而是出現(xiàn)了兩個(gè)新屬性:key 和 char,用來替代 keyCode 和 charCode 屬性。
但是不建議使用 key、char 屬性,因?yàn)橛幸徊糠譃g覽器對他支持的不是很好。點(diǎn)這里
參考:JavaScript 事件——“事件類型”中“鍵盤與文本事件”的注意要點(diǎn)
變動(dòng)事件是在 DOM 結(jié)構(gòu)發(fā)生變化時(shí)觸發(fā)
在 DOM2 中定義了多個(gè)變動(dòng)事件,但是在 DOM3 中又廢除了一些,在這里先簡單提一下有這個(gè)東西,以后用到再作補(bǔ)充。
HTML5 事件contextmenu 事件:單擊鼠標(biāo)右鍵,會(huì)觸發(fā)這個(gè)事件并調(diào)出頁面的上下文菜單。這個(gè)事件是鼠標(biāo)事件的一種,并且支持冒泡。
See the Pen context menu test by percy (@percy507) on CodePen.
在上面的例子中,我們演示了利用 contextmenu 事件來設(shè)置自定義右鍵菜單,以及屏蔽右鍵菜單。
然而,屏蔽右鍵菜單卻難不倒高手,Greasy Fork 上面有一個(gè)腳本(網(wǎng)頁限制解除),專門來打破對右鍵菜單有限制的頁面。
beforeunload 事件:當(dāng)瀏覽器窗口,文檔或其資源將要卸載時(shí)或者刷新頁面時(shí),會(huì)觸發(fā)這個(gè)事件【MDN】
下面有幾點(diǎn)需要注意一下:
1. 如果處理函數(shù)為 Event 對象的 returnValue 屬性賦值非空字符串,瀏覽器會(huì)彈出一個(gè)對話框,來詢問用戶是否確定要離開當(dāng)前頁面。沒有賦值時(shí),該事件不做任何響應(yīng)。
2. 從2011年5月25號開始,HTML5規(guī)范指出在此事件處理函數(shù)中,對于window.alert(), window.confirm(), 和 window.prompt() 的調(diào)用會(huì)被忽略。
3. 舊版本的瀏覽器可能會(huì)在提示框里顯示返回的信息,但是新版本瀏覽器都默認(rèn)采用瀏覽器內(nèi)設(shè)的提示信息。
// 復(fù)制粘貼于瀏覽器控制端,然后關(guān)閉頁面,會(huì)出現(xiàn)提示框 window.addEventListener("beforeunload", function() { var message = "你真的要離開嗎?"; event.returnValue = message; return message; }, false);
DOMContentLoaded 事件:在頁面文檔形成完整的 DOM 樹時(shí)觸發(fā),不理會(huì)圖像、js文件、css文件等資源是否加載完畢
這個(gè)事件可以為 document 或 window 綁定,但實(shí)際目標(biāo)是 document。這個(gè)事件會(huì)冒泡。
注意:這個(gè)事件與 load 事件是不一樣的,正常情況下,會(huì)早于 load 事件被觸發(fā)。
See the Pen DOMContentLoaded & load by percy (@percy507) on CodePen.
感覺篇幅太長了,事件委托、移動(dòng)設(shè)備中的事件、事件對內(nèi)存性能的影響等內(nèi)容將在以后逐漸寫出。
參考資料【書】《JavaScript 高級程序設(shè)計(jì)(第三版)》
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/80469.html
摘要:以我自己的理解,函數(shù)式編程就是以函數(shù)為中心,將大段過程拆成一個(gè)個(gè)函數(shù),組合嵌套使用。越來越多的跡象表明,函數(shù)式編程已經(jīng)不再是學(xué)術(shù)界的最愛,開始大踏步地在業(yè)界投入實(shí)用。也許繼面向?qū)ο缶幊讨?,函?shù)式編程會(huì)成為下一個(gè)編程的主流范式。 使用React也滿一年了,從剛剛會(huì)使用到逐漸探究其底層實(shí)現(xiàn),以便學(xué)習(xí)幾招奇技淫巧從而在自己的代碼中使用,寫出高效的代碼。下面整理一些知識點(diǎn),算是React看書...
摘要:當(dāng)發(fā)出一個(gè)請求的時(shí)候,如果這個(gè)請求需要等待,那就會(huì)被放入隊(duì)列中,如果有別的請求發(fā)出,并且無需等待則立刻做出處理,之后,再調(diào)用該請求的回調(diào)。差異相對于瀏覽器而言是沒有對象的也沒有瀏覽器安全級別的限制也不具備只能運(yùn)行 node初體驗(yàn) 1、node環(huán)境 node 是一個(gè)服務(wù)端JavaScript解析器,node中this指向global,而在瀏覽器中this指向window 所以unde...
摘要:誕生之初,是單線程的。當(dāng)接收到服務(wù)端的響應(yīng)之后,便通過回調(diào)函數(shù)執(zhí)行之后的操作。沖鋒基于事件驅(qū)動(dòng)。擁有攔截請求消息推送靜默更新地理圍欄等服務(wù)??刂茣r(shí)處于兩種狀態(tài)之一終止以節(jié)省內(nèi)存監(jiān)聽獲取和消息事件。支持的所有事件五銷毀瀏覽器決定是否銷毀。 這次體驗(yàn)一種新的博客風(fēng)格,我們長話短說,針針見血。 showImg(https://segmentfault.com/img/remote/14600...
閱讀 1858·2021-09-22 15:45
閱讀 1639·2019-08-30 15:55
閱讀 1829·2019-08-29 11:16
閱讀 3302·2019-08-26 11:44
閱讀 702·2019-08-23 17:58
閱讀 2698·2019-08-23 12:25
閱讀 1624·2019-08-22 17:15
閱讀 3597·2019-08-22 16:09