2:Vue雙向數(shù)據(jù)綁定的實(shí)現(xiàn)
vue.js 則是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個(gè)屬性的setter,getter,在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給 訂閱者(文本節(jié)點(diǎn)則是作為訂閱者),在收到消息后執(zhí)行相應(yīng)的更新操作。
compile主要做的事情是解析模板指令,將模板中的變量替換成數(shù)據(jù),然后初始化渲染頁面視圖,并將每個(gè)指令對應(yīng)的節(jié)點(diǎn)綁定更新函數(shù),添加監(jiān)聽數(shù)據(jù)的訂閱者,一旦數(shù)據(jù)有變動(dòng),收到通知,更新視圖
MVVM作為數(shù)據(jù)綁定的入口,整合Observer、Compile和Watcher三者,通過Observer來監(jiān)聽自己的model數(shù)據(jù)變化,通過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋梁,達(dá)到數(shù)據(jù)變化 -> 視圖更新;視圖交互變化(input) -> 數(shù)據(jù)model變更的雙向綁定效果。
AngularJS 采用“臟值檢測”的方式,數(shù)據(jù)發(fā)生變更后,對于所有的數(shù)據(jù)和視圖的綁定關(guān)系進(jìn)行一次檢測,識別是否有數(shù)據(jù)發(fā)生了改變。
3:react和vue有哪些不同 說說你對這兩個(gè)框架的看法
都用了virtual dom的方式, 性能都很好
ui上都是組件化的寫法,開發(fā)效率很高
vue是雙向數(shù)據(jù)綁定,react是單項(xiàng)數(shù)據(jù)綁定,當(dāng)工程規(guī)模比較大時(shí)雙向數(shù)據(jù)綁定會(huì)很難維護(hù)
vue適合不會(huì)持續(xù)的 小型的web應(yīng)用,使用vue.js能帶來短期內(nèi)較高的開發(fā)效率. 否則采用react
4:let和const的區(qū)別
let聲明的變量可以改變,值和類型都可以改變,沒有限制。
const聲明的變量不得改變值 本質(zhì)就是地址不會(huì)改變,但可以改變它屬性的值
5:平時(shí)用了es6的哪些特性,體驗(yàn)如何 和es5有什么不同
let const關(guān)鍵字 箭頭函數(shù) 字符串模板 class類 模塊化 promise
es5 require react.createclass
6:瀏覽器原生支持module嗎,如果支持,會(huì)帶來哪些便利
不支持
7:介紹一下你對webpack的理解,和gulp有什么不同
Webpack是模塊打包工具,他會(huì)分析模塊間的依賴關(guān)系,然后使用loaders處理它們,最后生成一個(gè)優(yōu)化并且合并后的靜態(tài)資源。
gulp是前端自動(dòng)化工具 能夠優(yōu)化前端工作流程,比如文件合并壓縮
8:webpack打包速度慢,你覺得可能的原因是什么,該如何解決
模塊太多
Webpack 可以配置 externals 來將依賴的庫指向全局變量,從而不再打包這個(gè)庫
9:http響應(yīng)中content-type包含哪些內(nèi)容
請求中的消息主體是用何種方式編碼
application/x-www-form-urlencoded
這是最常見的 POST 提交數(shù)據(jù)的方式 按照 key1=val1&key2=val2 的方式進(jìn)行編碼
application/json
告訴服務(wù)端消息主體是序列化后的 JSON 字符串
10:瀏覽器緩存有哪些,通常緩存有哪幾種方式
強(qiáng)緩存 強(qiáng)緩存如果命中,瀏覽器直接從自己的緩存中讀取資源,不會(huì)發(fā)請求到服務(wù)器。
協(xié)商緩存 當(dāng)強(qiáng)緩存沒有命中的時(shí)候,瀏覽器一定會(huì)發(fā)送一個(gè)請求到服務(wù)器,通過服務(wù)器端依據(jù)資源的另外一些http header驗(yàn)證這個(gè)資源是否命中協(xié)商緩存,如果協(xié)商緩存命中,服務(wù)器會(huì)將這個(gè)請求返回(304),若未命中請求,則將資源返回客戶端,并更新本地緩存數(shù)據(jù)(200)。
HTTP頭信息控制緩存
Expires(強(qiáng)緩存)+過期時(shí)間 Expires是HTTP1.0提出的一個(gè)表示資源過期時(shí)間的header,它描述的是一個(gè)絕對時(shí)間
Cache-control(強(qiáng)緩存) 描述的是一個(gè)相對時(shí)間,在進(jìn)行緩存命中的時(shí)候,都是利用客戶端時(shí)間進(jìn)行判斷 管理更有效,安全一些 Cache-Control: max-age=3600
Last-Modified/If-Modified-Since(協(xié)商緩存) 標(biāo)示這個(gè)響應(yīng)資源的最后修改時(shí)間。Last-Modified是服務(wù)器相應(yīng)給客戶端的,If-Modified-Sinces是客戶端發(fā)給服務(wù)器,服務(wù)器判斷這個(gè)緩存時(shí)間是否是最新的,是的話拿緩存。
Etag/If-None-Match(協(xié)商緩存) etag和last-modified類似,他是發(fā)送一個(gè)字符串來標(biāo)識版本。
11:如何取出一個(gè)數(shù)組里的圖片并按順序顯示出來
function loadImage(imgList,callback){
if(!$.isArray(imgList) || !$.isFunction(callback)) return ;
var imageData = [] ;
$.each(imgList, function(i,src){
var img = new Image() ;
img.onload = function(){
$(imageData.shift()).appendTo("body") ;
if(!imageData.length){
callback() ;
return ;
}
this.onload = null ;
} ;
img.src= src ;
imageData.push(img) ;
}) ;
} ;
12:平時(shí)是怎么學(xué)新技術(shù)的
infoq 掘金 簡書 慕課網(wǎng) B站
13:Node,Koa用的怎么樣
koa是一個(gè)相對于express來說,更小,更健壯,更富表現(xiàn)力的Web框架,不用寫回調(diào)
koa是從第一個(gè)中間件開始執(zhí)行,遇到next進(jìn)入下一個(gè)中間件,一直執(zhí)行到最后一個(gè)中間件,在逆序
async await語法的支持
14:使用模塊化加載時(shí),模塊加載的順序是怎樣的,如果不知道,根據(jù)已有的知識,你覺得順序應(yīng)該是怎么樣的
commonjs 同步 順序執(zhí)行
AMD 提前加載,不管是否調(diào)用模塊,先解析所有模塊 requirejs 速度快 有可能浪費(fèi)資源
CMD 提前加載,在真正需要使用(依賴)模塊時(shí)才解析該模塊 seajs 按需解析 性能比AMD差
15: 介紹一下閉包和閉包常用場景
閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù). 創(chuàng)建閉包常見方式,就是在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù).
應(yīng)用場景 設(shè)置私有變量和方法
不適合場景:返回閉包的函數(shù)是個(gè)非常大的函數(shù)
閉包的缺點(diǎn)就是常駐內(nèi)存,會(huì)增大內(nèi)存使用量,使用不當(dāng)很容易造成內(nèi)存泄露。
16: 為什么會(huì)出現(xiàn)閉包這種東西,解決了什么問題
受JavaScript鏈?zhǔn)阶饔糜蚪Y(jié)構(gòu)的影響,父級變量中無法訪問到子級的變量值,為了解決這個(gè)問題,才使用閉包這個(gè)概念
17: 介紹一下你所了解的作用域鏈,作用域鏈的盡頭是什么,為什么
每一個(gè)函數(shù)都有一個(gè)作用域,比如我們創(chuàng)建了一個(gè)函數(shù),函數(shù)里面又包含了一個(gè)函數(shù),那么現(xiàn)在 就有三個(gè)作用域,這樣就形成了一個(gè)作用域鏈。
作用域的特點(diǎn)就是,先在自己的變量范圍中查找,如果找不到,就會(huì)沿著作用域鏈往上找。
18: 一個(gè)Ajax建立的過程是怎樣的,主要用到哪些狀態(tài)碼
ajax:在不切換頁面的情況下完成異步的HTTP請求
(1)創(chuàng)建XMLHttpRequest對象,也就是創(chuàng)建一個(gè)異步調(diào)用對象.
(2)創(chuàng)建一個(gè)新的HTTP請求,并指定該HTTP請求的方法、URL及驗(yàn)證信息.
(3)設(shè)置響應(yīng)HTTP請求狀態(tài)變化的函數(shù).
(4)發(fā)送HTTP請求.
(5)獲取異步調(diào)用返回的數(shù)據(jù).
(6)使用JavaScript和DOM實(shí)現(xiàn)局部刷新.
var xmlHttp = new XMLHttpRequest();
xmlHttp.open('GET','demo.php','true');
xmlHttp.send()
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState === 4 & xmlHttp.status === 200){
}
}
//使用promise封裝
function getJSON(url) {
return new Promise(function(resolve, reject) {
var XHR = new XMLHttpRequest();
XHR.open('GET', url, true);
XHR.send();
XHR.onreadystatechange = function() {
if (XHR.readyState == 4) {
if (XHR.status == 200) {
try {
var response = JSON.parse(XHR.responseText);
resolve(response);
} catch (e) {
reject(e);
}
} else {
reject(new Error(XHR.statusText));
}
}
}
})
}
getJSON(url).then(res => console.log(res));
當(dāng)前狀態(tài)readystate
0 代表未初始化。 還沒有調(diào)用 open 方法
1 代表正在加載。 open 方法已被調(diào)用,但 send 方法還沒有被調(diào)用
2 代表已加載完畢。send 已被調(diào)用。請求已經(jīng)開始
3 代表交互中。服務(wù)器正在發(fā)送響應(yīng)
4 代表完成。響應(yīng)發(fā)送完畢
常用狀態(tài)碼status
404 沒找到頁面(not found)
403 禁止訪問(forbidden)
500 內(nèi)部服務(wù)器出錯(cuò)(internal service error)
200 一切正常(ok)
304 沒有被修改(not modified)(服務(wù)器返回304狀態(tài),表示源文件沒有被修改)
19: 說說你還知道的其他狀態(tài)碼,狀態(tài)碼的存在解決了什么問題
302/307 臨時(shí)重定向
301 永久重定向
借助狀態(tài)碼,用戶可以知道服務(wù)器端是正常處理了請求,還是出現(xiàn)了什么錯(cuò)誤
20: 知道語義化嗎?說說你理解的語義化,如果是你,平時(shí)會(huì)怎么做來保證語義化
像html5的新的標(biāo)簽header,footer,section等就是語義化
一方面,語義化就是讓計(jì)算機(jī)能夠快速的讀懂內(nèi)容,高效的處理信息,可以對搜索引擎更友好。
另一方面,便于與他人的協(xié)作,他人通過讀代碼就可以理解你網(wǎng)頁標(biāo)簽的意義。
21: 說說content-box和border-box,為什么看起來content-box更合理,但是還是經(jīng)常使用border-box
content-box 是W3C的標(biāo)準(zhǔn)盒模型 元素寬度=內(nèi)容寬度+padding+border
border-box 是ie的怪異盒模型 他的元素寬度等于內(nèi)容寬度 內(nèi)容寬度包含了padding和border
比如有時(shí)候在元素基礎(chǔ)上添加內(nèi)距padding或border會(huì)將布局撐破 但是使用border-box就可以輕松完成
22:介紹一下HTML5的新特性
新的DOCTYPE聲明 <!DOCTYPE html>
完全支持css3
video和audio
本地存儲(chǔ)
語義化標(biāo)簽
canvas
新事件 如ondrag onresize
23:對自己未來的規(guī)劃是怎樣的
對于剛畢業(yè)的人來說,前兩年是很重要的,先打好基礎(chǔ),多提升js能力。三至四年在提升JS能力的同時(shí),開始要往多方面發(fā)展,前端工程師遠(yuǎn)遠(yuǎn)不僅是JS而已。制作一個(gè)性能高、交互好、視覺美的頁面,需要從前端框架選型、架構(gòu)設(shè)計(jì)、構(gòu)建工具,到后端通信機(jī)制、設(shè)計(jì)與交互、網(wǎng)絡(luò)和瀏覽器優(yōu)化等各方面的知識。一專多長才是前端工程師的終極目標(biāo)。
24: 在一個(gè)UI李有10個(gè)li,實(shí)現(xiàn)點(diǎn)擊對應(yīng)的li,輸出對應(yīng)的下標(biāo)
var lis = querySelectorAll('li')
for(var i=0;i<10;i++){
lis[i].onclick = (function(a) {
return function() {
alert(a)
}
})(i)
}
事件委托
利用冒泡的原理,把事件加到父級上,觸發(fā)執(zhí)行效果。
1.可以大量節(jié)省內(nèi)存占用,減少事件注冊。
2.可以方便地動(dòng)態(tài)添加和修改元素,不需要因?yàn)樵氐母膭?dòng)而修改事件綁定。
var ul = document.querySelector('ul');
var list = document.querySelectorAll('ul li');
ul.addEventListener('click', function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElemnt;
for(var i = 0, len = list.length; i < len; i++){
if(list[i] == target){
alert(i + "----" + target.innerHTML);
}
}
});
25:實(shí)現(xiàn)三個(gè)DIV等分排布在一行(考察border-box)
1.設(shè)置border-box width33.3%
2.flexbox flex:1
26: 說說你知道JavaScript的內(nèi)存回收機(jī)制
垃圾回收器會(huì)每隔一段時(shí)間找出那些不再使用的內(nèi)存,然后為其釋放內(nèi)存。
一般使用標(biāo)記清除方法 當(dāng)變量進(jìn)入環(huán)境標(biāo)記為進(jìn)入環(huán)境,離開環(huán)境標(biāo)記為離開環(huán)境
還有引用計(jì)數(shù)方法
堆棧
stack為自動(dòng)分配的內(nèi)存空間,它由系統(tǒng)自動(dòng)釋放;而heap則是動(dòng)態(tài)分配的內(nèi)存,大小不定也不會(huì)自動(dòng)釋放。
基本數(shù)據(jù)類型存放在棧中
引用類型 存放在堆內(nèi)存中,首先從棧中獲得該對象的地址指針,然后再從堆內(nèi)存中取得所需的數(shù)據(jù)
27函數(shù)防抖和函數(shù)節(jié)流
函數(shù)防抖是指頻繁觸發(fā)的情況下,只有足夠的空閑時(shí)間,才執(zhí)行代碼一次
函數(shù)防抖的要點(diǎn),也是需要一個(gè)setTimeout來輔助實(shí)現(xiàn)。延遲執(zhí)行需要跑的代碼。
如果方法多次觸發(fā),則把上次記錄的延遲執(zhí)行代碼用clearTimeout清掉,重新開始。
如果計(jì)時(shí)完畢,沒有方法進(jìn)來訪問觸發(fā),則執(zhí)行代碼。
//函數(shù)防抖
var timer = false
document.getElementById("debounce").onScroll = function() {
clearTimeout(timer)
timer = setTimeout(function(){
console.log(‘函數(shù)防抖’)
}, 300)
}
\
1
2
3
4
5
6
7
8
函數(shù)節(jié)流是指一定時(shí)間內(nèi)js方法只跑一次
函數(shù)節(jié)流的要點(diǎn)是,聲明一個(gè)變量當(dāng)標(biāo)志位,記錄當(dāng)前代碼是否在執(zhí)行。
如果空閑,則可以正常觸發(fā)方法執(zhí)行。
如果代碼正在執(zhí)行,則取消這次方法執(zhí)行,直接return。
//函數(shù)節(jié)流
var canScroll = true;
document.getElementById('throttle').onScroll = function() {
if (!canScroll) {
return;
}
canScroll = false;
setTimeout(function(){
console.log('函數(shù)節(jié)流');
canScroll = true;
},300)
}
28:編程實(shí)現(xiàn)輸出一個(gè)數(shù)組中第N大的數(shù)據(jù)
自己寫唄
29.實(shí)現(xiàn)兩欄布局有哪些方法
*{margin:0; padding: 0;}
html,body{
height: 100%;/*高度百分百顯示*/
}
#left{
width: 300px;
height: 100%;
background-color: #ccc;
float: left;
}
#right{
height: 100%;
margin-left: 300px;
background-color: #eee;
*{margin:0; padding: 0;}
html,body{
height: 100%;/*高度百分百顯示*/
}
#left{
width: 300px;
height: 100%;
background-color: #ccc;
float: left;
}
#right{
height: 100%;
overflow:hidden;
background-color: #eee;
}
第二種方法,我利用的是創(chuàng)建一個(gè)新的BFC(塊級格式化上下文)來防止文字環(huán)繞的原理來實(shí)現(xiàn)的。BFC就是一個(gè)相對獨(dú)立的布局環(huán)境,它內(nèi)部元素的布局不受外面布局的影響。它可以通過以下任何一種方式來創(chuàng)建:
float 的值不為 none
position 的值不為 static 或者 relative
display 的值為 table-cell , table-caption , inline-block , flex , 或者 inline-flex 中的其中一個(gè)
overflow 的值不為 visible
第三種flex布局
自己想
30:設(shè)置width的flex元素,flex屬性值是多少
flex屬性是flex-grow, flex-shrink 和 flex-basis的簡寫
flex-grow屬性定義項(xiàng)目的放大比例,默認(rèn)為0
flex-shrink屬性定義了項(xiàng)目的縮小比例,默認(rèn)為1
flex-basis屬性定義了項(xiàng)目的固定空間
31get和post有什么不同
get是從服務(wù)器上獲取數(shù)據(jù),post是向服務(wù)器傳送數(shù)據(jù)
get請求可以將查詢字符串參數(shù)追加到url的末尾; post請求應(yīng)該把數(shù)據(jù)作為請求的主體提交.
get請求數(shù)據(jù)有大小限制;post沒有
post比get安全性更高
32:cookie和session有什么聯(lián)系和區(qū)別
cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務(wù)器上。
session比cookie更安全
單個(gè)cookie保存的數(shù)據(jù)不能超過4K,很多瀏覽器都限制一個(gè)站點(diǎn)最多保存20個(gè)cookie。
一般用cookie來存儲(chǔ)sessionid
33:判斷鏈表是否有環(huán)
使用追趕的方法,設(shè)定兩個(gè)指針slow、fast,從頭指針開始,每次分別前進(jìn)1步、2步。如存在環(huán),則兩者相遇;如不存在環(huán),fast遇到NULL退出。
34:輸出二叉樹的最小深度
判斷左子樹或右子樹是否為空,若左子樹為空,則返回右子樹的深度,反之返回左子樹的深度,如果都不為空,則返回左子樹和右子樹深度的最小值。
35: javaScript中的this是什么,有什么用,它的指向是什么
全局代碼中的this 是指向全局對象
作為對象的方法調(diào)用時(shí)指向調(diào)用這個(gè)函數(shù)的對象。
作為構(gòu)造函數(shù)指向新創(chuàng)建的對象
使用apply和call設(shè)置this
36:寫一個(gè)快速排序
var quickSort = function (arr){
if(arr.lenght <= 1) {
return arr;
}
var left = [];
var right = [];
var mid = arr.splice(Math.floor(arr.length/2), 1);
for(var i=0;i<arr.length;i++){
if(arr[i]<mid) {
left.push(arr[i]);
}
if(arr[i]>mid) {
right.push(arr[i]);
}
return quickSort(left).concat(mid, quickSort(right));
}
}
37怎么實(shí)現(xiàn)從一個(gè)DIV左上角到右下角的移動(dòng),有哪些方法,都怎么實(shí)現(xiàn)
改變left值為window寬度-div寬度 top值為window高度-div高度
jquery的animate方法
css3的transition
38: 簡單介紹一下promise,他解決了什么問題
Promise,就是一個(gè)對象,用來傳遞異步操作的消息。有三種狀態(tài):
Pending(進(jìn)行中)、Resolved(已完成,又稱 Fulfilled)和 Rejected(已失?。?。
有了 Promise 對象,就可以將異步操作以同步操作的流程表達(dá)出來,避免了層層嵌套的回調(diào)函數(shù)。
39: 寫一個(gè)組合繼承
var Super = function(name){
this.name = name;
}
Super.prototype.func1 = function() { console.log('func1'); }
var Sub = function(name,age) {
Super.call(this, name);
this.age = age;
}
Sub.prototype = new Super();
40:深拷貝方案有哪些,手寫一個(gè)深拷貝
var clone = function(v) {
var o = v.constructor === Array ? [] : {};
for (var i in v) {
o[i] = typeof v[i] === "Object" ? clone(v[i]) : v[i];
}
return o;
}
41:判斷數(shù)組有哪些方法
a instanceof Array
a.constructor == Array
Object.prototype.toString.call(a) == [Object Array]
42: 跨域通信有哪些方案,各有什么不同
JSONP:由于同源策略的限制,XmlHttpRequest只允許請求當(dāng)前源,script標(biāo)簽沒有同源限制
通過動(dòng)態(tài)<script>元素使用,使用時(shí)為src指定一個(gè)跨域url。回調(diào)函數(shù)處理JSON數(shù)據(jù) 兼容性好 不支持post
簡述原理與過程:首先在客戶端注冊一個(gè)callback, 然后把callback的名字傳給服務(wù)器。此時(shí),服務(wù)器先生成一個(gè)function , function 名字就是傳遞上來的參數(shù)。最后將 json 數(shù)據(jù)直接以入?yún)⒌姆绞?,放置?function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端??蛻舳藶g覽器,解析script標(biāo)簽,并執(zhí)行返回的 javascript 文檔,此時(shí)數(shù)據(jù)作為參數(shù),傳入到了客戶端預(yù)先定義好的 callback 函數(shù)里
<script>
var url = "http://localhost:8080/crcp/rcp/t99eidt/testjson.do?jsonp=callbackfunction";
var script = document.createElement('script');
script.setAttribute('src', url); //load javascript
document.getElementsByTagName('head')[0].appendChild(script);
//回調(diào)函數(shù)
function callbackfunction(data){
var html=JSON.stringify(data.RESULTSET);
alert(html);
}
</script>
cors:通過設(shè)置Access-Control-Allow-Origin來允許跨域 cors可用ajax發(fā)請求獲取數(shù)據(jù) 但是兼容性沒有jsonp好
43:多頁面通信有哪些方案,各有什么不同
localstorge在一個(gè)標(biāo)簽頁里被添加、修改或刪除時(shí),都會(huì)觸發(fā)一個(gè)storage事件,通過在另一個(gè)標(biāo)簽頁里監(jiān)聽storage事件,即可得到localstorge存儲(chǔ)的值,實(shí)現(xiàn)不同標(biāo)簽頁之間的通信。
settimeout+cookie
44:用Node實(shí)現(xiàn)一個(gè)用戶上傳文件的后臺(tái)服務(wù)應(yīng)該怎么做
multer模塊
45: XSS和CSRF攻擊
xss:比如在一個(gè)論壇發(fā)帖中發(fā)布一段惡意的JavaScript代碼就是腳本注入,如果這個(gè)代碼內(nèi)容有請求外部服務(wù)器,那么就叫做XSS
寫一個(gè)腳本將cookie發(fā)送到外部服務(wù)器這就是xss攻擊但是沒有發(fā)生csrf
防范:對輸入內(nèi)容做格式檢查 輸出的內(nèi)容進(jìn)行過濾或者轉(zhuǎn)譯
CSRF:又稱XSRF,冒充用戶發(fā)起請求(在用戶不知情的情況下),完成一些違背用戶意愿的請求 如惡意發(fā)帖,刪帖
比如在論壇發(fā)了一個(gè)刪帖的api鏈接 用戶點(diǎn)擊鏈接后把自己文章給刪了 這里就是csrf攻擊沒有發(fā)生xss
防范:驗(yàn)證碼 token 來源檢測
46:圣杯布局和雙飛翼布局
【圣杯布局】
html代碼中 middle部分首先要放在container的最前部分。然后是left,right
1.將三者都 float:left , 再加上一個(gè)position:relative (因?yàn)橄鄬Χㄎ缓竺鏁?huì)用到)
2.middle部分 width:100%占滿
3.此時(shí)middle占滿了,所以要把left拉到最左邊,使用margin-left:-100%
4.這時(shí)left拉回來了,但會(huì)覆蓋middle內(nèi)容的左端,要把middle內(nèi)容拉出來,所以在外圍container加上 padding:0 220px 0 200px
5.middle內(nèi)容拉回來了,但left也跟著過來了,所以要還原,就對left使用相對定位 left:-200px 同理,right也要相對定位還原 right:-220px
6.到這里大概就自適應(yīng)好了。如果想container高度保持一致可以給left middle right都加上min-height:130px
【雙飛翼布局】
前幾步都一樣 后邊把外圍padding和相對定位做法換成內(nèi)層margin
給middle增加一個(gè)內(nèi)層div-- middle-inner, 然后margin:0 220px 0 200px
47:offsetHeight, scrollHeight, clientHeight分別代表什么
clientHeight:包括內(nèi)容可見部分的高度,可見的padding;不包括border,水平方向的scrollbar,margin。
offsetHeight:包括內(nèi)容可見部分的高度,border,可見的padding,水平方向的scrollbar(如果存在);不包括margin。
scrollHeight:包括內(nèi)容的高度(可見與不可見),padding(可見與不可見);不包括border,margin。
48:垂直居中
單行行內(nèi)元素 1.可以設(shè)置padding-top,padding-bottom 2.將height和line-height設(shè)為相等
多行行內(nèi)元素 1.可以將元素轉(zhuǎn)為table樣式,再設(shè)置vertical-align:middle; 2.使用flex布局
塊級元素
已知高度絕對定位負(fù)邊距
未知高度transform: translateY(-50%);
flex布局
display: flex;
justify-content: center;
align-items: center;
49:transition的屬性值和應(yīng)用
屬性的名稱 過渡時(shí)間 時(shí)間曲線 延遲
50:rem和em的區(qū)別
em相對于父元素,rem相對于根元素
51:嚴(yán)格模式的特性
嚴(yán)格模式對Javascript的語法和行為,都做了一些改變。
全局變量必須顯式聲明。
對象不能有重名的屬性
函數(shù)必須聲明在頂層
消除Javascript語法的一些不合理、不嚴(yán)謹(jǐn)之處,減少一些怪異行為;
消除代碼運(yùn)行的一些不安全之處,保證代碼運(yùn)行的安全;
提高編譯器效率,增加運(yùn)行速度;
為未來新版本的Javascript做好鋪墊。
52:js的原型鏈,如何實(shí)現(xiàn)繼承?
function foo(){}
foo.prototype.z = 3;
var obj = new foo();
obj.x=1;
obj.y=2;
obj.x //1
obj.y //2
obj.z //3
53:圖片預(yù)加載和懶加載
預(yù)加載:
function loadImage(url, callback) {
var img = new Image();
img.src = url;
if (img.complete) { // 如果圖片已經(jīng)存在于瀏覽器緩存,直接調(diào)用回調(diào)函數(shù) 防止IE6不執(zhí)行onload BUG
callback.call(img);
return;
}
img.onload = function () {
callback.call(img);//將回調(diào)函數(shù)的this替換為Image對象
};
};
懶加載:
當(dāng)網(wǎng)頁滾動(dòng)的事件被觸發(fā) -> 執(zhí)行加載圖片操作 -> 判斷圖片是否在可視區(qū)域內(nèi) -> 在,則動(dòng)態(tài)將data-src的值賦予該圖片。
<script>
var aImages = document.getElementById("SB").getElementsByTagName('img'); //獲取id為SB的文檔內(nèi)所有的圖片
loadImg(aImages);
window.onscroll = function () { //滾動(dòng)條滾動(dòng)觸發(fā)
loadImg(aImages);
};
//getBoundingClientRect 是圖片懶加載的核心
function loadImg(arr) {
for (var i = 0, len = arr.length; i < len; i++) {
if (arr[i].getBoundingClientRect().top < document.documentElement.clientHeight && !arr[i].isLoad) {
arr[i].isLoad = true; //圖片顯示標(biāo)志位
//arr[i].style.cssText = "opacity: 0;";
(function (i) {
setTimeout(function () {
if (arr[i].dataset) { //兼容不支持data的瀏覽器
aftLoadImg(arr[i], arr[i].dataset.imgurl);
} else {
aftLoadImg(arr[i], arr[i].getAttribute("data-imgurl"));
}
arr[i].style.cssText = "transition: 1s; opacity: 1;" //相當(dāng)于fadein
}, 500)
})(i);
}
}
}
function aftLoadImg(obj, url) {
var oImg = new Image();
oImg.onload = function () {
obj.src = oImg.src; //下載完成后將該圖片賦給目標(biāo)obj目標(biāo)對象
}
oImg.src = url; //oImg對象先下載該圖像
}
</script>
54.輸入網(wǎng)址后到頁面展現(xiàn)的過程
通過dns解析獲取ip
tcp鏈接
客戶端發(fā)送http請求
tcp傳輸報(bào)文
服務(wù)器處理請求返回http報(bào)文
客戶端解析渲染頁面 (構(gòu)建DOM樹 –> 構(gòu)建渲染樹 –> 布局渲染樹:計(jì)算盒模型位置和大小 –> 繪制渲染樹)
55:UMD規(guī)范和ES6模塊化,Commonjs的對比
CommonJS是一個(gè)更偏向于服務(wù)器端的規(guī)范。用于NodeJS 是同步的
AMD是依賴前置的
CMD推崇依賴就近,延遲執(zhí)行??梢园涯愕囊蕾噷戇M(jìn)代碼的任意一行
AMD和CMD都是用difine和require,但是CMD標(biāo)準(zhǔn)傾向于在使用過程中提出依賴,就是不管代碼寫到哪突然發(fā)現(xiàn)需要依賴另一個(gè)模塊,那就在當(dāng)前代碼用require引入就可以了,規(guī)范會(huì)幫你搞定預(yù)加載,你隨便寫就可以了。但是AMD標(biāo)準(zhǔn)讓你必須提前在頭部依賴參數(shù)部分寫好(沒有寫好? 倒回去寫好咯)。這就是最明顯的區(qū)別。
UMD寫一個(gè)文件需要兼容不同的加載規(guī)范
ES6通過import、export實(shí)現(xiàn)模塊的輸入輸出。其中import命令用于輸入其他模塊提供的功能,export命令用于規(guī)定模塊的對外接口。
56:http請求頭
get post delete put head options trace connect
OPTIONS:返回服務(wù)器針對特定資源所支持的HTTP請求方法
57:nginx的好處?和node的比較
高并發(fā) 響應(yīng)快
區(qū)別不是很大,一個(gè)更專業(yè),一個(gè)更全面:
1.相似點(diǎn):
1.1異步非阻塞I/O, 事件驅(qū)動(dòng);
2.不同點(diǎn):
2.1Nginx 采用C編寫,更性能更高,但是它僅適合于做web服務(wù)器,用于反向代理或者負(fù)載均衡等服務(wù);Nginx背后的業(yè)務(wù)層編程思路很還是同步編程方式,例如PHP.
2.2NodeJs高性能平臺(tái),web服務(wù)只是其中一塊,NodeJs在處理業(yè)務(wù)層用的是JS編寫,采用的是異步編程方式和思維方式。
58.框架問題
什么是 MVVM , 和 MVC 是什么區(qū)別, 原理是什么?
mvc的界面和邏輯關(guān)聯(lián)緊密,數(shù)據(jù)直接從數(shù)據(jù)庫讀取,必須通過Controller來承上啟下,通信都是單向的。mvvm的View 和 ViewModel可以互相通信,界面數(shù)據(jù)從viewmodel中獲取。
父子組件怎么通信的?
vue:父組件是通過props屬性給子組件通信 在子組件里面emit,在父組件監(jiān)聽
react:props傳遞 父給子傳一個(gè)回調(diào)函數(shù) 將數(shù)據(jù)傳給父親處理
兄弟組件怎么通信的?
vuex 建立一個(gè)vue實(shí)例 emit觸發(fā)事件 on監(jiān)聽事件
redux 子A -> 父 -> 子B
生命周期有哪些, 怎么用?
beforecreated:el 和 data 并未初始化
created:完成了 data 數(shù)據(jù)的初始化,el沒有
beforeMount:完成了 el 和 data 初始化
mounted :完成掛載 updated;destroyed
react:初始化階段、運(yùn)行中階段、銷毀階段
初始化getDefaultProps()和getInitialState()初始化
componentWillMount() 在組件即將被渲染到頁面
render() 組件渲染
componentDidMount() 組件被渲染到頁面上,
運(yùn)行中shouldComponentUpdate() componentWillUpdate() render() componentDidUpdate()
銷毀componentWillUnmount()
59:清除浮動(dòng)
兩種原理:
1、利用clear屬性進(jìn)行清理
具體的實(shí)現(xiàn)原理是通過引入清除區(qū)域,這個(gè)相當(dāng)于加了一塊看不見的框把定義clear屬性的元素向下擠
父容器結(jié)尾插入空標(biāo)簽<div style="clear: both;"></div>
利用CSS偽元素:
.clearfix:after {
content: ".";
height: 0;
visibility: hidden;
display: block;
clear: both;
}
通過將這個(gè)類添加到父容器當(dāng)中,會(huì)在父容器的末尾增加了一個(gè)高度為0、具有清除屬性的、不可見的塊級元素。
2、將父容器形成BFC
BFC能清理浮動(dòng)主要運(yùn)用的是它的布局規(guī)則:
內(nèi)部的Box會(huì)在垂直方向,一個(gè)接一個(gè)地放置。
Box垂直方向的距離由margin決定。屬于同一個(gè)BFC的兩個(gè)相鄰Box的margin會(huì)發(fā)生重疊
每個(gè)元素的margin box的左邊, 與包含塊border box的左邊相接觸(對于從左往右的格式化,否則相反)。即使存在浮動(dòng)也是如此。
BFC的區(qū)域不會(huì)與float box重疊。
BFC就是頁面上的一個(gè)隔離的獨(dú)立容器,容器里面的子元素不會(huì)影響到外面的元素。反之也如此。
計(jì)算BFC的高度時(shí),浮動(dòng)元素也參與計(jì)算
浮動(dòng)清理利用的主要是第六條規(guī)則,只要將父容器觸發(fā)為BFC,就可以實(shí)現(xiàn)包含的效果。
那么觸發(fā)BFC有哪幾種方法?
根元素
float屬性不為none
position為absolute或fixed
display為inline-block, table-cell, table-caption, flex, inline-flex
overflow不為visible
60.前端性能優(yōu)化
1.減少http請求 使用sprite圖、合并js和css文件
2.使用cdn 將用戶安排在近的服務(wù)器上
3.使用緩存 緩存ajax 使用外部的css和js以便緩存 使用expire cach-control etag
4.壓縮資源 使用gzip壓縮js和css文件
5.代碼層面 避免使用樣式表達(dá)式、通配符選擇器、樣式放在頂部、腳本放在底部
61.事件模型和事件代理
事件三個(gè)階段:事件捕獲,目標(biāo),事件冒泡(低版本ie不支持捕獲階段)
w3c綁定事件target.addEventListener(event,handler,false)
解綁target.removeEventListener(eventType, handler, false)
ie綁定 target.attachEvent(on+event, handler)
解綁target.detachEvent("on"+eventType, handler)
事件代理優(yōu)點(diǎn):
可以大量節(jié)省內(nèi)存占用,減少事件注冊,比如在table上代理所有td的click事件就非常棒
可以實(shí)現(xiàn)當(dāng)新增子對象時(shí)無需再次對其綁定事件,對于動(dòng)態(tài)內(nèi)容部分尤為合適
bind和trigger實(shí)現(xiàn):
創(chuàng)建一個(gè)類或是匿名函數(shù),在bind和trigger函數(shù)外層作用域創(chuàng)建一個(gè)字典對象,用于存儲(chǔ)注冊的事件及響應(yīng)函數(shù)列表,bind時(shí),如果字典沒有則創(chuàng)建一個(gè),key是事件名稱,value是數(shù)組,里面放著當(dāng)前注冊的響應(yīng)函數(shù),如果字段中有,那么就直接push到數(shù)組即可。trigger時(shí)調(diào)出來依次觸發(fā)事件響應(yīng)函數(shù)即可。
function Emitter() {
this._listener = [];//_listener[自定義的事件名] = [所用執(zhí)行的匿名函數(shù)1, 所用執(zhí)行的匿名函數(shù)2]
}
//注冊事件
Emitter.prototype.bind = function(eventName, callback) {
var listener = this._listener[eventName] || [];//this._listener[eventName]沒有值則將listener定義為[](數(shù)組)。
listener.push(callback);
this._listener[eventName] = listener;
}
//觸發(fā)事件
Emitter.prototype.trigger = function(eventName) {
var args = Array.prototype.slice.apply(arguments).slice(1);//atgs為獲得除了eventName后面的參數(shù)(注冊事件的參數(shù))
var listener = this._listener[eventName];
if(!Array.isArray(listener)) return;//自定義事件名不存在
listener.forEach(function(callback) {
try {
callback.apply(this, args);
}catch(e) {
console.error(e);
}
})
}
62.將url的查詢參數(shù)解析成字典對象
function getQueryObject(url) {
url = url == null ? window.location.href : url;
var search = url.substring(url.lastIndexOf("?") + 1);
var obj = {};
var reg = /([^?&=]+)=([^?&=]*)/g;
search.replace(reg, function (rs, $1, $2) {
var name = decodeURIComponent($1);
var val = decodeURIComponent($2);
val = String(val);
obj[name] = val;
return rs;
});
return obj;
}
getQueryObject("http://www.cnblogs.com/leee/p/4456840.html?name=1&dd=ddd**")
Object {name: "1", dd: "ddd**"}
63.position的值, relative和absolute分別是相對于誰進(jìn)行定位的?
<1>、relative:相對定位,相對于自己本身在正常文檔流中的位置進(jìn)行定位。
<2>、absolute:生成絕對定位,相對于最近一級定位不為static的父元素進(jìn)行定位。
<3>、fixed: 生成絕對定位,相對于瀏覽器窗口或者frame進(jìn)行定位。
<4>、static:默認(rèn)值,沒有定位,元素出現(xiàn)在正常的文檔流中。
<5>、sticky:生成粘性定位的元素,容器的位置根據(jù)正常文檔流計(jì)算得出。
64.position:absolute和float屬性的異同?
共同點(diǎn):對內(nèi)聯(lián)元素設(shè)置float和absolute屬性,可以讓元素脫離文檔流,并且可以設(shè)置其寬高。
不同點(diǎn):float仍可占據(jù)位置,不會(huì)覆蓋在另一個(gè)BFC區(qū)域上,浮動(dòng)的框可以向左或向右移動(dòng),直到它的外邊緣碰到包含框或另一個(gè)浮動(dòng)框的邊框?yàn)橹?。absolute會(huì)覆蓋文檔流中的其他元素。
65.CSS 選擇符有哪些?哪些屬性可以繼承?優(yōu)先級算法如何計(jì)算? CSS3新增偽類有那些?
選擇符:
<1>、id選擇器(#myId);
<2>、類選擇器(.myClassName);
<3>、標(biāo)簽選擇器(div,p,h1);
<4>、相鄰選擇器(h1 + p);
<5>、子選擇器(ul > li);
<6>、后代選擇器(li a);
<7>、通配符選擇器(*);
<8>、屬性選擇器(button[disabled="true"]);
<9>、偽類選擇器(a:hover,li:nth-child);表示一種狀態(tài)
<10>、偽元素選擇器(li:before、:after,:first-letter,:first-line,:selecton);表示文檔某個(gè)部分的表現(xiàn)
優(yōu)先級:
!important > 行內(nèi)樣式(比重1000) > id(比重100) > class/屬性(比重10) > tag / 偽類(比重1);
偽類和偽元素區(qū)別:
1>、偽類:a:hover,li:nth-child;
2>、偽元素:li:before、:after,:first-letter,:first-line,:selecton;
65.兩個(gè)數(shù)組合并成一個(gè)數(shù)組排序返回
先依次比較兩個(gè)數(shù)組,按照小的就傳入新的數(shù)組。當(dāng)這次比較完之后可能有一個(gè)數(shù)組的長度很長,留下一些數(shù)組,然后在新數(shù)組的末尾插入即可。
<script>
functiongetRes(arr1, arr2){
var len1 = arr1.length,
len2 = arr2.length,
i = 0,
j = 0,
k = 0,
res = new Array(len1+len2);
while(i < len1 && j <len2){
res[k++] = arr[(arr[i] > arr[j]) ? j++ : i++];
}
While(i < len1) res[k++]= arr1[i++];
While(j < len2) res[k++]= arr2[j++];
Return res;
}
</script>
66.zepto和jquery區(qū)別
zepto比jquery體積小很多,移動(dòng)端的兼容性不需要要考慮很多,jquery中的很多功能都沒有。
width()和height()不一樣 解決用.css('width')
67.css3動(dòng)畫和jquery動(dòng)畫的差別
1.css3中的過渡和animation動(dòng)畫都是基于css實(shí)現(xiàn)機(jī)制的,屬于css范疇之內(nèi),并沒有涉及到任何語言操作。效率略高與jQuery中的animate()函數(shù),但兼容性很差。
2.jQuery中的animate()函數(shù)可以簡單的理解為css樣式的“逐幀動(dòng)畫”,是css樣式不同狀態(tài)的快速切換的結(jié)果。效率略低于css3動(dòng)畫執(zhí)行效率,但是兼容性好。?
68.如何解決ajax無法后退的問題
HTML5里引入了新的API,即:history.pushState, history.replaceState
可以通過pushState和replaceState接口操作瀏覽器歷史,并且改變當(dāng)前頁面的URL。
onpopstate監(jiān)聽后退
69.實(shí)現(xiàn)一個(gè)once函數(shù)
<script>
function test () {console.log('test')}
var once = function (fn) {
var isFirst = true;
return function () {
if (isFirst) {
isFirst = !isFirst;
fn();
}
};
};
var b = once(test);
b(); // 'test'
b(); // nothing
</script>
70.分域名請求圖片的原因和好處
瀏覽器的并發(fā)請求數(shù)目限制是針對同一域名的,超過限制數(shù)目的請求會(huì)被阻塞
瀏覽器并發(fā)請求有個(gè)數(shù)限制,分域名可以同時(shí)并發(fā)請求大量圖片
71.頁面的加載順序
html順序加載,其中js會(huì)阻塞后續(xù)dom和資源的加載,css不會(huì)阻塞dom和資源的加載但是會(huì)阻塞js的加載。
瀏覽器會(huì)使用prefetch對引用的資源提前下載
1.沒有 defer 或 async,瀏覽器會(huì)立即加載并執(zhí)行指定的腳本
2.有 async,加載和渲染后續(xù)文檔元素的過程將和 script.js 的加載與執(zhí)行并行進(jìn)行(下載異步,執(zhí)行同步,加載完就執(zhí)行)。
3.有 defer,加載后續(xù)文檔元素的過程將和 script.js 的加載并行進(jìn)行(異步),但是 script.js 的執(zhí)行要在所有元素解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成。
72.生成10個(gè)20-50之間的隨機(jī)數(shù),存在數(shù)組中,常見排序方法,數(shù)組亂序方法
var arr = [];
for(var i = 0;i<10;i++){
var num = Math.random()*30 + 20;
num = parseInt(num, 10);
arr.push(num);
}
arr.sort(function(a,b){
return 0.5 - Math.random();
})
73.計(jì)算機(jī)網(wǎng)絡(luò)的分層概述
tcp/ip模型:從下往上分別是鏈路層,網(wǎng)絡(luò)層,傳輸層,應(yīng)用層
osi模型:從下往上分別是物理層,鏈路層,網(wǎng)絡(luò)層,傳輸層,會(huì)話層,表示層,應(yīng)用層。
73.jscss緩存問題
瀏覽器緩存的意義在于提高了執(zhí)行效率,但是也隨之而來帶來了一些問題,導(dǎo)致修改了js、css,客戶端不能更新
都加上了一個(gè)時(shí)間戳作為版本號
<script type=”text/javascript” src=”{JS文件連接地址}?version=XXXXXXXX”></script>
74.setTimeout,setInterval,requestAnimationFrame之間的區(qū)別
setInterval如果函數(shù)執(zhí)行的時(shí)間很長的話,第二次的函數(shù)會(huì)放到隊(duì)列中,等函數(shù)執(zhí)行完再執(zhí)行第二次,導(dǎo)致時(shí)間間隔發(fā)生錯(cuò)誤。
而settimeout一定是在這個(gè)時(shí)間定時(shí)結(jié)束之后,它才會(huì)執(zhí)行
requestAnimationFrame是為了做動(dòng)畫專用的一個(gè)方法,這種方法對于dom節(jié)點(diǎn)的操作會(huì)比較頻繁。
75.webpack常用到哪些功能
>設(shè)置入口 設(shè)置輸出目 設(shè)置loader extract-text-webpack-plugin將css從js代碼中抽出并合并 處理圖片文字等功能 解析jsx解析bable
76.介紹sass
&定義變量 css嵌套 允許在代碼中使用算式 支持if判斷for循環(huán)
77.websocket和ajax輪詢
Websocket是HTML5中提出的新的協(xié)議,注意,這里是協(xié)議,可以實(shí)現(xiàn)客戶端與服務(wù)器端的通信,實(shí)現(xiàn)服務(wù)器的推送功能。
其優(yōu)點(diǎn)就是,只要建立一次連接,就可以連續(xù)不斷的得到服務(wù)器推送的消息,節(jié)省帶寬和服務(wù)器端的壓力。
ajax輪詢模擬長連接就是每個(gè)一段時(shí)間(0.5s)就向服務(wù)器發(fā)起ajax請求,查詢服務(wù)器端是否有數(shù)據(jù)更新
其缺點(diǎn)顯而易見,每次都要建立HTTP連接,即使需要傳輸?shù)臄?shù)據(jù)非常少,所以這樣很浪費(fèi)帶寬
78.tansition和margin的百分比根據(jù)什么計(jì)算
transition是相對于自身,margin相對于參照物
79.冒泡排序、快速排序、去重、查找字符串最多值
//冒泡排序
var bubbleSort = function(arr) {
for (var i = 0; i < arr.length-1; i++) {
for (var j = i+1; j < arr.length; j++) {
if (arr[i]>arr[j]) {
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return arr;
};
//快速排序
var quickSort = function(arr) {
if (arr.length <= 1) {
return arr;
}
var len = arr.length;
var midIndex = Math.floor(len/2);
var mid = arr.splice(midIndex,1);
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < mid) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat(mid,quickSort(right))
}
// 去重
var distinct = function(arr) {
var map = {};
var result = [];
for (var i = 0; i < arr.length; i++) {
if (!map[arr[i]]) {
map[arr[i]] = true;
result.push(arr[i]);
}
}
return result;
}
//查找字符串中最多的值
var search = function(str) {
var json = {};
var max = 0;
var char;
for (var i = 0; i < str.length; i++) {
if (!json[str[i]]) {
json[str[i]]=1;
} else {
json[str[i]]++;
}
}
console.log(json);
for(var i in json){
if(json[i]>max){
max = json[i];
char = i;
}
}
console.log(max, char);
}
80.函數(shù)組合繼承
原型繼承、構(gòu)造函數(shù)繼承、call aplly繼承
var Super = function(name){
this.name = name;
}
Super.prototype.func1 = function() { console.log('func1'); }
var Sub = function(name,age) {
Super.call(this, name);
this.age = age;
}
Sub.prototype = new Super();
81.事件綁定
var addEvent = function(e, type, handler, capture ) {
if (e.addEventListener) {
e.addEventListener(type, handler, capture);
} else if (e.attachEvent) {
e.attachEvent('on'+type, handler);
} else {
e['on'+type] = handler;
}
}
82.淺克隆和深度克隆
//淺克隆
function extendCopy(p) {
var c = {};
for (var i in p) {
c[i] = p[i];
}
c.uber = p;
return c;
}
//深度克隆
var clone = function(v) {
var o = v.constructor === Array ? [] : {};
for (var i in v) {
o[i] = typeof v[i] === "Object" ? clone(v[i]) : v[i];
}
return o;
}
83.實(shí)現(xiàn)一個(gè)秒針繞一點(diǎn)轉(zhuǎn)動(dòng)的效果
animation: move 60s infinite steps(60);
/*設(shè)置旋轉(zhuǎn)的中心點(diǎn)為中間底部*/
transform-origin: center bottom;
/*旋轉(zhuǎn)從0度到360度*/
@keyframes move {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
84.移動(dòng)端兼容問題
IOS移動(dòng)端click事件300ms的延遲響應(yīng)
一些情況下對非可點(diǎn)擊元素如(label,span)監(jiān)聽click事件,ios下不會(huì)觸發(fā),css增加cursor:pointer就搞定了
85.bootstrap的柵格系統(tǒng)如何實(shí)現(xiàn)的
box-sizing: border-box;
container row column設(shè)置百分比