原生DOM兼容特性
瀏覽器主要也就是IE有點獨特,所以把IE重點區分開
名稱 | 主流 | IE | |
---|---|---|---|
內文本 | innerText | textContent | |
請求對象 | XMLHttpRequest | ActiveXObject ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"] |
|
監聽事件添加 | addEventListener(DOM2), ["on"+eventName](DOM0) |
attachEvent | |
監聽事件移除 | removeEventListener(DOM2), ["on"+eventName]=null(DOM0) |
detachEvent | |
事件對象 | function(e) e | window.event(IE7之前) | |
阻止默認事件 | preventDefault | e.returnValue=false | |
阻止冒泡 | stopPropagation | e.cancelBubble=true | |
鍵盤事件鍵盤編碼 | e.charCode | e.keyCode | |
獲取剪貼板的文本 | e.clipboardData | window.clipboardData | |
設置剪貼板文本 | e.clipboardData.setData("text/plain",value); | window.clipboardData.setData("text",value); | |
觸發事件的元素 | e.target | e.srcElement | |
獲取樣式 | getComputedStyle(obj,false)[attr];(Firefox瀏覽器) obj.style.attr(只對filter,opacity等有效) obj.style[attr] |
obj.currentStyle[attr]; | |
窗口左邊的位置 | window.screenLeft | window.screenX | |
頁面視口大小 | window.innerHeight | if(document.compatMode=="CSS1Compat")window.documentElement.clientHeight; if(document.compatMode=="BackCompat")window.body.clientHeight |
|
獲取元素 | document.getElementById(id); | document.all[id];(IE5) | |
返回指定的屬性 | ele.getAttribute(attr) | ele.attribute[attr] | |
ele是否存在指定屬性 attr | ele.hasAttribute(attr) | ele.attributes[attr].specified; | |
鼠標滾動,正數表示向上滾動 | function getWheelDelta(e){ if(e.wheelData){ return (client.engine.opera&&client.engine.opera<9.5)? -e.wheelData:e.wheelData; }else { return -e.detail*40;//firefox } } |
||
提取選中的文本 | textbox.value.subString(textbox.selectionStart,textbox.selectionEnd); | document.selection.createRange().text; (IE8之前沒有selectionStart,selectionEnd屬性 |
|
設置文本選中 | textbox.setSelectionRange(startIndex,stopIndex); | var range=textbox.createTextRange(); range.collapse(true); range.moveStart("character",0); range.moveEnd("character",stopIndex-startIndex); range.select() |
下面是積累下來的一些兼容函數,可以當做模板用
添加多個onload事件
處理ActiveXObject/XMLHttpRequest問題
請求對象的屬性和方法設置
發送表單數據
跨瀏覽器的CORS
跨瀏覽器事件處理程序
處理target/srcelemnt問題,代替this
實現insertAfter
給element加上類名
判斷是不是數組
IE10之前不支持docunment.getElementByClassName
獲取css樣式
手寫動畫
取得窗口左邊和上邊的位置
取得頁面視口大小
檢測插件方法
獲取元素
檢查對象的某個特性是否存在
對象轉換成數組
返回指定的屬性
ele是否存在指定屬性
ele是否符合選擇器selector
獲取內文本
獲取鼠標事件的父元素
探測按的是鼠標的哪個鍵
鼠標滾動事件
提取選中的文本
設置文本選中
bind方法對老版本的瀏覽器不起作用
包裝cookie
包裝子cookie
indexedDB
手寫typeof
深度克隆
組合使用構造函數模式和原型模式創建對象
組合繼承
觀察者模式
分享一個題目
添加多個onload事件function addLoadEvent(func){ var oldonload=window.onload; if(typeof window.onload!= "function"){ window.onload=func; } else{ window.onload=function(){ oldonload(); func(); } } }處理ActiveXObject/XMLHttpRequest問題
//第一種寫法,《js高級程序設計》的寫法 惰性載入技巧 function createXHR(){ if(typeof XMLHttpRequest!="undefined"){//XMLHttpRequest createXHR=function(){ return new XMLHttpRequest(); }; }else if(typeof ActiveXObject!="undefined"){//IE ActiveXObject createXHR=function(){ if(typeof arguments.callee.activeXString!="string"){ var versions=["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],//IE i,len; for(i=0,len=versions.length;i請求對象的屬性和方法設置 var xhr=createXHR(); xhr.onreadystatechange=function(){//firfox引入onlaod,readyState==4時觸發,代替onreadystatechange if(xhr.readyState==4){ try{ if((xhr.status>=200&&xhr.status<300)||xhr.status==304){ alert(xhr.responseText); }else { alert("unsuccessful"); } }catch(ex){} } } xhr.onload=function(){ if((xhr.status>=200&&xhr.status<300)||xhr.status==304){ alert(xhr.responseText); }else { alert("unsuccessful"); } } xhr.onprogress=function(event){ if(event.lengthComputable){//進度信息是否可用 console.log("Received"+event.position+"of"+event.totalSize); } } xhr.onerror=function(){ alert("error"); } xhr.timeout=1000; xhr.ontimeout=function(){ alert("timeout"); } xhr.open("get","example.php",true); xhr.overrideMimeType("text/xml"); xhr.send(null);//GET發送表單數據var form=document.getElementById("info"); xhr.send(serialize(form));//第一種寫法 xhr.send(new FormData(form));//第二種寫法跨瀏覽器的CORSfunction createCORSRequest(method,url){ var xhr=new XMLHttpRequest(); if("withCredentials" in xhr){ xhr.open(method,url,true); }else if(typeof XDomainRequest !="undefined"){ xhr=new XDomainRequest(); xhr.open(method,url); }else { xhr=null; } return xhr; } var request=createCORSRequest("get","http://www.somewhere"); if(request){ request.onload=function(){}; request.send(); }跨瀏覽器事件處理程序var eventUtil={ // 頁面加載完成后 readyEvent : function(fn) { if (fn==null) { fn=document; } var oldonload = window.onload; if (typeof window.onload != "function") { window.onload = fn; } else { window.onload = function() { oldonload(); fn(); }; } }, addEventHandler: function (obj, eventName, handler) { if (document.attachEvent) {//IE obj.attachEvent("on" + eventName, handler); } else if (document.addEventListener) {//DOM2級 obj.addEventListener(eventName, handler, false);//false- 默認。事件句柄在冒泡階段執行 } else{//DOM0級 obj["on"+eventName]=handler; } }, removeEventHandler:function(obj, eventName, handler){ if (document.attachEvent) {//IE obj.detachEvent("on" + eventName, handler); } else if (document.addEventListener) {//DOM2級 obj.removeEventListener(eventName, handler, false); } else{//DOM0級 obj["on"+eventName]=null; } }, //獲取event對象的引用,取到事件的所有信息,確保隨時能使用event; getEvent: function (e) { var ev = e || window.event; if (!ev) { var c = this.getEvent.caller; while (c) { ev = c.arguments[0]; if (ev && Event == ev.constructor) { break; } c = c.caller; } } return ev; }, //事件類型 getType: function (e) { return e.type; }, //調用事件的元素 getElement: function (e) { return e.target|| e.srcElement; }, //阻止默認事件 preventDefault: function (e) { e= this.getEvent(e); if(e.preventDefault){ e.preventDefault(); } else { return e.returnValue=false;//IE } }, //阻止冒泡 stopPropagation:function(e) { if(e.stopPropagation){ e.stopPropagation(); } else { e.cancelBubble=true;//IE } }, //鍵盤事件鍵盤的編號 getCharCode:function (e){ if(typeof e.charCode=="number")return e.charCode; else return e.keyCode; }, //獲取剪貼板的文本 getClipbordText:function(e){ var clipboardData=(e.clipboardData||window.clipboardData); return clipboardData.getData("text"); }, //設置剪貼板文本 setClipboardText:function(e,value){ if(e.clipboardData){ return e.clipboardData.setData("text/plain",value); }else if(window.clipboardData){ return window.clipboardData.setData("text",value); } }, }處理target/srcelemnt問題,代替thisfunction getActivatedObject(e) { var obj; if (!e) { // early version of IE obj = window.event.srcElement; } else if (e.srcElement) { // IE 7 or later obj = e.srcElement; } else { // DOM Level 2 browser obj = e.target; } return obj; }實現insertAfter/** * 把newElement插在targetElement后面 ,js的API只有insertBefore,沒有insertAfter */ function insertAfter(newElement,targetElement) { var parent = targetElement.parentNode; if (parent.lastChild == targetElement) { parent.appendChild(newElement); } else { parent.insertBefore(newElement,targetElement.nextSibling); } }給element加上類名function addClass(element,value) { if (!element.className) { element.className = value; } else { newClassName = element.className; newClassName+= " "; newClassName+= value; element.className = newClassName; } }判斷是不是數組function isArray(arg) { //return Object.prototype.toString.call(arr)=="[Object Array]";這種方法也可以 if (typeof arg == "object") { //所有數組都有一個包含單詞"arry"的constructor,最后的i表示不區分大小寫 var criteria = arg.constructor.toString().match(/array/i); return (criteria != null); } return false; }IE10之前不支持docunment.getElementByClassNamefunction getByClass(clsName,parent){ if(docunment.getElementByClassName) return docunment.getElementByClassName(clsName); //IE10之前 var oParent=parent?document.getElementById(parent):document, eles=[], elements=oParent.getElementsByTagName("*"); for(var i=0,l=elements.length;i獲取css樣式 function getStyle(obj,attr){ if(obj.currentStyle) {//IE 瀏覽器 return obj.currentStyle[attr]; }else{//Firefox瀏覽器 return getComputedStyle(obj,false)[attr]; } }手寫動畫//動畫 startMove(oLi,{width:400,height:200,opacity:100}) function startMove(obj,json,fn){ clearInterval(obj.timer); obj.timer=setInterval(function () { for(var attr in json){ var cur=0; if(attr=="opacity"){ cur=Math.round(parseFloat(getStyle(obj,attr))*100); } else { cur=parseInt(getStyle(obj,attr)); } var speed=(json[attr]-cur)/8; speed=speed>0?Math.ceil(speed):Math.floor(speed); var flag=true; if(cur!=json[attr]){//使得所有屬性做完運動才結束 flag=false; } if(attr=="opacity"){ obj.style.filter="alpha(opacity:"+(cur+speec)+")"; obj.style.opacity=(cur+speed)/100; } else{ obj.style[attr]=(cur+speed)+"px"; } } if(flag){ clearInterval(obj.timer); if(fn){ fn(); } } }) }取得窗口左邊和上邊的位置var leftPos=(typeof window.screenLeft =="number")?window.screenLeft:window.screenX;取得頁面視口大小var pageWidth=window.innerWidth, pageHeight=window.innerHeight; if(typeof pageHeight!="number"){ if(document.compatMode=="CSS1Compat"){//標準模式 pageHeight=window.documentElement.clientHeight; pageWidth=window.documentElement.clientWidth; } else {//BackCompat pageHeight=window.body.clientHeight; pageWidth=window.body.clientWidth; } }檢測插件方法/** * * 檢測插件方法一,IE下無效 */ function hasPlugin(name){ name=name.toLowerCase(); for(var i=0;i獲取元素 function getElement(id){ if(document.getElementById){ return document.getElementById(id); }else if(document.all){//IE5前 return document.all[id]; }else { throw new Error("no way to retrieve element!"); } }檢查對象的某個特性是否存在function isHostMethod(object,property){ var t =typeof object[property]; return t=="function"|| (!!(t=="object")&&object[property])|| t=="unknown";//不懂 }對象轉換成數組function convertToArray(nodes){ var array=null; try{ array=Array.propotype.slice.call(nodes,0);//IE8前無效 }catch(ex){ for(var i=0,len=nodes.length;i返回指定的屬性 /** * * 返回指定的屬性 IE ele.attribute[] * Element.getAttribute() */ function outputAttribute(ele){ var pairs=new Array(), attrname,attrvalue,u,len; for(i=0,len=ele.attribute.length;iele是否存在指定屬性 /** * * ele是否存在指定屬性 attr */ function hasattribute(ele,attr){ if(ele.hasAttribute){ return ele.hasAttribute(attr); }else {//IE return ele.attributes[attr].specified; } }ele是否符合選擇器selector/** * ele是否符合選擇器selector */ function matchesSelector(ele,selector){ if(ele.matchesSelector){ return ele.matchesSelector(selector); }else if(ele.msmatchesSelector){ return ele.msmatchesSelector(selector); }else if(ele.mozmatchesSelector){ return ele.mozmatchesSelector(selector); }else if(ele.webkitmatchesSelector){ return ele.webkitmatchesSelector(selector); }else{ throw new Error("not support"); } }獲取內文本//innerText/textContent function getInnerText(ele){ return (typeof ele.innerText=="string")? ele.innerText:ele.textContent; }獲取鼠標事件的父元素function getRelatedTarget(e){ if(e.relatedTarget) return e.relatedTarget; else if(e.fromElement) return e.fromElement;//mouseover else if(e.toElement) return e.toElement;//mouseout else return null; }探測按的是鼠標的哪個鍵function getButton(e){ if(document.implementation.hasFeature("MouseEvents","2.0")){ return e.button; }else { switch(e.button){ case 0 : case 1: case 3: case 5: case 7: return 0; case 2: case 6:return 2; case 4:return 1; } } }鼠標滾動事件//鼠標滾動,正數表示向上滾動 function getWheelDelta(e){ if(e.wheelData){ return (client.engine.opera&&client.engine.opera<9.5)? -e.wheelData:e.wheelData; }else { return -e.detail*40;//firefox } }提取選中的文本function getSelectedText(textbox){ if(typeof selectionStart=="number"){ return textbox.value.subString(textbox.selectionStart,textbox.selectionEnd); }else if(document.selection){//IE8之前沒有selectionStart,selectionEnd屬性 return document.selection.createRange().text; } }設置文本選中function selectText(textbox,startIndex,stopIndex){ if(textbox.setSelectionRange){ textbox.setSelectionRange(startIndex,stopIndex); }else if(textbox.createTextRange){//IE var range=textbox.createTextRange(); range.collapse(true); range.moveStart("character",0); range.moveEnd("character",stopIndex-startIndex); range.select(); } }bind方法對老版本的瀏覽器不起作用Function.prototype.bind = Function.prototype.bind || function(context){ var self = this; return function(){ return self.apply(context, arguments); }; }包裝cookie//cookie var cookieUtil={ // 創建cookie setcookie:function (name, value, expires, path, domain, secure) { var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value); if (expires instanceof Date) { cookieText += "; expires=" + expires.toGMTString(); } if (path) { cookieText += "; path=" + path; } if (domain) { cookieText += "; domain=" + domain; } if (secure) { cookieText += "; secure"; } document.cookie = cookieText; }, // 獲取cookie getcookie:function (name) { var cookieName = encodeURIComponent(name) + "="; var cookieStart = document.cookie.indexOf(cookieName); var cookieValue = null; if (cookieStart > -1) { var cookieEnd = document.cookie.indexOf(";", cookieStart); if (cookieEnd == -1) { cookieEnd = document.cookie.length; } cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd)); } return cookieValue; }, // 刪除cookie unsetcookie:function (name,path,domain,secure) { this.setcookie(name,"",new Date(0),path,domain,secure); } }包裝子cookie//子cookie var subcookieUtil={ get:function(name,subname){ var subcookie=getAll(name); if(subcookie){ return subcookie[subname]; }else { return null; } }, getAll:function(name){ var cookieName = encodeURIComponent(name) + "="; var cookieStart = document.cookie.indexOf(cookieName); var cookieValue = null; var subcookie,result={}; var len,i,parts; if (cookieStart > -1) { var cookieEnd = document.cookie.indexOf(";", cookieStart); if (cookieEnd == -1) { cookieEnd = document.cookie.length; } cookieValue = document.cookie.substring(cookieStart + cookieName.length, cookieEnd); if(cookieValue.length>0){ subcookie=cookieValue.split("&"); len=subcookie.length; for(i=0;iindexedDB0&&subcookies.hasOwnProperty(subname)){ subcookiesParts.push(encodeURIComponent(subname)+"="+encodeURIComponent(subcookies[subname])); } } if(subcookiesParts.length>0){ cookieText+=subcookiesParts.join("&"); if (expires instanceof Date) { cookieText += "; expires=" + expires.toGMTString(); } if (path) { cookieText += "; expires=" + expires; } if (domain) { cookieText += "; domain=" + domain; } if (secure) { cookieText += "; secure"; } } document.cookie = cookieText; }, unset:function(name,subname,path,domain,secure){ var subcookies=this.getAll(name); if(subcookies){ delete subcookies[subname]; this.setAll(name,subcookies,null,path,domain,secure); } }, unsetAll:function(name,path,domain,secure){ this.setAll(name,null,new Date(0),path,domain,secure); } } var indexedDB=window.indexedDB||window.mozIndexedDB||window.msIndexedDB||window.webkitIndexedDB; var idbRequest=indexedDB.open("vvv"); idbRequest.onsuccess=function(event){ database=event.target.result; } idbRequest.onerror=function(event){ alert(event.target.errorCode); }手寫typeoffunction type(obj) { var toString = Object.prototype.toString; var map = { "[object Boolean]" : "boolean", "[object Number]" : "number", "[object String]" : "string", "[object Function]" : "function", "[object Array]" : "array", "[object Date]" : "date", "[object RegExp]" : "regExp", "[object Undefined]": "undefined", "[object Null]" : "null", "[object Object]" : "object" }; if(obj instanceof Element) {//因為對不同標簽,toString會返回對應不同標簽的構造函數 return "element"; } return map[toString.call(obj)]; }深度克隆/** * * 深度克隆方法一,用的是instanceof */ function clone(Obj) { var buf; if (Obj instanceof Array) { buf = []; // 創建一個空的數組 var i = Obj.length; while (i--) { buf[i] = clone(Obj[i]); } return buf; } else if (Obj instanceof Object){ buf = {}; // 創建一個空對象 for (var k in Obj) { // 為這個對象添加新的屬性 buf[k] = clone(Obj[k]); } return buf; }else{ return Obj; } } /** * * 深度拷貝方法二,用的是 toString */ function deepClone(data) { var t = type(data), o, i, ni; if(t === "array") { o = []; }else if( t === "object") { o = {}; }else { return data; } if(t === "array") { for (i = 0, ni = data.length; i < ni; i++) { o.push(deepClone(data[i])); } return o; }else if( t === "object") { for( i in data) { o[i] = deepClone(data[i]); } return o; } } //通過JSON.stringify一下,然后再JSON.parse一下,就能實現深拷貝。但是數據類型只支持基本數值類型。 var obj = { a: "a", b: function(){console.log("b")} } JSON.stringify(obj);// "{"a":"a"}"組合使用構造函數模式和原型模式創建對象//組合使用構造函數模式和原型模式創建對象 function Person(name,age){ this.name=name; this.age=age; this.friends=["may","john"]; } Person.prototype={ constructor:Person,//字面量形式的原型默認構造函數是object,所以在這里要指定constructor sayName=function(){ alert(this.name); } }組合繼承//組合繼承 funcion super(name){ this.name=name; this.color=["red","blue"]; } Super.prototype.sayname=function(){ alert(this.name); } function Sub(age){ Super.call(this); this.age=age; } Sub.prototype=new Super();// Sub.prototype.constructor=Sub;//這個很重要!! Sub.prototype.sayage=function(){ alert(this.age); }觀察者模式//觀察者模式 function EventTarget(){ this.handlers = {}; } EventTarget.prototype = { constructor: EventTarget, addHandler: function(type, handler){ if (typeof this.handlers[type] == "undefined"){ this.handlers[type] = []; } this.handlers[type].push(handler); }, fire: function(event){//執行 if (!event.target){ event.target = this; } if (this.handlers[event.type] instanceof Array){ var handlers = this.handlers[event.type]; for (var i=0, len=handlers.length; i < len; i++){ handlers[i](event); } } }, removeHandler: function(type, handler){ if (this.handlers[type] instanceof Array){ var handlers = this.handlers[type]; for (var i=0, len=handlers.length; i < len; i++){ if (handlers[i] === handler){ break; } } handlers.splice(i, 1); } } };分享一個題目//[附加題] 請實現下面的自定義事件 Event 對象的接口,功能見注釋(測試1) //該 Event 對象的接口需要能被其他對象拓展復用(測試2) //測試1 Event.on("test", function (result) { console.log(result); }); Event.on("test", function () { console.log("test"); }); Event.emit("test", "hello world"); // 輸出 "hello world" 和 "test" // 測試2 var person1 = {}; var person2 = {}; Object.assign(person1, Event); Object.assign(person2, Event); person1.on("call1", function () { console.log("person1"); }); person2.on("call2", function () { console.log("person2"); }); person1.emit("call1"); //輸出 "person1" person1.emit("call2"); // 沒有輸出 person2.emit("call1"); // 沒有輸出 person2.emit("call2"); // 輸出 "person2" var Event = { // 通過on接口監聽事件eventName // 如果事件eventName被觸發,則執行callback回調函數 on: function (eventName, callback) { //你的代碼 if(!this.handles){ //Object.assign(target, source); //這個是ES6的新對象方法,用于對象的合并,將源對象(source)的所有可枚舉屬性,復制到目標對象(target)。 Object.defineProperty(this, "handles", { value: {}, enumerable: false,//關鍵! configurable: true, writable: true }) } if(!this.handles[eventName]){ this.handles[eventName]=[]; } this.handles[eventName].push(callback); }, // 觸發事件 eventName emit: function (eventName) { //你的代碼 if(this.handles[arguments[0]]){ for(var i=0;i50 && nHeight > 50) { aResult.push(oNode); } } var aChildNodes = oNode.childNodes; if (aChildNodes.length > 0) { for (var i = 0, l = aChildNodes.length; i < l; i++) { var oTmp = aChildNodes[i]; aResult = aResult.concat(traverse(oTmp)); } } return aResult; }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92936.html
摘要:前言終于要做這個計劃了,前端框架千千萬,絕不能一頭扎進去盲目開始,本片文章總結一下目前前各種端框架,以及它們的用途主要解決什么問題,然后最后做出學習計劃。希望入了前端坑的同學們可以有所幫助。但是庫與框架很難嚴格區分,所以統一稱為解決方案。 前言:終于要做這個計劃了,前端框架千千萬,絕不能一頭扎進去盲目開始,本片文章總結一下目前前各種端框架,以及它們的用途主要解決什么問題,然后最后做出學...
摘要:由于是需要兼容的后臺系統,該項目并不能使用到等技術,因此我在上的經驗大都是使用原生的編寫的,可以看見一個組件分為兩部分視圖部分,和數據部分。 在公司里幫項目組里開發后臺系統的前端項目也有一段時間了。 vue這種數據驅動,組件化的框架和react很像,從一開始的快速上手基本的開發,到后來開始自定義組件,對element UI的組件二次封裝以滿足項目需求,期間也是踩了不少坑。由于將來很長一...
摘要:如何實現瀏覽器內多個標簽頁之間的通信阿里調用等本地存儲方式頁面可見性可以有哪些用途通過的值檢測頁面當前是否可見,以及打開網頁的時間等在頁面被切換到其他后臺進程的時候,自動暫停音樂或視頻的播放網頁驗證碼是干嘛的,是為了解決什么安全問題。 前端面試題總結——綜合問題(持續更新中) 1.頁面從輸入URL到頁面加載顯示完成,這個過程中都發生了什么?(流程說的越詳細越好) 1.輸入域名地址2.發...
摘要:如何實現瀏覽器內多個標簽頁之間的通信阿里調用等本地存儲方式頁面可見性可以有哪些用途通過的值檢測頁面當前是否可見,以及打開網頁的時間等在頁面被切換到其他后臺進程的時候,自動暫停音樂或視頻的播放網頁驗證碼是干嘛的,是為了解決什么安全問題。 前端面試題總結——綜合問題(持續更新中) 1.頁面從輸入URL到頁面加載顯示完成,這個過程中都發生了什么?(流程說的越詳細越好) 1.輸入域名地址2.發...
摘要:如何實現瀏覽器內多個標簽頁之間的通信阿里調用等本地存儲方式頁面可見性可以有哪些用途通過的值檢測頁面當前是否可見,以及打開網頁的時間等在頁面被切換到其他后臺進程的時候,自動暫停音樂或視頻的播放網頁驗證碼是干嘛的,是為了解決什么安全問題。 前端面試題總結——綜合問題(持續更新中) 1.頁面從輸入URL到頁面加載顯示完成,這個過程中都發生了什么?(流程說的越詳細越好) 1.輸入域名地址2.發...
閱讀 1860·2021-11-25 09:43
閱讀 3693·2021-11-24 10:32
閱讀 1084·2021-10-13 09:39
閱讀 2337·2021-09-10 11:24
閱讀 3351·2021-07-25 21:37
閱讀 3471·2019-08-30 15:56
閱讀 866·2019-08-30 15:44
閱讀 1456·2019-08-30 13:18