1、v-model默認(rèn)的觸發(fā)條件是input事件,加了.lazy修飾符之后,v-model會在change事件觸發(fā)的時候去監(jiān)聽
2、:class 綁定變量 綁定對象 綁定一個數(shù)組 綁定三元表達(dá)式
:style 綁定變量 綁定對象 綁定函數(shù)返回值 綁定三元表達(dá)式
3、 組件中寫name選項(xiàng)有什么作用
- 項(xiàng)目使用keep-alive時,可搭配組件name進(jìn)行緩存過濾
- DOM做遞歸組件時需要調(diào)用自身name
- vue-devtools調(diào)試工具里顯示的組見名稱是由vue中組件name決定的
4、diff算法
(key的體現(xiàn):不設(shè)key,newCh和oldCh只會進(jìn)行頭尾兩端的相互比較,設(shè)key后,除了頭尾兩端的比較外,還會從用key生成的對象oldKeyToIdx中查找匹配的節(jié)點(diǎn),所以為節(jié)點(diǎn)設(shè)置key可以更高效的利用dom。)
diff的過程就是調(diào)用patch函數(shù),就像打補(bǔ)丁一樣修改真實(shí)dom。
function patch (oldVnode, vnode) {
if (sameVnode(oldVnode, vnode)) {
patchVnode(oldVnode, vnode)
} else {
const oEl = oldVnode.el
let parentEle = api.parentNode(oEl) //取得oldvnode.el的父節(jié)點(diǎn),parentEle是真實(shí)dom
createEle(vnode) //createEle(vnode)會為vnode創(chuàng)建它的真實(shí)dom,令vnode.el =真實(shí)dom
if (parentEle !== null) {
api.insertBefore(parentEle, vnode.el, api.nextSibling(oEl)) //parentEle將新的dom插入,移除舊的dom
api.removeChild(parentEle, oldVnode.el)
oldVnode = null
}
}
return vnode
function sameVnode (a, b) {
return (
a.key === b.key && // key值
a.tag === b.tag && // 標(biāo)簽名
a.isComment === b.isComment && // 是否為注釋節(jié)點(diǎn)
// 是否都定義了data,data包含一些具體信息,例如onclick , style
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b) // 當(dāng)標(biāo)簽是<input>的時候,type必須相同
)
}
如果兩個節(jié)點(diǎn)是一樣的,那么就深入檢查他們的子節(jié)點(diǎn)。如果兩個節(jié)點(diǎn)不一樣那就可以直接替換oldVnode:
當(dāng)我們確定兩個節(jié)點(diǎn)相同之后我們會對兩個節(jié)點(diǎn)執(zhí)行patchVnode方法:
當(dāng)兩個節(jié)點(diǎn)值得比較時
function patchVnode (oldVnode, vnode) {
const el = vnode.el = oldVnode.el
let i, oldCh = oldVnode.children, ch = vnode.children
if (oldVnode === vnode) return
if (oldVnode.text !== null && vnode.text !== null && oldVnode.text !== vnode.text) {
api.setTextContent(el, vnode.text)
}else {
updateEle(el, vnode, oldVnode)
if (oldCh && ch && oldCh !== ch) {
updateChildren(el, oldCh, ch)
}else if (ch){
createEle(vnode) //create el's children dom
}else if (oldCh){
api.removeChildren(el)
}
}
}
這個函數(shù)做了以下事情:
找到對應(yīng)的真實(shí)dom,稱為el
判斷Vnode和oldVnode是否指向同一個對象,如果是,那么直接return
如果他們都有文本節(jié)點(diǎn)并且不相等,那么將el的文本節(jié)點(diǎn)設(shè)置為Vnode的文本節(jié)點(diǎn)。
如果oldVnode有子節(jié)點(diǎn)而Vnode沒有,則刪除el的子節(jié)點(diǎn)
如果oldVnode沒有子節(jié)點(diǎn)而Vnode有,則將Vnode的子節(jié)點(diǎn)真實(shí)化之后添加到el
如果兩者都有子節(jié)點(diǎn),則執(zhí)行updateChildren函數(shù)比較子節(jié)點(diǎn),這一步很重要
對比當(dāng)前真實(shí)的DOM和虛擬DOM,在對比過程中直接更新真實(shí)DOM
只對比同一層級的變化
節(jié)點(diǎn)比較時有5中情況
- if (oldVnode === vnode),他們的引用一致,可以認(rèn)為沒有變化。
- if(oldVnode.text !== null && vnode.text !== null && oldVnode.text !== vnode.text),文本節(jié)點(diǎn)的比較,需要修改,則會調(diào)用Node.textContent = vnode.text。
- if( oldCh && ch && oldCh !== ch ), 兩個節(jié)點(diǎn)都有子節(jié)點(diǎn),而且它們不一樣,這樣我們會調(diào)用updateChildren函數(shù)比較子節(jié)點(diǎn),這是diff的核心,后邊會講到。
- else if (ch),只有新的節(jié)點(diǎn)有子節(jié)點(diǎn),調(diào)用createEle(vnode),vnode.el已經(jīng)引用了老的dom節(jié)點(diǎn),createEle函數(shù)會在老dom節(jié)點(diǎn)上添加子節(jié)點(diǎn)。
- else if (oldCh),新節(jié)點(diǎn)沒有子節(jié)點(diǎn),老節(jié)點(diǎn)有子節(jié)點(diǎn),直接刪除老節(jié)點(diǎn)。
首屏加載優(yōu)化
- 異步路由和異步加載
- 還有分屏加載, 按需加載, 延時加載圖片等, cdn, 域名拆分
- webpack壓縮HTML/CSS/JS,
- 首屏css單獨(dú)提取內(nèi)聯(lián),
- 關(guān)鍵資源Proload,
- 圖片:不縮放,使用webp、小圖片base64(3k大小,太大的話會增加css文件大小,Base64 跟 CSS 混在一起,大大增加了瀏覽器需要解析CSS樹的耗時。),iconfont,
- gzip,
dns-prefetch, - 靜態(tài)資源單獨(dú)域名,去掉cookie
- 將資源放到不同的域下:瀏覽器同時從一個域下載資源的數(shù)目有限(chrome為6個),增加域可以提高并行下載量
- 減少回流重繪
事件捕獲和事件冒泡
http://www.itdecent.cn/p/c88c15c6074c
封裝axios主要封裝
封裝處理配置(路徑、時間、token)、統(tǒng)一管理接口、錯誤處理、不同形式的請求、消息提示、loading等。
div水平垂直居中
- 使用flex布局
div.parent {
display: flex;
justify-content: center;
align-items: center;
}
}
- 子元素絕對定位
div.parent {
position: relative;
}
}
div.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
- 知道子元素高度的情況下
/* 或者 */
div.child {
width: 50px;
height: 10px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -25px;
margin-top: -5px;
}
}
/* 或 */
div.child {
width: 50px;
height: 10px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
}
div.parent {
display: grid;
}
}
div.child {
justify-self: center;
align-self: center;
}
}
div.parent {
font-size: 0;
text-align: center;
&::before {
content: "";
display: inline-block;
width: 0;
height: 100%;
vertical-align: middle;
}
}
}
div.child{
display: inline-block;
vertical-align: middle;
}
}
5
div.parent{
display:flex;
}
}
div.child{
margin:auto;
}
}
computed原理
在initComputed中遍歷每一個computed屬性,創(chuàng)建對應(yīng)的Watcher。在Watcher實(shí)例化過程中,計(jì)算computed屬性結(jié)果,會對依賴的data進(jìn)行取值,從而觸發(fā)data的getter進(jìn)行依賴收集,將當(dāng)前Watcher加入到訂閱者數(shù)組中。當(dāng)computed屬性依賴的data改變時,會觸發(fā)data的setter通知訂閱者更新,這個computed會重新計(jì)算。
淺拷貝是拷貝一層,深層次的對象級別的就拷貝引用;深拷貝是拷貝多層,每一級別的數(shù)據(jù)都會拷貝出來;
箭頭函數(shù)和普通函數(shù)的區(qū)別
1、箭頭函數(shù)是匿名函數(shù),不能作為構(gòu)造函數(shù),即不能使用new來創(chuàng)建對象
2、箭頭函數(shù)不能綁定arguments,需要用類似語法來實(shí)現(xiàn) (...a)=>{拿到的是一個數(shù)組}
3、箭頭函數(shù)沒有原型屬性
4、箭頭函數(shù)沒有自己的this
flex布局
flex-container有6個屬性,包括flex-direction、flex-wrap、flex-flow、justify-content、align-items、align-content
其中
1、flex-direction主要來定義主軸的方向(默認(rèn)我為row,還有row-reverse、column、column-reverse)
2、flex-wrap主要定義是否換行(默認(rèn)nowrap、wrap、wrap-reverse)
3、flex-flow是flex-direction和flex-wrap的集合
4、justify-content用來定義項(xiàng)目在主軸上的對齊方式(flex-start,flex-end,center,space-between,space-around(2倍),space-evenly(均分))
5、align-items用來定義項(xiàng)目在交叉軸上如何對齊(flex-start,flex-end,center,baseline,stretch(默認(rèn)值,如果item沒有高度則會拉伸至整個container高度))
baseline是以文本基線來對齊的(項(xiàng)目的第一行文字的基線對齊)
6、align-content決定了多行的flex-items在交叉軸上的對齊方式。
和justify-content類似,不過軸換成了交叉軸
每一個item上也有6個屬性,分別為order、flex-grow、flex-shrink、flex-basis、flex、align-self
(1)其中order定義每個item的排列順序,數(shù)值越小排列越靠前
(2)flex-grow定義項(xiàng)目的放大比例,默認(rèn)為0,即如果存在剩余空間也不放大。
flex-grow決定了items如何擴(kuò)展,當(dāng)flex container在主軸方向上有剩余size的時候flex-grow才會生效。
----若所有items的flex-grow總和sum超過1,每個flex item擴(kuò)展的size為剩余的sizeflex-grow/num
----若總和不超過1,每個item擴(kuò)展的size為剩余的sizeflex-grow
前端安全:
xss攻擊,sql注入,CSRF攻擊
前端性能優(yōu)化
(1)資源的合并于壓縮html壓縮,css壓縮,js壓縮與混亂,公共文件合并
(2)服務(wù)端開啟gzip
(3)懶加載 預(yù)加載
(4)緩存,分級緩存
200(from cache): 由expires / cache-control 控制。expires(http1.0有效)是絕對時間;cache-control(http1.1有效)是相對時間。兩者都存在時,cache-control 覆蓋 expires,只要沒有失效,瀏覽器只訪問自己的緩存。
304 : 由 last-modified / etag 控制。當(dāng)上一層失效時或用戶點(diǎn)擊refresh,F(xiàn)5時,瀏覽器就會發(fā)送請求給服務(wù)器,如果服務(wù)器端沒有變化,則返回304給瀏覽器。
200 :當(dāng)瀏覽器本身沒有緩存或者上一層失效時,或者用戶點(diǎn)擊了CTL + F5 時,瀏覽器直接去服務(wù)器下載最新數(shù)據(jù)。
url從輸入到呈現(xiàn)經(jīng)歷的步驟。(性能優(yōu)化)
1、瀏覽器查緩存,有直接返回,沒有則從服務(wù)器取。
2、解析協(xié)議,主機(jī),端口,path,開啟網(wǎng)絡(luò)線程
(每一個tab頁面可以看作是瀏覽器內(nèi)核進(jìn)程,然后這個進(jìn)程是多線程的,它有幾大類子線程)
- GUI線程
- JS引擎線程
- 事件觸發(fā)線程
- 定時器線程
- 網(wǎng)絡(luò)請求線程
3、組裝http報(bào)文
4、瀏覽器獲取主機(jī)ip地址(dns 瀏覽器、本機(jī)、hosts)
DNS Prefetch 是讓具有此屬性的域名不需要用戶點(diǎn)擊鏈接就在后臺解析,而域名解析和內(nèi)容載入是串行的網(wǎng)絡(luò)操作,所以這個方式能減少用戶的等待時間,提升用戶體驗(yàn) 。
5、拿到主機(jī)地址后,打開一個socket與主機(jī)建立三次握手
6、建立成功后發(fā)送http請求
7、服務(wù)器接收請求報(bào)文并解析。(若請求頭中包含緩存驗(yàn)證,如果命中則返回304狀態(tài)碼)
8、服務(wù)器將相應(yīng)報(bào)文返回瀏覽器
9、瀏覽器檢查報(bào)文頭中緩存信息,確認(rèn)是否緩存
10、如果是gzip則先解碼,后根據(jù)資源類型決定如何處理
11、解析html文檔。
構(gòu)建dom樹,
解析過程中遇到圖片、樣式表、js文件則啟動下載
構(gòu)建cssom樹
根據(jù)dom和cssom樹構(gòu)建渲染樹(從dom樹的根節(jié)點(diǎn)遍歷所有可見節(jié)點(diǎn))
for in和for of
for ... in 循環(huán)返回的值都是數(shù)據(jù)結(jié)構(gòu)的 鍵值名。
遍歷對象返回的對象的key值,遍歷數(shù)組返回的數(shù)組的下標(biāo)(key)。
for ... in 循環(huán)不僅可以遍歷數(shù)字鍵名,還會遍歷原型上的值和手動添加的其他鍵。如——例3
特別情況下, for ... in 循環(huán)會以任意的順序遍歷鍵名
總結(jié)一句: for in 循環(huán)特別適合遍歷對象。
for of 循環(huán)用來獲取一對鍵值對中的值,而 for in 獲取的是 鍵名
一個數(shù)據(jù)結(jié)構(gòu)只要部署了 Symbol.iterator 屬性, 就被視為具有 iterator接口, 就可以使用 for of循環(huán)。
例1這個對象,沒有 Symbol.iterator這個屬性,所以使用 for of會報(bào) obj is not iterable
for of 不同與 forEach, 它可以與 break、continue和return 配合使用,也就是說 for of 循環(huán)可以隨時退出循環(huán)。
提供了遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一接口
html全局屬性
clas contenteditable (h5新加) dir(元素中文字的方向) id hidden spellcheck (表明瀏覽器是否應(yīng)該對元素的內(nèi)容進(jìn)行拼寫檢查) style title
meta中viewpoint的作用
如果不定義viewpoint的話,頁面寬度以屏幕分辨率為基準(zhǔn),而設(shè)置以后可以根據(jù)設(shè)備寬度來調(diào)整頁面,達(dá)到適配終端大小的效果
css加載方式
1、外部樣式表 style link
2、內(nèi)部樣式style里寫樣式
3、@import引入
4、內(nèi)聯(lián)樣式,即直接在標(biāo)簽里寫
inline元素特點(diǎn)
inline元素的margin和padding屬性,水平方向的padding-left, padding-right, margin-left, margin-right都產(chǎn)生邊距效果;但豎直方向的padding-top, padding-bottom, margin-top, margin-bottom不會產(chǎn)生邊距效果。
Object.create()方法創(chuàng)建一個新對象,使用現(xiàn)有對象來提供新創(chuàng)建的對象的proto
document
document.ready 和 window.onload 的區(qū)別是:上面定義的document.ready方法在DOM樹加載完成后就會執(zhí)行,而window.onload是在頁面資源(比如圖片和媒體資源,它們的加載速度遠(yuǎn)慢于DOM的加載速度)加載完成之后才執(zhí)行。也就是說$(document).ready要比window.onload先執(zhí)行。
js繼承的6種方式
- 原型鏈繼承
function Person(name){
this.name = name
}
function Son(){
this.name = "son"
}
Son.prototype = new Person()
重點(diǎn):讓新實(shí)例的原型等于父類的實(shí)例。
特點(diǎn):1、實(shí)例可繼承的屬性有:實(shí)例的構(gòu)造函數(shù)的屬性,父類構(gòu)造函數(shù)屬性,父類原型的屬性。(新實(shí)例不會繼承父類實(shí)例的屬性?。?缺點(diǎn):1、新實(shí)例無法向父類構(gòu)造函數(shù)傳參。
2、繼承單一。
3、所有新實(shí)例都會共享父類實(shí)例的屬性。(原型上的屬性是共享的,一個實(shí)例修改了原型屬性,另一個實(shí)例的原型屬性也會被修改!)
- 借用構(gòu)造函數(shù)繼承
func Son(){
Person.call(this,'son2')
}
重點(diǎn):用.call()和.apply()將父類構(gòu)造函數(shù)引入子類函數(shù)(在子類函數(shù)中做了父類函數(shù)的自執(zhí)行(復(fù)制))
特點(diǎn):1、只繼承了父類構(gòu)造函數(shù)的屬性,沒有繼承父類原型的屬性。
2、解決了原型鏈繼承缺點(diǎn)1、2、3。
3、可以繼承多個構(gòu)造函數(shù)屬性(call多個)。
4、在子實(shí)例中可向父實(shí)例傳參。
缺點(diǎn):1、只能繼承父類構(gòu)造函數(shù)的屬性。
2、無法實(shí)現(xiàn)構(gòu)造函數(shù)的復(fù)用。(每次用每次都要重新調(diào)用)
3、每個新實(shí)例都有父類構(gòu)造函數(shù)的副本,臃腫。
- 組合繼承(組合原型鏈繼承和借用構(gòu)造函數(shù)繼承)(常用)
function Son(name){
Person.call(this, name)
}
Son.prototype = new Person()
重點(diǎn):結(jié)合了兩種模式的優(yōu)點(diǎn),傳參和復(fù)用
特點(diǎn):1、可以繼承父類原型上的屬性,可以傳參,可復(fù)用。
2、每個新實(shí)例引入的構(gòu)造函數(shù)屬性是私有的。
缺點(diǎn):調(diào)用了兩次父類構(gòu)造函數(shù)(耗內(nèi)存),子類的構(gòu)造函數(shù)會代替原型上的那個父類構(gòu)造函數(shù)。
- 最完美的繼承
function Parent4(){
this.name = "parent4";
this.colors = ["red","blue","yellow"];
}
Parent4.prototype.sex = "男";
Parent4.prototype.say = function(){console.log("Oh, My God!")}
function Child4(){
Parent4.call(this);
this.type = "child4";
}
Child4.prototype = Object.create(Parent4.prototype);
Child4.prototype.constructor = Child4;
//Object.create是一種創(chuàng)建對象的方式,它會創(chuàng)建一個中間對象
清除浮動
.clearfix:after,.clearfix:before{
content: "";
display: table;
}
.clearfix:after{
clear: both;
}
.clearfix:after{/偽元素是行內(nèi)元素 正常瀏覽器清除浮動方法/
content: "";
display: block;
height: 0;
clear:both;
visibility: hidden;
}
.clearfix{
zoom: 1;/ie6清除浮動的方式 號只有IE6-IE7執(zhí)行,其他瀏覽器不執(zhí)行/
}
typeof除了null以外都可以顯示正確的類型,對象和數(shù)組都返回object
instanceof主要來判斷引用類型,原理是根據(jù)原型鏈來查找。
除了undefined、null、false、NaN、''、0、-0以外的值都會被轉(zhuǎn)為true,包括所有的引用類型,即使是空的。
promise構(gòu)造函數(shù)內(nèi)的代碼是同步執(zhí)行的,之后的then或catch方式是異步執(zhí)行的。構(gòu)造函數(shù)接收兩個參數(shù),resolve和reject。
eventloop的理解
js的執(zhí)行機(jī)制簡單來說就是先執(zhí)行同步代碼,然后執(zhí)行異步代碼,而異步代碼里又分為宏任務(wù)代碼和微任務(wù)代碼,先執(zhí)行微任務(wù),然后執(zhí)行宏任務(wù)。
- 將所有js作為一個宏任務(wù),遇到同步代碼就執(zhí)行,然后開始分配任務(wù),遇到宏任務(wù)就把他們的回調(diào)分配到宏任務(wù)的隊(duì)列里,遇到微任務(wù)就把他們的回調(diào)分配到微任務(wù)的隊(duì)列里,然后開始執(zhí)行所有的微任務(wù)。
- 執(zhí)行微任務(wù)的過程還是遵循先同步然后分配異步任務(wù)的順序,微任務(wù)執(zhí)行完畢之后,一次eventloop的tick就完成了。接著挨個去執(zhí)行分配好的宏任務(wù),在每個宏任務(wù)里又先同步后異步分配任務(wù),完成下一次tick,循環(huán)往復(fù)
34、瀏覽器或元素的各種距離參數(shù)。
解決跨域
- jsonp
- 設(shè)置頭部Access-Control-Allow-Origin
===運(yùn)算符判斷相等的流程是怎樣的
- 如果兩個值不是相同類型,它們不相等
- 如果兩個值都是 null 或者都是 undefined,它們相等
- 如果兩個值都是布爾類型 true 或者都是 false,它們相等
- 如果其中有一個是NaN,它們不相等
- 如果都是數(shù)值型并且數(shù)值相等,他們相等, -0 等于 0
- 如果他們都是字符串并且在相同位置包含相同的 16 位值,他它們相等;如果在長度或者內(nèi)容上不等,它們不相等;兩個字符串顯示結(jié)果相同但是編碼不同==和===都認(rèn)為他們不相等
如果他們指向相同對象、數(shù)組、函數(shù),它們相等;如果指向不同對象,他們不相等
==運(yùn)算符判斷相等的流程是怎樣的
- 如果兩個值類型相同,按照===比較方法進(jìn)行比較
- 如果類型不同,使用如下規(guī)則進(jìn)行比較
- 如果其中一個值是 null,另一個是 undefined,它們相等
- 如果一個值是數(shù)字另一個是字符串,將字符串轉(zhuǎn)換為數(shù)字進(jìn)行比較
- 如果有布爾類型,將true 轉(zhuǎn)換為 1,false 轉(zhuǎn)換為 0,然后用==規(guī)則繼續(xù)比較
- 如果一個值是對象,另一個是數(shù)字或字符串,將對象轉(zhuǎn)換為原始值然后用==規(guī)則繼續(xù)比較
其他所有情況都認(rèn)為不相等(例如a = {} , a=="[object Object]"就返回true)
38、cookie 屬性有名,值,max-age,path, domain,secure;
進(jìn)行網(wǎng)站性能優(yōu)化
dns方面
1、減少dns查詢
2、DNS Prefetch 是讓具有此屬性的域名不需要用戶點(diǎn)擊鏈接就在后臺解析,而域名解析和內(nèi)容載入是串行的網(wǎng)絡(luò)操作,所以這個方式能減少用戶的等待時間,提升用戶體驗(yàn) 。content 方面
1.減少http請求(雪碧圖,小圖片base64)
2.組件懶加載
3.前后端進(jìn)行數(shù)據(jù)交互時盡量使用json格式,數(shù)據(jù)處理方便,資源偏小。server方面
1.添加 Expires 或者 Cache-Control(max-age、no-store、no-cache、public、private) 響應(yīng)頭
2.開啟gzip
3.避免空 src 的 img 標(biāo)簽(當(dāng) <link> 標(biāo)簽的 href 屬性為空,或 <script>、<img>、<iframe> 標(biāo)簽的 src 屬性為空時,瀏覽器在渲染的過程中仍會將 href 屬性或 src 屬性中的空內(nèi)容進(jìn)行加載,直至加載失敗,這樣就阻塞了頁面中其他資源的下載進(jìn)程,而且最終加載到的內(nèi)容是無效的,因此要盡量避免。)cookie方面
1、去除沒有必要的cookie,如果網(wǎng)頁不需要cookie就完全禁掉。
靜態(tài)資源和主頁面不同域,加載靜態(tài)資源的HTTP請求就不會帶上主頁面中的cookie等數(shù)據(jù),減少了數(shù)據(jù)傳輸量,節(jié)省流量,提升上傳效率。
2、將cookie的大小減到最小。
由于cookie在訪問對應(yīng)域名下的資源時都會通過HTTP請求發(fā)送到服務(wù)器,因此,減小cookie的大小,能減小HTTP請求報(bào)文的大小,提高響應(yīng)速度。
3、設(shè)置合適的過期時間,較長的過期時間可以提高響應(yīng)速度。
給cookie添加一個過期時間,則cookie信息將存儲到硬盤上,即使瀏覽器退出Cookie還會存在。只要Cookie未被清除且還在過期時間內(nèi),該Cookie就會在訪問對應(yīng)域名時發(fā)送給服務(wù)器。
4、通過使用不同的domain減少cookie的使用。
cookie在訪問對應(yīng)域名下的資源時都會通過HTTP請求發(fā)送到服務(wù)器,但在訪問一些資源,如js,css和圖片時,大多數(shù)情況下cookie是多余的,可以使用不同的domain來存儲這些靜態(tài)資源,這樣訪問這些資源時就不會發(fā)送多余的cookie,從而提高響應(yīng)速度。css
1.將樣式表放到頁面頂部
原理:
CSS的下載是按照其在文檔中出現(xiàn)的順序進(jìn)行的,所以很容易想到將不需立即使用的CSS,如彈出框CSS,放在底部,這似乎可以得到一個加載很快的頁面。然而這其實(shí)是錯誤的,IE8及以下瀏覽器的工作方式是:為了避免樣式變化導(dǎo)致頁面重繪or重排,會阻塞內(nèi)容呈現(xiàn),在所有CSS加載并解析完之前不會呈現(xiàn)內(nèi)容,導(dǎo)致整個瀏覽器顯示空白,出現(xiàn)“白屏”(瀏覽器呈現(xiàn)過程:先出現(xiàn)白屏,后出現(xiàn)文字,圖片,最后出現(xiàn)樣式),直到CSS加載完畢。若在網(wǎng)速非常慢的情況下,CSS下載時間會特別長,導(dǎo)致瀏覽器“白屏”的時間很長,用戶體驗(yàn)會非常差。
將CSS放在底部,頁面可以逐步呈現(xiàn),但在CSS下載并解析完畢后,已經(jīng)呈現(xiàn)的文字和圖片就要需要根據(jù)新的樣式重繪,這是一種不好的用戶體驗(yàn)。
2.不使用表達(dá)式
3.不使用@import
4.盡量避免回流。
引起回流包括
1).頁面渲染初始化
2).DOM結(jié)構(gòu)改變,比如刪除了某個節(jié)點(diǎn)
3).render樹變化,比如減少了padding
4).窗口resize
5).改變字體大小
優(yōu)化方案:
減少逐項(xiàng)更改樣式,最好一次性更改style,或者將樣式定義為class并一次性更新
避免循環(huán)操作dom,創(chuàng)建一個documentFragment或div,在它上面應(yīng)用所有DOM操作,最后再把它添加到window.document
避免多次讀取offset等屬性。無法避免則將它們緩存到變量
將復(fù)雜的元素絕對定位或固定定位,使得它脫離文檔流,否則回流代價(jià)會很高js
1.將腳本放到頁面底部
script全部放在head中會出現(xiàn)的問題:
在需要操作body中的某元素時,可能找不到該元素,因此,若要放在head中,一般需要綁定一個監(jiān)聽windows.οnlοad=function(){ ... },當(dāng)文檔全部解析完之后再執(zhí)行script代碼。
2.將 javascript 和 css 從外部引入
3.壓縮圖片方面
1.保證 favicon.ico 小并且可緩存
css
1.transform可以設(shè)置的屬性translate,translate3的,scale,rotate,skewX
2.CSS3新增了三個邊框?qū)傩?,分別是border-radius、box-shadow和border-image。border-radius可以創(chuàng)建圓角邊框,box-shadow可以為元素添加陰影,border-image可以使用圖片來繪制邊框。IE9+支持border-radius和box-shadow屬性。Firefox、Chrome以及Safari支持所有新的邊框?qū)傩浴?br>
3.css優(yōu)先級內(nèi)聯(lián)樣式 > ID 選擇器 > 類選擇器 = 屬性選擇器 = 偽類選擇器 > 元素(類型)選擇器 = 偽元素選擇器 !important 權(quán)重最高
4.字體單位
- px
px就是pixel像素的縮寫,相對長度單位,網(wǎng)頁設(shè)計(jì)常用的基本單位。像素px是相對于顯示器屏幕分辨率而言的 - em
em是相對長度單位。相對于當(dāng)前對象內(nèi)文本的字體尺寸(參考物是父元素的font-size)
如當(dāng)前父元素的字體尺寸未設(shè)置,則相對于瀏覽器的默認(rèn)字體尺寸
特點(diǎn):
1. em的值并不是固定的;
2. em會繼承父級元素的字體大小 - rem(移動端)
rem是CSS3新增的一個相對單位,rem是相對于HTML根元素的字體大?。╢ont-size)來計(jì)算的長度單位
如果你沒有設(shè)置html的字體大小,就會以瀏覽器默認(rèn)字體大小,一般是16px - vw、vh
vw、vh、vmax、vmin這四個單位都是基于視口
vw是相對視口(viewport)的寬度而定的,長度等于視口寬度的1/100
假如瀏覽器的寬度為200px,那么1vw就等于2px(200px/100)
vh是相對視口(viewport)的高度而定的,長度等于視口高度的1/100
假如瀏覽器的高度為500px,那么1vh就等于5px(500px/100)
vmin和vmax是相對于視口的高度和寬度兩者之間的最小值或最大值
5.box-sizing屬性用來控制元素的盒子模型的解析模式,默認(rèn)為content-box。
context-box:W3C的標(biāo)準(zhǔn)盒子模型,設(shè)置元素的height/width屬性指的是content部分的高/寬;border-box:IE傳統(tǒng)盒子模型。設(shè)置元素的height/width屬性指的是border + padding + content部分的高/寬。
6.偽類和偽元素
偽類:用于已有元素處于某種狀態(tài)時為其添加對應(yīng)的樣式,這個狀態(tài)是根據(jù)用戶行為而動態(tài)變化的。例如:當(dāng)用戶懸停在指定元素時,可以通過:hover來描述這個元素的狀態(tài),雖然它和一般css相似,可以為已有元素添加樣式,但是它只有處于DOM樹無法描述的狀態(tài)下才能為元素添加樣式,所以稱為偽類。
狀態(tài)偽類:
1 :link
選擇未訪問的鏈接
2 :visited
選擇已訪問的鏈接
3 :hover
選擇鼠標(biāo)指針浮動在其上的元素
4 :active
選擇活動的鏈接
5 :focus
選擇獲取焦點(diǎn)的輸入字段
偽元素:用于創(chuàng)建一些不在DOM樹中的元素,并為其添加樣式。例如,我們可以通過:before來在一個元素之前添加一些文本,并為這些文本添加樣式,雖然用戶可以看見這些文本,但是它實(shí)際上并不在DOM文檔中。
6::checked
其他:
遇到有defer屬性的script標(biāo)簽,瀏覽器繼續(xù)往下面解析頁面,且會并行下載script標(biāo)簽的外部js文件,解析完HTML頁面,再執(zhí)行剛下載的js腳本(在DOMContentLoaded事件觸發(fā)前執(zhí)行,即剛剛解析完</html>,且可保證執(zhí)行順序就是他們在頁面上的先后順序)
遇到有sync屬性的script標(biāo)簽,會繼續(xù)往下解析,并且同時另開進(jìn)程下載腳本,腳本下載完畢,瀏覽器停止解析,開始執(zhí)行腳本,執(zhí)行完畢后繼續(xù)往下解析
為什么移動端會產(chǎn)生1px問題呢?
因?yàn)閁I設(shè)計(jì)師在最初設(shè)計(jì)的時候使用的尺寸是按照640x960設(shè)計(jì)的,前端寫的時候是按照320x480寫的,寫1px(css),瀏覽器自動變成2px(真實(shí)像素)。
那么前端工程師為什么不能直接寫0.5px(css)呢?
因?yàn)樵诶习姹镜南到y(tǒng)里寫0.5px(css)的話,會被瀏覽器解讀為0px(css),就沒有邊框了。不過在新版的系統(tǒng)里,已經(jīng)開始逐漸支持0.5px(css)這種寫法。所以如果設(shè)計(jì)師在大圖上設(shè)計(jì)了一個1px(真實(shí)像素)的線的話,前端工程師直接除以2,寫0.5px(css)就好了。
設(shè)置viewpoint來解決<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
webpack常用loader和插件
loader 讓 webpack 能夠去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以將所有類型的文件轉(zhuǎn)換為 webpack 能夠處理的有效模塊,然后你就可以利用 webpack 的打包能力,對它們進(jìn)行處理。
這么說loaders負(fù)責(zé)的是處理源文件的如css、jsx,一次處理一個文件。而plugins并不是直接操作單個文件,它直接對整個構(gòu)建過程起作用
1、樣式解析
2、file-loader、url-loader
file-loader可以解析項(xiàng)目中的url引入(不僅限于css),根據(jù)我們的配置,將圖片拷貝到相應(yīng)的路徑,再根據(jù)我們的配置,修改打包后文件引用路徑,使之指向正確的文件。
url-loader 功能與 file-loader 相似,但是如果文件小于一個 指定的大小他可以返回一個 DataURL。
3、mini-css-extract-plugin將css提取為單獨(dú)的文件
4、uglify-webpack-plugin壓縮代碼
5、optimize-css-assets-webpack-plugin優(yōu)化壓縮css資源
6、HTMLWebpackPlugin,將style插入到html
其他:
vue大概流程
一、主要步驟
1.初始化
vue初始化init的過程包含生命周期、事件、props、methods、data、computed與watch等的初始化
其中最主要的兩個步驟是watch的初始化和data屬性的observer過程,兩個過程是實(shí)現(xiàn)響應(yīng)式和依賴收集
2.編譯
編譯是將template轉(zhuǎn)變?yōu)閞ender function 的過程,包括:解析/優(yōu)化/生成三個步驟
解析:template->AST(抽象語法樹)
優(yōu)化:標(biāo)記AST中的靜態(tài)(static)節(jié)點(diǎn)
生成:AST->render function
3.render function 執(zhí)行
render function 執(zhí)行后生成虛擬節(jié)點(diǎn)樹(VNode DOM Tree)
4.渲染展現(xiàn)頁面
二、依賴收集過程
整體的流程圖中render function 執(zhí)行開始的綠色箭頭指向的流程為依賴收集過程
1.render function 執(zhí)行中會依此調(diào)用使用到的data.attr的get方法
2.get方法調(diào)用Dep.add將Vue對象中的watch加入到attr.Dep數(shù)組里
3.整個頁面渲染完畢后,所有需要使用attr的組件Vue對象的watch都收集到attr.Dep,attr.Dep內(nèi)容即為template與data的依賴關(guān)系(attr是隨便起的一個組件名)
三、響應(yīng)式原理
整體流程圖中attr.set()執(zhí)行開始的紅色箭頭指向的流程為響應(yīng)式原理
1.對data.attr賦值即調(diào)用attr.set方法
2.attr.set會調(diào)用Dep.notify(),notify方法是依次執(zhí)行attr.Dep數(shù)組中watch對象的update方法
3.update()是重新渲染視圖的過程,中間生成的Vnode DOM Tree,供patch使用 (利用diff算法)
四、update中的patch
patch,是將update產(chǎn)生的New Vnode節(jié)點(diǎn)與上一次渲染的Old Vnode進(jìn)行對比的過程,最終只有對比后的差異節(jié)點(diǎn)才會被更新到視圖上,從而達(dá)到提高update性能的目的
hash router和history的區(qū)別:
hash模式url里面永遠(yuǎn)帶著#號,我們在開發(fā)當(dāng)中默認(rèn)使用這個模式。window.location.href
如果用戶考慮url的規(guī)范那么就需要使用history模式,因?yàn)閔istory模式?jīng)]有#號,是個正常的url適合推廣宣傳 history.pushState
功能也有區(qū)別,比如我們在開發(fā)app的時候有分享頁面,那么這個分享出去的頁面就是用vue或是react做的,
咱們把這個頁面分享到第三方的app里,有的app里面url是不允許帶有#號的,所以要將#號去除那么就要使用history模式
但是使用history模式還有一個問題就是,在訪問二級頁面的時候,做刷新操作,會出現(xiàn)404錯誤,那么就需要和后端人配合讓他配置一下apache或是nginx的url重定向,重定向到你的首頁路由上就ok啦。
偽類和偽元素
偽類的受體是文檔樹中已有的元素,而偽元素則創(chuàng)建了一個DOM外的元素
偽類用于添加元素的特殊效果,而偽元素則是添加元素的內(nèi)容
偽類使用的一個冒號,為元素使用兩個冒號
偽類更常用一些簡單的動畫或者交互的樣式,例如滑入滑出,而為偽元素更常用語字體圖標(biāo),清除浮動等
BFC
滿足下列條件之一就可以觸發(fā)BFC
1:根元素,即html元素
2:float的值不為none
3:overflow的值不為visible
4:display的值為inline-block、table-cell、table-caption
5:position的值為absolute或者fixed
CSS選擇器有哪些?哪些屬性可以繼承?CSS優(yōu)先級算法如何計(jì)算?
- id選擇器( # myid)
- 類選擇器(.myclassname)
- 標(biāo)簽(元素)選擇器(div, h1, p)
- 相鄰選擇器(h1 + p)
- 子選擇器(ul > li)
- 后代選擇器(li a)
- 通配符選擇器( * )
- 屬性選擇器(a[rel = "external"])
- 偽類選擇器(a:hover, li:nth-child)
偽元素選擇器、分組選擇器。
繼承性:
可繼承的樣式:font-size, font-family, color,ul,li,dl,dt,dd;
不可繼承的樣式:border, padding, margin, width, height
優(yōu)先級(就近原則):!important > [ id > class > tag ]
!important 比內(nèi)聯(lián)優(yōu)先級高
優(yōu)先級算法計(jì)算
優(yōu)先級就近原則,同權(quán)重情況下樣式定義最近者為準(zhǔn)
!important>id >class>tag
important比內(nèi)聯(lián)優(yōu)先級高
元素選擇符的權(quán)值:元素標(biāo)簽(派生選擇器):1,class選擇符:10,id選擇符:100,內(nèi)聯(lián)樣式權(quán)值最大,為1000
!important聲明的樣式優(yōu)先級最高,如果沖突再進(jìn)行計(jì)算。
如果優(yōu)先級相同,則選擇最后出現(xiàn)的樣式。
繼承得到的樣式的優(yōu)先級最低。
position
absolute
生成絕對定位的元素,相對于 static 定位以外的第一個父元素進(jìn)行定位。
元素的位置通過 "left", "top", "right" 以及 "bottom" 屬性進(jìn)行規(guī)定。
fixed
生成固定定位的元素,相對于瀏覽器窗口進(jìn)行定位。(老IE不支持)
元素的位置通過 "left", "top", "right" 以及 "bottom" 屬性進(jìn)行規(guī)定。
relative
生成相對定位的元素,相對于其正常位置進(jìn)行定位,不脫離文檔流。
因此,"left:20" 會向元素的 LEFT 位置添加 20 像素。
static 默認(rèn)值。沒有定位,元素出現(xiàn)在正常的文檔流中(忽略 top, bottom, left, right 或者 z-index 聲明)。
inherit 規(guī)定應(yīng)該從父元素繼承 position 屬性的值。
vue和react區(qū)別
設(shè)計(jì)思想
react
1 函數(shù)式思想,all in js ,jsx語法,js操控css
2 單項(xiàng)數(shù)據(jù)流
3 setState重新渲染
4 每當(dāng)應(yīng)用的狀態(tài)被改變時,全部子組件都會重新渲染。當(dāng)然,這可以通過shouldComponentUpdate這個生命周期方法來進(jìn)行控制,如果為true繼續(xù)渲染、false不渲染,但Vue將此視為默認(rèn)的優(yōu)化。
vue
1 響應(yīng)式思想,也就是基于數(shù)據(jù)可變的。把html、js、css、組合到一起,也可以通過標(biāo)簽引擎組合到一個頁面中
2 雙向綁定,每一個屬性都需要建立watch監(jiān)聽(頁面不用,涉及到組件更新的話需要)
3 Vue宣稱可以更快地計(jì)算出Virtual DOM的差異,這是由于它在渲染過程中,會跟蹤每一個組件的依賴關(guān)系,不需要重新渲染整個組件樹
兩者本質(zhì)的區(qū)別:模板和組件化的區(qū)別
Vue本質(zhì)是MVVM框架,由MVC發(fā)展而來;
React是前端組件化框架,由后端組件化發(fā)展而來;
Vue使用模板
React使用JSX
React本身就是組件化
Vue是在MVVM上擴(kuò)展的
共同點(diǎn):
都支持組件化,都是數(shù)據(jù)驅(qū)動視圖
ES6相關(guān)
let 聲明變量 (推薦)
特性
1、支持 塊作用域
2、不支持 JS預(yù)解析
3、不支持 重復(fù)聲明 (同域同名變量)
const 聲明常量
特性
1、let所有特性
2、聲明時必須賦值,否則報(bào)錯
3、定義常量后,再也不能更改值
解構(gòu)賦值
箭頭函數(shù)
導(dǎo)出語法
模板字符串(${name})
...展開運(yùn)算符,react大量用到
promise
瀏覽器緩存
強(qiáng)緩存通過Expires和Cache-Control兩種響應(yīng)頭實(shí)現(xiàn)
1、Expires
Expires是http1.0提出的一個表示資源過期時間的header,它描述的是一個絕對時間,由服務(wù)器返回。
Expires 受限于本地時間,如果修改了本地時間,可能會造成緩存失效
2、Cache-Control
Cache-Control 出現(xiàn)于 HTTP / 1.1,優(yōu)先級高于 Expires ,表示的是相對時間
Cache-Control: no-store才是真正的不緩存數(shù)據(jù)到本地
Cache-Control: no-cache代表使用協(xié)商緩存
Cache-Control: public可以被所有用戶緩存(多用戶共享),包括終端和CDN等中間代理服務(wù)器
Cache-Control: private只能被終端瀏覽器緩存(而且是私有緩存),不允許中繼緩存服務(wù)器進(jìn)行緩存
當(dāng)瀏覽器對某個資源的請求沒有命中強(qiáng)緩存,就會發(fā)一個請求到服務(wù)器,驗(yàn)證協(xié)商緩存是否命中,如果協(xié)商緩存命中,請求響應(yīng)返回的http狀態(tài)為304并且會顯示一個Not Modified的字符串
協(xié)商緩存是利用的是【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】這兩對Header來管理的
Last-Modified 表示本地文件最后修改日期,瀏覽器會在request header加上If-Modified-Since(上次返回的Last-Modified的值),詢問服務(wù)器在該日期后資源是否有更新,有更新的話就會將新的資源發(fā)送回來
但是如果在本地打開緩存文件,就會造成 Last-Modified 被修改,所以在 HTTP / 1.1 出現(xiàn)了 ETag
Max-Age相比Expires?
Expires使用的是服務(wù)器端的時間
但是有時候會有這樣一種情況-客戶端時間和服務(wù)端不同步
那這樣,可能就會出問題了,造成了瀏覽器本地的緩存無用或者一直無法過期
所以一般http1.1后不推薦使用Expires
而Max-Age使用的是客戶端本地時間的計(jì)算,因此不會有這個問題
因此推薦使用Max-Age。
注意,如果同時啟用了Cache-Control與Expires,Cache-Control優(yōu)先級高。
使用閉包的注意點(diǎn)
1)由于閉包會使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會造成網(wǎng)頁的性能問題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
2)閉包會在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當(dāng)作對象(object)使用,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。
防抖節(jié)流(函數(shù)防抖是某一段時間內(nèi)只執(zhí)行一次,而函數(shù)節(jié)流是間隔時間執(zhí)行。)
防抖:任務(wù)頻繁觸發(fā)的情況下,只有任務(wù)觸發(fā)的間隔超過指定間隔的時候,任務(wù)才會執(zhí)行。
應(yīng)用:
-輸入框聯(lián)想,以防不停的發(fā)http請求
節(jié)流:
可以將一些事件降低觸發(fā)頻率。比如懶加載時要監(jiān)聽計(jì)算滾動條的位置,但不必每次滑動都觸發(fā),可以降低計(jì)算的頻率,而不必去浪費(fèi)資源;另外還有做商品預(yù)覽圖的放大鏡效果時,不必每次鼠標(biāo)移動都計(jì)算位置。