摘要:惰性載入表示函數(shù)執(zhí)行的分支只會(huì)發(fā)生一次,這里有兩種解決方式。插件,可以讓回調(diào)函數(shù)在頁(yè)面結(jié)構(gòu)加載完成后再運(yùn)行。
前端基本功-示例代碼 (一) 點(diǎn)這里
前端基本功-示例代碼 (二) 點(diǎn)這里
var xhr = new XMLHttpRequest(); // 聲明一個(gè)請(qǐng)求對(duì)象 // 前端設(shè)置是否帶cookie xhr.withCredentials = true; xhr.open("GET", "xxxx"); //xhr.open("post", "http://www.domain2.com:8080/login", true); // 如何設(shè)置請(qǐng)求頭? xhr.setRequestHeader(header, value); xhr.setRequestHeader("Content-Type", "application/json"); xhr.onreadystatechange = function(){ if(xhr.readyState === 4){ // readyState 4 代表已向服務(wù)器發(fā)送請(qǐng)求 if(xhr.status === 200){ // status 200 代表服務(wù)器返回成功 console.log(xhr.responseText); // 這是返回的文本 } else{ console.log("Error: "+ xhr.status); // 連接失敗的時(shí)候拋出錯(cuò)誤 } } } xhr.send(null); //xhr.send("user=admin"); // get方法 send null(亦或者不傳,則直接是傳遞 header) ,post 的 send 則是傳遞值2.jsonp 1.)原生實(shí)現(xiàn):
服務(wù)端返回如下(返回時(shí)即執(zhí)行全局函數(shù)):
onBack({"status": true, "user": "admin"})2.)jquery ajax:
$.ajax({ url: "http://www.domain2.com:8080/login", type: "get", dataType: "jsonp", // 請(qǐng)求方式為jsonp jsonpCallback: "onBack", // 自定義回調(diào)函數(shù)名 data: {} });3.)vue.js:
this.$http.jsonp("http://www.domain2.com:8080/login", { params: {}, jsonp: "onBack" }).then((res) => { console.log(res); })4.)npm包jsonp:
npm install jsonp --save
import originJSONP from "jsonp" //引入jsonp //進(jìn)行封裝并export export default function jsonp(url,data,option) { url += (url.indexOf("?")<0? "?" : "&")+param(data) return new Promise((resolve,reject)=>{ originJSONP(url,option,(err,data)=>{ if(!err){ resolve(data) }else{ reject(err) } }) }) } //對(duì)data進(jìn)行處理,并encodeURIComponent()進(jìn)行轉(zhuǎn)碼。 function param(data) { let url = "" for(var k in data) { let value = data[k] !== undefined? data[k] : "" url += "&" + k + "=" + encodeURIComponent(value) } return url ? url.substring(1) : "" }
本節(jié)參考文章: vue項(xiàng)目中jsonp跨域獲取qq音樂(lè)首頁(yè)推薦
3.實(shí)現(xiàn)一個(gè)簡(jiǎn)單的PromisePromise對(duì)象調(diào)用
let p =new Promise(function(resolve, reject){ if(/* 異步操作成功 */){ resolve(data) }else{ reject(err) } })
p.then((res)=>{ console.log(res) },(err)=>{ console.log(err) })
實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Promise
function Promise(fn){ var status = "pending" function successNotify(){ status = "fulfilled"http://狀態(tài)變?yōu)閒ulfilled toDoThen.apply(undefined, arguments)//執(zhí)行回調(diào) } function failNotify(){ status = "rejected"http://狀態(tài)變?yōu)閞ejected toDoThen.apply(undefined, arguments)//執(zhí)行回調(diào) } function toDoThen(){ setTimeout(()=>{ // 保證回調(diào)是異步執(zhí)行的 if(status === "fulfilled"){ for(let i =0; i< successArray.length;i ++) { successArray[i].apply(undefined, arguments)//執(zhí)行then里面的回掉函數(shù) } }else if(status === "rejected"){ for(let i =0; i< failArray.length;i ++) { failArray[i].apply(undefined, arguments)//執(zhí)行then里面的回掉函數(shù) } } }) } var successArray = [] var failArray = [] fn.call(undefined, successNotify, failNotify) return { then: function(successFn, failFn){ successArray.push(successFn) failArray.push(failFn) return undefined // 此處應(yīng)該返回一個(gè)Promise } } }
解題思路:Promise中的resolve和reject用于改變Promise的狀態(tài)和傳參,then中的參數(shù)必須是作為回調(diào)執(zhí)行的函數(shù)。因此,當(dāng)Promise改變狀態(tài)之后會(huì)調(diào)用回調(diào)函數(shù),根據(jù)狀態(tài)的不同選擇需要執(zhí)行的回調(diào)函數(shù)。
本節(jié)參考文章:面向面試題和實(shí)際使用談promise
示例2
const PENDING = "pending"; //等待 const FULFILLED = "fulfilled"; //已完成 const REJECTED = "rejected"; // 已拒絕 function Promise(executor) { let self = this; self.status = PENDING; self.value; self.reason; function resolve(value) { if (self.status === PENDING) { self.status = FULFILLED; self.value = value; } } function reject(reason) { if (self.status === PENDING) { self.status = REJECTED; self.reason = reason; } } try { // 規(guī)范提到,執(zhí)行器拋異常會(huì)reject executor(resolve, reject); } catch(e) { reject(e) } } // then方法實(shí)現(xiàn) Promise.prototype.then = function (onFulfilled, onRjected) { let self = this; /** * onFulfilled 和 onRejected 都是可選參數(shù)。 * 如果 onFulfilled 不是函數(shù),其必須被忽略 * 如果 onRejected 不是函數(shù),其必須被忽略 */ onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function(value) { return value; }; onRjected = typeof onRjected === "function" ? onRjected : function(reason) { throw reason; } if (self.status === FULFILLED) { onFulfilled(self.value); } if (self.status === REJECTED) { onRjected(self.reason); } }
本節(jié)參考文章:Javascript Promise學(xué)習(xí)過(guò)程總結(jié)
4.閉包var fn = function() { var divs = document.querySelectorAll("div"); for (var i = 0; i < 3; i++) { divs[i].onclick = (function(i) { return function() { alert(i); }; })(i); } }; fn();
或者如下的寫(xiě)法:
var fn = function() { var divs = document.querySelectorAll("div"); for (var i = 0; i < 3; i++) { (function(i) { divs[i].onclick = function() { alert(i); }; })(i); } }; fn();
for (var i = 0; i < 3; i++) { setTimeout((function(i) { return function() { console.log(i); }; })(i), 0); console.log(i); }5.事件代理
事件代理(Event Delegation),又稱之為事件委托。是 JavaScript 中常用綁定事件的常用技巧。“事件代理”即是把原本需要綁定的事件委托給父元素,讓父元素?fù)?dān)當(dāng)事件監(jiān)聽(tīng)的職務(wù)。事件代理的原理是DOM元素的事件冒泡。
減少事件注冊(cè),節(jié)省內(nèi)存占用,提高性能
可以實(shí)現(xiàn)當(dāng)新增子對(duì)象時(shí)無(wú)需再次對(duì)其綁定
6.封裝dom查詢(面向?qū)ο螅?/b>添加繪畫(huà)散步靜坐
function Elem(id){ this.elem = document.getElementById(id) } Elem.prototype.html = function(val){ var elem = this.elem if(val) { elem.innerHTML = val return this //鏈?zhǔn)? } else { return elem.innerHTML } } Elem.prototype.on = function(type,fn){ var elem = this.elem elem.addEventListener(type, fn) return this //鏈?zhǔn)? } //調(diào)用 var div = new Elem("id") div.html("7.DOM劫持hello
").on("click",function(){ console.log("suceess") })
function nodeToFragment (node) { var flag = document.createDocumentFragment(); var child; // 首先,所有表達(dá)式必然會(huì)返回一個(gè)值,賦值表達(dá)式亦不例外 // 理解了上面這一點(diǎn),就能理解 while (child = node.firstChild) 這種用法 // 其次,appendChild 調(diào)用以后 child 會(huì)從原來(lái) DOM 中移除 // 所以,第二次循環(huán)時(shí),node.firstChild 已經(jīng)不再是之前的第一個(gè)子元素了 while (child = node.firstChild) { flag.appendChild(child); // 將子節(jié)點(diǎn)劫持到文檔片段中 } return flag }8.添加calssName
// 為元素添加類(lèi)名 export function addClass(el, className) { // 先判斷一下元素是否含有需要添加的類(lèi)名,有則直接 return if(hasClass(el, className)) { return } // 把該元素含有的類(lèi)名以空格分割 let newClass = el.className.split(" ") // 把需要的類(lèi)名 push 進(jìn)來(lái) newClass.push(className) // 最后以空格拼接 el.className = newClass.join(" ") } // 判斷是否有要查看的 className,有則返回true,否則返回 false export function hasClass(el, className) { let reg = new RegExp("(^|s)" + className + "(s|$)") return reg.test(el.className) }9.自動(dòng)添加游覽器前綴
let elementStyle = document.createElement("div").style // 主流瀏覽器內(nèi)核 let vendor = (() => { let transfromNames = { webkit: "webkitTransform", Moz: "MozTransform", ms: "msTransform", O: "OTransform", standard: "transform" } for(let key in transfromNames) { if(elementStyle[transfromNames[key]] !== undefined) { return key } } return false })() // 添加樣式的瀏覽器前綴 export function prefixStyle(style) { if(vendor === false) { return false } if(vendor === "standard") { return style } return vendor + style.charAt(0).toUpperCase() + style.substr(1) }10.圖片懶加載
定義:延遲加載也稱為惰性加載,即在長(zhǎng)網(wǎng)頁(yè)中延遲加載圖像。用戶滾動(dòng)到它們之前,視口外的圖像不會(huì)加載。這與圖像預(yù)加載相反,在長(zhǎng)網(wǎng)頁(yè)上使用延遲加載將使網(wǎng)頁(yè)加載更快。在某些情況下,它還可以幫助減少服務(wù)器負(fù)載。
Lazyload 1
jQuery的error事件
$("img").error(function(){ $(this).attr("src","http://ww.jpg"); });
jQuery的one綁定
使用onerror或者jQuery的error事件時(shí),如果默認(rèn)圖片也發(fā)生加載失敗,則會(huì)形成死循環(huán),最好的辦法是使用one綁定事件,只執(zhí)行一次
$("img").one("error", function(e){ $(this).attr("src", "http://ww.jpg"); });12.圖片按比例響應(yīng)式縮放、裁剪
html部分:
css部分:
.zoomImage{ width:100%; height:0; padding-bottom: 100%; overflow:hidden; //padding為百分比的時(shí)候根據(jù)他父層的寬度來(lái)進(jìn)行計(jì)算 background-position: center center; background-repeat: no-repeat; -webkit-background-size:cover; -moz-background-size:cover; //把背景圖像擴(kuò)展至完全覆蓋背景區(qū)域 background-size:cover; }
總結(jié):你所需要的比例,就是width與padding-bottom的比例
用的時(shí)候,直接把.zoomImage當(dāng)成img標(biāo)簽來(lái)用就可以了。
思維擴(kuò)展
很多輪播的插件本來(lái)是響應(yīng)式的, 但可能有兩個(gè)問(wèn)題:
1.這個(gè)輪播圖你必須要給他一個(gè)高度,但高度不是固定死的,是需要按比例的...
2.輪播圖里的圖片不是需要的比例...
所以我們可以用剛剛上面的padding方法
拿swiper輪播圖插件舉例
優(yōu)化前
優(yōu)化后
本節(jié)詳細(xì):如何讓圖片按比例響應(yīng)式縮放、并自動(dòng)裁剪的css技巧
13.選項(xiàng)卡切換html的結(jié)構(gòu)和樣式:
111222333
//過(guò)程式的編程思想 window.onload=function(){ //獲取元素 var oParent=document.getElementById("div1"); var btns=oParent.getElementsByTagName("button"); var divs=oParent.getElementsByTagName("div"); //通過(guò)循環(huán)給每個(gè)btn添加點(diǎn)擊事件 for (var i = 0; i < btns.length; i++) { btns[i].index=i;//存儲(chǔ)當(dāng)前btn的下標(biāo) btns[i].onclick=function(){ for (var i = 0; i < btns.length; i++) { btns[i].className=""; divs[i].style.display="none"; } this.className="active"; divs[this.index].style.display="block";//讓對(duì)應(yīng)當(dāng)前btn的div顯示 } } }
//面向?qū)ο?window.onload = function(){ var t1=new Tab(); t1.init(); }; function Tab() { this.btns=oParent.getElementsByTagName("button"); this.divs=oParent.getElementsByTagName("div"); } Tab.prototype.init=function(){ var This=this; for (var i = 0; i < this.btns.length; i++) { this.btns[i].index=i; this.btns[i].onclick=function(){ This.change(this); } } } Tab.prototype.change=function(btn) { for (var i = 0; i < this.btns.length; i++) { this.btns[i].className=""; this.divs[i].style.display="none"; } btn.className="active"; this.divs[btn.index].style.display="block"; };14.元素拖拽
#div1{ width: 100px; height: 100px; background: red; position: absolute; }
//過(guò)程式的編程思想 window.onload=function(){ var oDiv=document.getElementById("div1"); var disX=0; var disY=0; oDiv.onmousedown=function(ev){ var ev=ev || window.event; disX=ev.clientX-oDiv.offsetLeft; disY=ev.clientY-oDiv.offsetTop; document.onmousemove=function(ev){ var ev=ev || window.event; oDiv.style.left=ev.clientX-disX+"px"; oDiv.style.top=ev.clientY-disY+"px"; }; document.onmouseup=function(){ document.onmousemove=null; document.onmouseup=null; } return false; } }
//面向?qū)ο?window.onload = function() { var d1 = new Drag("div1"); d1.init(); }; function Drag(id) { this.oDiv = document.getElementById(id); this.disX = 0; this.disY = 0; } Drag.prototype.init = function() { var This = this; this.oDiv.onmousedown = function(ev) { var ev = ev || window.event; This.fnDown(ev); return false; }; }; Drag.prototype.fnDown = function(ev) { var This = this; this.disX = ev.clientX - this.oDiv.offsetLeft; this.disY = ev.clientY - this.oDiv.offsetTop; document.onmousemove = function(ev) { var ev = ev || window.event; This.fnMove(ev); }; document.onmouseup = function() { This.fnUp(); } }; Drag.prototype.fnMove = function(ev) { this.oDiv.style.left = ev.clientX - this.disX + "px"; this.oDiv.style.top = ev.clientY - this.disY + "px"; }; Drag.prototype.fnUp = function() { document.onmousemove = null; document.onmouseup = null; };15.函數(shù)節(jié)流(throttle)
//fn 要執(zhí)行的函數(shù) //delay 延遲 //atleast 在time時(shí)間內(nèi)必須執(zhí)行一次 function throttle(fn, delay, atleast) { var timeout = null, startTime = new Date(); return function() { var curTime = new Date(); clearTimeout(timeout); // 如果達(dá)到了規(guī)定的觸發(fā)時(shí)間間隔,觸發(fā) handler if(curTime - startTime >= atleast) { fn(); startTime = curTime; }else { // 沒(méi)達(dá)到觸發(fā)間隔,重新設(shè)定定時(shí)器 timeout = setTimeout(fn, delay); } } } // 實(shí)際想綁定在 scroll 事件上的 handler function lazyload(event) { console.log("觸發(fā)了") }
// 采用了節(jié)流函數(shù) window.addEventListener("scroll",throttle(lazyload,500,1000));16.函數(shù)去抖(debounce)
// debounce函數(shù)用來(lái)包裹我們的事件 function debounce(fn, delay) { // 持久化一個(gè)定時(shí)器 timer let timer = null; return function() { // 如果事件被觸發(fā),清除 timer 并重新開(kāi)始計(jì)時(shí) clearTimeout(timer); timer = setTimeout(function() { fn(); }, delay); } } // 實(shí)際想綁定在 scroll 事件上的 handler function lazyload(event) { console.log("觸發(fā)了") } // 采用了去抖函數(shù) window.addEventListener("scroll",debounce(lazyload,500));17.分時(shí)函數(shù)
如果一次獲得了很多數(shù)據(jù)(比如有10W數(shù)據(jù)),然后在前端渲染的時(shí)候會(huì)卡到爆,所以在處理這么多數(shù)據(jù)的時(shí)候,我們可以選擇分批進(jìn)行。
function timeChunk(data, fn, count = 1, wait) { let obj, timer; function start() { let len = Math.min(count, data.length); for (let i = 0; i < len; i++) { val = data.shift(); // 每次取出一個(gè)數(shù)據(jù),傳給fn當(dāng)做值來(lái)用 fn(val); } } return function() { timer = setInterval(function() { if (data.length === 0) { // 如果數(shù)據(jù)為空了,就清空定時(shí)器 return clearInterval(timer); } start(); }, wait); // 分批執(zhí)行的時(shí)間間隔 } } // 測(cè)試用例 let arr = []; for (let i = 0; i < 100000; i++) { // 這里跑了10萬(wàn)數(shù)據(jù) arr.push(i); } let render = timeChunk(arr, function(n) { // n為data.shift()取到的數(shù)據(jù) let div = document.createElement("div"); div.innerHTML = n; document.body.appendChild(div); }, 8, 20); render();
參考文章:高階函數(shù),你怎么那么漂亮呢!
18.惰性載入函數(shù)假如你要寫(xiě)一個(gè)函數(shù),里面有一些判斷語(yǔ)句
function foo(){ if(a != b){ console.log("aaa") }else{ console.log("bbb") } }
如果你的a和b是不變的,那么這個(gè)函數(shù)不論執(zhí)行多少次,結(jié)果都是不變的,但是每次執(zhí)行還要進(jìn)行if判斷,這就造成了不必要的浪費(fèi)。
惰性載入表示函數(shù)執(zhí)行的分支只會(huì)發(fā)生一次,這里有兩種解決方式。
// 常見(jiàn)的例子 if (window.addEventListener) { ele.addEventListener(type, fn, false); } else if (window.attachEvent) { ele.attachEvent("on" + type, fn); }
在函數(shù)被調(diào)用時(shí)再處理函數(shù)
function foo(){ if(a != b){ foo = function(){ console.log("aaa") } }else{ foo = function(){ console.log("bbb") } } return foo(); }
這樣進(jìn)入每個(gè)分支后都會(huì)對(duì)foo進(jìn)行賦值,覆蓋了之前的函數(shù),之后每次調(diào)用foo就不會(huì)再執(zhí)行if判斷
在聲明函數(shù)時(shí)就指定適當(dāng)?shù)暮瘮?shù)
var foo = (function foo(){ if(a != b){ return function(){ console.log("aaa") } }else{ return function(){ console.log("bbb") } } })();
本節(jié)參考文章:JS高級(jí)技巧(簡(jiǎn)潔版)
19.實(shí)現(xiàn)once函數(shù)function test(){ alert("hello"); } var once = function (fn) { var isFirst = true; return function () { if (isFirst) { isFirst = !isFirst; fn(); } }; }; once(test); once(test);20.requirejs架子
require.js的誕生,就是為了解決這兩個(gè)問(wèn)題:
實(shí)現(xiàn)js文件的異步加載,避免網(wǎng)頁(yè)失去響應(yīng);
管理模塊之間的依賴性,便于代碼的編寫(xiě)和維護(hù)。
/** 網(wǎng)頁(yè)中引入require.js及main.js **/ /** main.js 入口文件/主模塊 **/ // 首先用config()指定各模塊路徑和引用名 require.config({ baseUrl: "js/lib", paths: { "jquery": "jquery.min", //實(shí)際路徑為js/lib/jquery.min.js "underscore": "underscore.min", } }); // 執(zhí)行基本操作 require(["jquery","underscore"],function($,_){ // some code here });
引用模塊的時(shí)候,我們將模塊名放在[]中作為reqiure()的第一參數(shù);如果我們定義的模塊本身也依賴其他模塊,那就需要將它們放在[]中作為define()的第一參數(shù)。
// 定義math.js模塊 define(function () { var basicNum = 0; var add = function (x, y) { return x + y; }; return { add: add, basicNum :basicNum }; }); // 定義一個(gè)依賴underscore.js的模塊 define(["underscore"],function(_){ var classify = function(list){ _.countBy(list,function(num){ return num > 30 ? "old" : "young"; }) }; return { classify :classify }; }) // 引用模塊,將模塊放在[]內(nèi) require(["jquery", "math"],function($, math){ var sum = math.add(10,20); $("#sum").html(sum); });
加載非規(guī)范的模塊
理論上,require.js加載的模塊,必須是按照AMD規(guī)范、用define()函數(shù)定義的模塊。但是實(shí)際上,雖然已經(jīng)有一部分流行的函數(shù)庫(kù)(比如jQuery)符合AMD規(guī)范,更多的庫(kù)并不符合。那么,require.js是否能夠加載非規(guī)范的模塊呢?
這樣的模塊在用require()加載之前,要先用require.config()方法,定義它們的一些特征。舉例來(lái)說(shuō),underscore和backbone這兩個(gè)庫(kù),都沒(méi)有采用AMD規(guī)范編寫(xiě)。如果要加載它們的話,必須先定義它們的特征。
require.config({ shim: { "underscore":{ exports: "_" }, "backbone": { deps: ["underscore", "jquery"], exports: "Backbone" } } });
require.config()接受一個(gè)配置對(duì)象,這個(gè)對(duì)象除了有前面說(shuō)過(guò)的paths屬性之外,還有一個(gè)shim屬性,專門(mén)用來(lái)配置不兼容的模塊。具體來(lái)說(shuō),每個(gè)模塊要定義(1)exports值(輸出的變量名),表明這個(gè)模塊外部調(diào)用時(shí)的名稱;(2)deps數(shù)組,表明該模塊的依賴性。
比如,jQuery的插件可以這樣定義:
shim: { "jquery.scroll": { deps: ["jquery"], exports: "jQuery.fn.scroll" } }
require.js插件
require.js還提供一系列插件,實(shí)現(xiàn)一些特定的功能。domready插件,可以讓回調(diào)函數(shù)在頁(yè)面DOM結(jié)構(gòu)加載完成后再運(yùn)行。
require(["domready!"], function (doc){ // called once the DOM is ready });
text和image插件,則是允許require.js加載文本和圖片文件。
define([ "text!review.txt", "image!cat.jpg" ], function(review,cat){ console.log(review); document.body.appendChild(cat); } );
類(lèi)似的插件還有json和mdown,用于加載json文件和markdown文件。
本節(jié)參考文章:require.js的用法
華米科技 招前端聯(lián)系: 于夢(mèng)中(wx:tsw0618) 內(nèi)推,備注來(lái)意,簡(jiǎn)歷請(qǐng)甩 weihongjie@huami.com
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/100980.html
摘要:基本結(jié)構(gòu)語(yǔ)言中,一個(gè)頁(yè)面是由四個(gè)部分組成文檔聲明標(biāo)簽對(duì)標(biāo)簽對(duì)標(biāo)簽對(duì)圖示文檔聲明這是一個(gè)文檔聲明,表示這是一個(gè)頁(yè)面。標(biāo)簽標(biāo)簽表示頁(yè)面內(nèi)容的范圍。 HTML HTML ...
摘要:可見(jiàn)對(duì)一個(gè)頁(yè)面正確渲染很重要。和標(biāo)簽對(duì)用于標(biāo)識(shí)頁(yè)面的頭部區(qū)域,和之間的內(nèi)容都屬于頭部區(qū)域中的內(nèi)容。是一個(gè)輔助性標(biāo)簽,對(duì)頁(yè)面可以進(jìn)行很多方面的特性的設(shè)置。當(dāng)頁(yè)面沒(méi)有設(shè)置字符集時(shí),瀏覽器會(huì)使用默認(rèn)的字符編碼顯示。 showImg(https://segmentfault.com/img/bVbjNkI?w=900&h=383); 往期回顧 在 1.2 節(jié)介紹 HTML 語(yǔ)言時(shí)講到:HTML...
摘要:前端基本功示例代碼一點(diǎn)這里前端基本功示例代碼二點(diǎn)這里一像素偽類(lèi)實(shí)現(xiàn)對(duì)于老項(xiàng)目,有沒(méi)有什么辦法能兼容的尷尬問(wèn)題了,個(gè)人認(rèn)為偽類(lèi)是比較完美的方法了。 前端基本功-示例代碼 (一) 點(diǎn)這里前端基本功-示例代碼 (二) 點(diǎn)這里 1.一像素 偽類(lèi) + transform 實(shí)現(xiàn)對(duì)于老項(xiàng)目,有沒(méi)有什么辦法能兼容1px的尷尬問(wèn)題了,個(gè)人認(rèn)為偽類(lèi)+transform是比較完美的方法了。 原理是把原先元素...
摘要:前端基本功示例代碼一點(diǎn)這里前端基本功示例代碼二點(diǎn)這里一像素偽類(lèi)實(shí)現(xiàn)對(duì)于老項(xiàng)目,有沒(méi)有什么辦法能兼容的尷尬問(wèn)題了,個(gè)人認(rèn)為偽類(lèi)是比較完美的方法了。 前端基本功-示例代碼 (一) 點(diǎn)這里前端基本功-示例代碼 (二) 點(diǎn)這里 1.一像素 偽類(lèi) + transform 實(shí)現(xiàn)對(duì)于老項(xiàng)目,有沒(méi)有什么辦法能兼容1px的尷尬問(wèn)題了,個(gè)人認(rèn)為偽類(lèi)+transform是比較完美的方法了。 原理是把原先元素...
摘要:后代選擇器后代選擇器又稱包含選擇器,用于選擇指定元素的后代元素。這些選擇器既可以是基本選擇器,也可以是一個(gè)復(fù)合選擇器。注意元素選擇器及和屬性選擇器之間沒(méi)有空格。 showImg(https://segmentfault.com/img/bVblJEJ?w=900&h=383); 復(fù)合選擇器是通過(guò)基本選擇器進(jìn)行組合后構(gòu)成的,常用的復(fù)合選擇器有: 交集選擇器 并集選持器 后代選擇器 子元...
摘要:惰性載入表示函數(shù)執(zhí)行的分支只會(huì)發(fā)生一次,這里有兩種解決方式。插件,可以讓回調(diào)函數(shù)在頁(yè)面結(jié)構(gòu)加載完成后再運(yùn)行。 前端基本功-示例代碼 (一) 點(diǎn)這里前端基本功-示例代碼 (二) 點(diǎn)這里 1.ajax var xhr = new XMLHttpRequest(); // 聲明一個(gè)請(qǐng)求對(duì)象 // 前端設(shè)置是否帶cookie xhr.withCredentials = true; xhr....
閱讀 1993·2021-11-24 10:45
閱讀 1850·2021-10-09 09:43
閱讀 1291·2021-09-22 15:38
閱讀 1219·2021-08-18 10:19
閱讀 2837·2019-08-30 15:55
閱讀 3057·2019-08-30 12:45
閱讀 2962·2019-08-30 11:25
閱讀 356·2019-08-29 11:30