HTML部分
你是如何理解 HTML 語義化的?
HTML語義化就是使用合適的標(biāo)簽書寫合適的內(nèi)容目溉,避免使用過多無意義的標(biāo)簽明肮,例如div
。舉例來說:段落使用p標(biāo)簽缭付,標(biāo)題使用h1-h6柿估,連接使用a標(biāo)簽,動畫使用canvas等陷猫。HTML語義化可以便于搜索引擎更好的解析代碼秫舌,也利于瀏覽器爬蟲獲得更多的信息,并且對團(tuán)隊(duì)的合作開發(fā)和維護(hù)也更有利绣檬。
meta viewport 是做什么用的足陨,怎么寫?
針對移動端優(yōu)化娇未,在手機(jī)上墨缘,不想讓頁面縮放,不采用媒體查詢零抬,應(yīng)使用meta vieport镊讼。Viewport 就是瀏覽器窗口,它不是一個 HTML 結(jié)構(gòu)平夜,因而不能通過 CSS 去改變它的形態(tài)蝶棋。
<meta name=”viewport” content=”width=device-width, initial-scale=1, maximum-scale=1 minimum-scale=1 user-scalable=no”>
- width: 控制視口的寬度,
- device-width:表示縮放為100%時忽妒,以css像素計(jì)量的屏幕寬度
- initial-scale:控制頁面最初加載時的縮放等級
- minimum-scale:允許用戶的最小縮放值玩裙,為一個數(shù)字,可以帶小數(shù)
- maximum-scale:允許用戶的最大縮放值锰扶,為一個數(shù)字,可以帶小數(shù)
- user-scalable:是否允許用戶縮放,
瀏覽器會擴(kuò)展視口(而不是放大頁面)來適應(yīng)屏幕
你用過哪些 HTML 5 標(biāo)簽寝受?
-
section
:定義文檔中的一個章節(jié) -
header
:定義頁面和文章的頭部 -
footer
:定義文章的底部 -
main
:定義文章的主要內(nèi)容 -
aside
:定義側(cè)邊欄內(nèi)容 -
canvas
:繪制圖形
<canvas id = "canvas" width="150" height="150"></canvas>
//width和height已經(jīng)限制了canvas 的長度和寬度坷牛,并且width和height是HTML標(biāo)簽屬性,
//不是使用CSS設(shè)置的很澄。使用css對width和height進(jìn)行設(shè)置京闰,只是拉伸了canvas的長寬,
//并不是真的修改了.
const canvas = document.getElementById('canvas')
//獲取2d渲染上下文
const ctx = canvas.getContext('2d')
//填充
ctx.fillStyle = "red"
//畫矩形
ctx.fillRect(10,10,3000,3000)
//上面限制了canvas的跨寬高颜及,所以3000,3000最大只能為150-10,150-10
-
video
:用于在文檔中嵌入媒體播放器,用于支持當(dāng)前文檔內(nèi)的視頻播放蹂楣。
<video controls>
<source src="myVideo.mp4" type="video/mp4">
<source src="myVideo.webm" type="video/webm">
<p>Your browser doesn't support HTML5 video. Here is
a <a href="myVideo.mp4">link to the video</a> instead.</p>
</video>
-
audio
:用于在文檔中表示多個音頻內(nèi)容俏站。
//使用source元素
<audio controls="controls">
Your browser does not support the <code>audio</code> element.
<source src="foo.wav" type="audio/wav">
</audio>
//不適用source元素
<audio src="http://developer.mozilla.org/@api/deki/files/2926/=AudioTest_(1).ogg" autoplay>
Your browser does not support the <code>audio</code> element.
</audio>
-
touchstart
事件,touchmove
事件,touchend
事件
H5 是什么痊土?
H5表示微信等移動端的解決方案肄扎。這個解決方案包括HTML5的新特性,例如audio赁酝,canvas番枚,拖曳特性尿孔,本地存儲等。也包括盒模型,絕對定位等一系列的前端知識呈昔。H5特指基于HTML5技術(shù)的交互網(wǎng)頁應(yīng)用,以商業(yè)用途為主削咆。
H5動畫口芍,微信H5
HTML5 跨平臺性,更有效的數(shù)據(jù)推送菩收,本地存儲梨睁,無插件播放視頻audio,圖像動畫canvas
HTML5新特性包括哪些坛梁?
- 語義化更好的標(biāo)簽
1. 結(jié)構(gòu)標(biāo)簽:article而姐,header,nav划咐,footer拴念,aside,section
2. 其他元素:video褐缠,audio政鼠,canvas,menu队魏,meter公般,time
- 廢除了一些部分瀏覽器支持的元素,以及對頁面產(chǎn)生負(fù)面影響的元素胡桨。html5支持iframe
- 新增了一些API官帘,
- canvas
獲取canvas的上下文對象,利用該上下文的繪圖功能進(jìn)行繪制
let ctx = canvas.getContext('2d')
- Svg是html5的另一種圖形功能昧谊,是一種矢量圖形刽虹,是一種文件格式,有自己的API
<svg height = "100" width = "100">
<circle cx = "50" cy = "50" r = "50"></circle>
</svg>
- 音頻和視頻(video和audio),瀏覽器原生支持呢诬,不需要在安裝涌哲。媒體元素也向web頁面提供了通用胖缤,集成可腳本化的API
- XMLHttpRequest Level2:改進(jìn)了XMLHttpRequest和進(jìn)度事件,實(shí)現(xiàn)了使用CORS實(shí)現(xiàn)XMLHttpRequest阀圾,跨源請求包含一個Origin 頭部哪廓,他為HTTP提供了請求的頭部信息。
- WebSockets:要連接遠(yuǎn)程主機(jī)初烘,只需新建一個WebSocket實(shí)例涡真,提供希望連接的對端URL。
- Web Storage API:sessionStorage(保存在session中账月,瀏覽器關(guān)閉综膀,數(shù)據(jù)消失)、localStorage(保存在客戶端本地局齿,除非手動刪除剧劝,否則一直保存)
- Web Workers:可以讓應(yīng)用程序具有處理后臺的能力,對于多線程的支持非常好抓歼,但是它不能直接訪問web頁面和DOMapi讥此。
- 拖放API:draggable屬性、拖放事件(dragstart谣妻、drag萄喳、dragenter、dragleave蹋半、dragover他巨、drap、dragend)减江、dataTransfer對象
- 新表單特性和函數(shù):placeholder染突、autocomplete、autofocus辈灼、spellcheck份企、list特性、datalist元素巡莹、min和max司志、step、required
Label標(biāo)簽的 作用是什么降宅?
Label表情通常寫在form表單內(nèi)骂远,通常關(guān)聯(lián)一個控件
- 語法
<label for = "username" accesskey = "N">
<input id = "username" type = "text">
</lbael>
- 含義
for屬性:表示這個label標(biāo)簽是為了那個控件服務(wù)的,通常對應(yīng)input標(biāo)簽的ID或Name腰根,當(dāng)點(diǎn)擊Label標(biāo)簽時激才,所綁定的空間元素將獲得焦點(diǎn),點(diǎn)擊label所包裹的內(nèi)容,自動指向for指定的Id 或Name贸营。
accesskey屬性:定義了訪問這個空間的熱鍵( 所設(shè)置的快捷鍵不能與瀏覽器的快捷鍵沖突,否則將優(yōu)先激活瀏覽器的快捷鍵)
CSS部分
兩種盒模型分別說一下
- 盒模型: 內(nèi)容(content)岩睁、填充(padding)钞脂、邊界(margin)、 邊框(border)捕儒;
- IE盒模型: width= content+ padding + border
- W3C標(biāo)準(zhǔn)盒模型: width=content
box-sizing: content-box ;標(biāo)準(zhǔn)盒模型 (默認(rèn))
bo-sizing:border-box; IE盒模型
- 平時使用border box冰啃,因?yàn)楦糜谩R驗(yàn)槲覀兊木W(wǎng)頁逐漸從固定尺寸轉(zhuǎn)變?yōu)槭褂冒俜直葋碜赃m應(yīng)尺寸刘莹,當(dāng)一個盒子內(nèi)的兩個內(nèi)容有padding的時候阎毅,使用content-box計(jì)算起來就比較麻煩,此時使用border-box的優(yōu)勢就體現(xiàn)了点弯。
如何垂直居中扇调?
- table自帶功能
- 100%高度的after before 加上line block
- div裝成table
- margin-top: -50%
- translate:-50%
- abslute margin auto
- flex
flex布局怎么用,常用屬性有哪些抢肛?
- flex布局是一維的布局狼钮。
-
display:flex
:容易變成flex容器,容器內(nèi)的直接子元素為flex元素 -
flex-direction
:定義主軸 row,row-reverse,column,column-reverse -
flex-wrap:wrap
:實(shí)現(xiàn)多行效果捡絮。 -
flex-frow
:為flex-direction
和flex-wrap:wrap
的縮寫 -
flex-grow
:flex-grow屬性是處理flex元素在主軸上增加空間的問題 -
flex-shrink
屬性是處理flex元素收縮的問題熬芜。 -
align-items
: 屬性可以使元素在交叉軸方向?qū)R。 -
justify-content
:屬性可以使元素在主軸方向?qū)R福稳。
BFC 是什么涎拉?
- 推薦文章CSS-BFC相關(guān)知識
- 功能
- 清楚浮動,父元素設(shè)置
overflow:hidden / float:left
- 實(shí)現(xiàn)左右布局的圆,左邊元素
float: left,width: 100px;
右邊元素overflow: auto
- FC會阻止垂直(父子)的外邊距折疊:只要把父元素設(shè)置為BFC就可以了鼓拧。
- 可以觸發(fā)BFC
- 浮動元素(元素的 float 不是 none)
- 絕對定位元素(元素的 position 為 absolute 或 fixed)
- 行內(nèi)塊元素
- overflow 值不為 visible 的塊元素
- 彈性元素(display為 flex 或 inline-flex元素的直接子元素)
CSS 選擇器優(yōu)先級
- 越具體優(yōu)先級越高
- 后面的會覆蓋前面的
- !important優(yōu)先級最高,但不建議經(jīng)常使用
清除浮動說一下
.clearfix:after {
display: block;
content: '';
clear: both;
}
//IE兼容
.clearfix{
zoom: 1; /* IE 兼容*/
}
響應(yīng)式布局
- 響應(yīng)式布局指的是同一頁面在不同的屏幕有不同的布局略板。
- 響應(yīng)式布局與自適應(yīng)布局的區(qū)別:
響應(yīng)式布局只有一個頁面毁枯,根據(jù)視口分辨率的不同,做不通的代碼代理叮称,之后顯示相應(yīng)的內(nèi)容和布局种玛,自適應(yīng)布局,有很多頁面瓤檐,根據(jù)視口分辨率的不同赂韵,判斷是Pc端還是手機(jī)端等,之后返回一套完成的頁面用于展示挠蛉。 - 響應(yīng)式布局的實(shí)現(xiàn)方案
- 媒體查詢@media + px:可以針對不同的媒體類型寫對應(yīng)的樣式祭示,當(dāng)重置瀏覽器窗口大小的過程中,頁面會根據(jù)瀏覽器的寬度和高度渲染頁面谴古。
判斷移動優(yōu)先還是PC優(yōu)先
因?yàn)楹竺娴臉邮綍采w前面的樣式质涛,
移動優(yōu)先應(yīng)使用min-width
PC優(yōu)先稠歉,應(yīng)使用max-width
- 百分比布局
通過百分比單位,可以使瀏覽器組件中的寬高隨著瀏覽器的寬高的變化而變化汇陆,從而實(shí)現(xiàn)響應(yīng)式布局怒炸。 - rem布局
rem 是css3新增的屬性,并且移動端的支持度很高毡代,rem 的單位是相對于根元素html的font-size來確定的阅羹。根元素的font-size提供了一個基礎(chǔ),當(dāng)頁面的size發(fā)生變化的時候教寂,只要更改font-size即可捏鱼,那么依賴font-size的rem 就自動變化。
rem 布局的缺點(diǎn):在響應(yīng)式布局中酪耕,必須通過js來動態(tài)控制根元素font-size的大小导梆,也就是說css樣式和js代碼有一定的耦合性,且必須將改變font-size的代碼放在css樣式之前 - 視口單位
vw:表示相對于視圖窗口的寬度迂烁。vh:表示相對于視圖窗口的高度.
依賴視口大小而自動縮放问潭,無論視口過大還是過小,它也隨著時候過大或者過小婚被,失去了最大最小寬度的限制.可以結(jié)合rem - 圖片響應(yīng)式:圖片能夠隨著頁面的大小進(jìn)行縮放
max-width:100%; height: auto
不用width,是因?yàn)閣idth無法進(jìn)行圖片的自適應(yīng)
使用srcset
<img srcset="photo_w350.jpg 1x, photo_w640.jpg 2x" src="photo_w350.jpg" alt="">
- 媒體查詢需要注意點(diǎn)
設(shè)置viewport
媒體查詢
字體的適配(字體單位)
百分比布局
圖片的適配(圖片的響應(yīng)式)
結(jié)合flex狡忙,grid,BFC址芯,柵格系統(tǒng)等已經(jīng)成型的方案
:before和:after的區(qū)別是什么灾茁?
- 他們都是偽類元素
- :before在元素渲染邏輯頭部添加信息
- :after在元素渲染邏輯后面添加信息
- 并且他們添加的信息不會對頁面結(jié)構(gòu)造成影響
你用過哪些偽類?
- a標(biāo)簽相關(guān)偽類
a:link {color:#FF0000;} /* 未訪問的鏈接 */
a:visited {color:#00FF00;} /* 已訪問的鏈接 */
a:hover {color:#FF00FF;} /* 鼠標(biāo)劃過鏈接 */
a:active {color:#0000FF;} /* 已選中的鏈接 */
- :focus
- :first-child
- :first-of-type
- :last-child
animation對應(yīng)的屬性
- animation屬性用來指定一組或多組動畫谷炸,之間用逗號分隔北专。
- animation-name: 屬性指定應(yīng)用的一系列動畫,每個名稱代表一個由@keyframes定義的動畫序列旬陡。
- animation-duration: 性指定一個動畫周期的時長拓颓。
- animation-timing-function:
屬性定義CSS動畫在每一動畫周期中執(zhí)行的節(jié)奏。
可能值為一或多個<timing-function>
- animation-delay:屬性定義動畫于何時開始描孟,即從動畫應(yīng)用在元素上到動畫開始的這段時間的長度驶睦。
- animation-itaration-count:定義動畫在結(jié)束前運(yùn)行的次數(shù) 可以是1次 無限循環(huán).
- animation-direction:屬性指示動畫是否反向播放,它通常在簡寫屬性
animation
中設(shè)定 - animation-fill-mode:設(shè)置CSS動畫在執(zhí)行之前和之后如何將樣式應(yīng)用于其目標(biāo)匿醒。
- animation-play-state:屬性定義一個動畫是否運(yùn)行或者暫停场航。可以通過查詢它來確定動畫是否正在運(yùn)行廉羔。另外溉痢,它的值可以被設(shè)置為暫停和恢復(fù)的動畫的重放。
animation:none duration timig-function delay iteration-count direction
px em rem vh vw的區(qū)別?
- rem是相對于根元素html的font-size計(jì)算大小的孩饼。
- em是相對于父元素的font-size計(jì)算大小的髓削。
- vw:表示相對于視圖窗口的寬度
- vh:表示相對于視圖窗口的高度
- px:像素單位,顯示像素的基本單位
原生 JS
ES 6 語法知道哪些镀娶,分別怎么用蔬螟?
var let const 區(qū)別
- var 存在變量提升,可以聲明寫在下面汽畴,使用寫在上面。此時JS 只有函數(shù)作用域和全局作用域
- let 使JS 存在塊級作用域耸序,必須先聲明在使用忍些,(存在暫時性死區(qū),即在聲明之前使用是不可以的坎怪。)let 更適合和for結(jié)合使用罢坝,每次都會生成一個新的塊級作用域。
- let 不允許重復(fù)聲明搅窿,但允許重復(fù)賦值,
let a = 1,a=2
可以嘁酿,let a = 1,let a = 2
不可以. - const 只有一次聲明和賦值的機(jī)會,不允許重復(fù)聲明及賦值.
箭頭函數(shù)
- 箭頭函數(shù)只能做賦值男应,不能做聲明
let a = (x,y) => {return x + y}
- 函數(shù)只有在調(diào)用的時候闹司,才能確定
this
的值,箭頭函數(shù)可以保證沐飘,函數(shù)內(nèi)的this
與函數(shù)外的this
值相等. - 箭頭函數(shù)沒有
this
的概念游桩,箭頭函數(shù)的第一個參數(shù)就是一個參數(shù),沒有隱藏的this
let a = () => {console.log(this)}
a.call({name:"ll"})
a()
//以上結(jié)果相等 this為window
- 箭頭函數(shù)的應(yīng)用,
- 簡化回調(diào)函數(shù)
let arr = [1,2,3]
arr.map(number => number * number) //[1,4,9]
- this 指向固定化耐朴,因?yàn)榧^函數(shù)沒有this借卧,導(dǎo)致函數(shù)內(nèi)部this就是外部代碼塊的this
- Vue中不要直接使用箭頭函數(shù),Vue依賴this筛峭,可以當(dāng)this捕獲之后铐刘,在使用箭頭函數(shù).
- 箭頭函數(shù)返回一個對象,必須用(),因?yàn)閧}被理解為塊級作用域
let x = () => ({name: 'qq'})
- 箭頭函數(shù)還可以和變量解構(gòu)結(jié)合使用
let x = ({x,y}) => {return x + y}
- 箭頭函數(shù)的注意事項(xiàng)
- 箭頭函數(shù)的this是在定義函數(shù)時確定的影晓,而不是使用镰吵。
- 箭頭函數(shù)不能用作構(gòu)造函數(shù),即不能使用關(guān)鍵字new
- 箭頭函數(shù)不可以使用arguments對象挂签,該對象在函數(shù)體內(nèi)不存在捡遍,可以使用rest代替
- 不可以使用yield命令,因?yàn)榧^函數(shù)不能用在Generator函數(shù)
- 箭頭函數(shù)沒有this竹握,使用call,bind画株,apply改變this的指向沒用。
- 不適用場景
- 定義對象的方法,且該方法內(nèi)包含對象
let obj = {
name: 'lili',
fn: () => {this.name} //this指向window
}
此種錯誤谓传,箭頭函數(shù)的this是指創(chuàng)建函數(shù)時所在的作用域蜈项,但是對象不能創(chuàng)建作用(只有函數(shù)才可),所以此時This為window
//改建
let obj = {
name: 'lili',
fn: function(){
let f = () => {this.name}
}
}
- 需要動態(tài)this的時候续挟,不能使用箭頭函數(shù)
button.onClick = function(){
this.classList.add('active')
}
//此時就不能用箭頭函數(shù)
展開操作符(...)
MDN: 展開語法(Spread syntax), 可以在函數(shù)調(diào)用/數(shù)組構(gòu)造時, 將數(shù)組表達(dá)式或者string在語法層面展開紧卒;還可以在構(gòu)造字面量對象時, 將對象表達(dá)式按key-value的方式展開。(譯者注: 字面量一般指 [1, 2, 3] 或者 {name: "mdn"} 這種簡潔的構(gòu)造方式)
展開運(yùn)算符不僅適用于數(shù)組诗祸,還適用于對象,只能用于可迭代對象
- 偽數(shù)組變真數(shù)組的方法
//ES6
let args = [...arguments] OR
let args = Array.from(arguments)
//ES5
let args = Array.prototype.slice.call(arguments)
- 獲取array1的剩余部分
let array1 = [1,2,3,4,5,6,7]
let [a,b,...array2] = array1
// array2 = [3,4,5,6,7]
//語法糖
[,,...array2] = array1
- 復(fù)制一個數(shù)組
let array1 = [1,2,3]
let [...array2] = array1 //let 很重要
// array2 = [1,2,3]
- 在array1前面加1跑芳,在后面加7
let array1 = [3,4,5]
let array2 = [1,...array1,7]
// array2 = [1,3,4,5,7]
- 函數(shù)調(diào)用
function sum(x,y,z){
return x + y + z
}
const numbers = [1,2,3]
sum(...numbers) //6 等價于apply sum.apply(null,numbers)
- 使用 new 關(guān)鍵字來調(diào)用構(gòu)造函數(shù)時,
var dateFields = [1970, 0, 1]; // 1970年1月1日
var d = new Date(...dateFields);
- 連接多個數(shù)組直颅,代替concat()
let arr1 = [1,2,3]
let arr2 = [4,5,6]
let arr3 = arr1.concat(arr2)
console.log(arr3) //[1,2,3,4,5,6]
//展開運(yùn)算符
let arr3 = [...arr1,...arr2]
console.log(arr3) //[1,2,3,4,5,6]
- 字面量對象展開運(yùn)算符,淺拷貝
let obj1 = {foo: 'zzz',num: 23}
let obj2 = {foo: 'xxx',age: 45}
let obj3 = {...obj1}
console.log(obj3) //{foo: 'zzz',num: 23}
默認(rèn)參數(shù)
默認(rèn)參數(shù)允許在沒有值或undefined傳入的時候博个,使用默認(rèn)形參
- 設(shè)置了默認(rèn)參數(shù),即使函數(shù)調(diào)用時顯示把參數(shù)設(shè)置為undefined功偿,值還是默認(rèn)值盆佣,但是設(shè)置null,參數(shù)值就是null
function sum(a = 1){
console.log(a)
}
sum(undefined) //1
sum(null) //null
sum('') //''
- 在函數(shù)被調(diào)用時械荷,默認(rèn)參數(shù)值就會被解析共耍,每次都會創(chuàng)建一個新的參數(shù)對象。
function array (value, arr = []){
arr.push(value)
console.log(arr)
}
array(1) // [1]
array(2) // [2] 不是[1,2]
這是兩個完全不同的數(shù)組吨瞎。
解構(gòu)賦值
解構(gòu)賦值是JavaScript的一種表達(dá)式痹兜,通過解構(gòu)賦值可以把屬性/值從對象 或數(shù)組中取出來,賦值給其他變量.
- 賦值,剩余數(shù)組必須是最后一個元素
[a,b,...rest] = [1,2,3,4,5,6,7]
console.log(a) //1
console.log(b) //2
console.log(rest) //[3,4,5,6,7]
- 對象
//取對象的屬性值
let a,b;
({a,b} = {a: 'li',b:20})
console.log(a) //li
console.log(b) //20
// 其他情況,一個變量可以獨(dú)立于聲明進(jìn)行結(jié)構(gòu)賦值
let a,b;
({a,b} = {name: 'li',b:20})
console.log(a) //undefined
console.log(b) //20
// 其他情況,淺拷貝,代替object.assign()
let rest;
({...rest} = {name: 'li',b:20})
console.log(rest) // {name: 'li',b:20}
等價于 let rest = Object.assign({},{name: 'li',b:20})
- 為了防止從數(shù)組中取出undefined對象颤诀,可以為變量設(shè)置默認(rèn)值
let [a=2,b=3] = [1]
console.log(a) //1
console.log(b) //3
- 交換兩個變量的值
let a = 1,b = 2;
//左邊為需要賦值的變量佃蚜,
[a,b]= [b,a]
console.log(a) //2
console.log(b) //1
- 可以給新的變量名賦值
let o = {q: 42,p:23 }
let {q: foo,p: bar} = o
console.log(foo) //42
console.log(bar) //23
- 解構(gòu)對象時會查找原型鏈(如果屬性不在對象自身,將從原型鏈中查找)
impoer export
export 用于從模塊中導(dǎo)出函數(shù)着绊,對象谐算,原始值等,以便其他程序通過import導(dǎo)入相應(yīng)的模塊進(jìn)行使用.
- 有名字的導(dǎo)入導(dǎo)出
eaport {name.age.city}
import {name,age,city} from "1/js"
使用時归露,使用什么變量import什么變量即可
- 默認(rèn)導(dǎo)出
export default Name
import Name from "1.js"
- 導(dǎo)出模塊變量名相同洲脂,需要重新設(shè)置變量名
import {name as name1} from "1.js"
//name 重命名為name1
- 導(dǎo)入模塊的所有
import * as name from '1.js';
- 關(guān)鍵字import可以像調(diào)用函數(shù)一樣來動態(tài)的導(dǎo)入模塊。以這種方式調(diào)用剧包,將返回一個 promise恐锦。
import("1.js").then(() => {},() =>{})
- 對于不支持import 和export 的瀏覽器,建議使用babel.js
JS數(shù)據(jù)類型疆液,ES6新增的數(shù)據(jù)類型
- JS數(shù)據(jù)類型
null 一铅,number,String堕油,undefined潘飘,object肮之,boolean,symbol卜录,
- ES6新增的數(shù)據(jù)類型
Symbol
- Symbol()不支持new()語法戈擒,因?yàn)樗痪哂衏onstructor()函數(shù).
new Symbol() //報(bào)錯
- 每個從Symbol()返回的symbol值都是唯一的
var a = Symbol()
var b = Symbol()
console.log(a === b) //false
- 一個Symbol值可以作為對象屬性的標(biāo)識符,這是該數(shù)據(jù)類型僅有的目的艰毒。筐高。ES6之前,對象的屬性標(biāo)識符都是字符串丑瞧,現(xiàn)在也可以使Symbol
var a = Symbol()
var obj = {}
obj[0] = '000' //[0]0 其實(shí)是字符串
obj[a] = 'sss'
- symbol是一種基本數(shù)據(jù)結(jié)構(gòu)柑土,不是對象
var a = Symbol()
typeof a //symbol
- symbol可以實(shí)現(xiàn)有一個真的私有屬性
{
let a = Symbol()
let obj = {
name: 'li',
age: 18,
[a]:'隱藏屬性'
}
window.object = obj
}
console.log(object)
console.log(object['Symbol()']) //undefined
如何實(shí)現(xiàn)數(shù)組去重?
- 利用hash來實(shí)現(xiàn)
- 代碼
let array = [1,2,3,4,5,3,4,2,5,1,6,8]
function unip(array){
let result = []
let hash = {}
for(let i = 0; i < array.length; i++){
hash[array[i]] = true
}
console.log(hash)
//遍歷對象使用for...in
for(let key in hash){
result.push(key)
}
console.log(result)
}
unip(array)
- 缺點(diǎn)
返回的數(shù)組元素時字符串绊汹,不是數(shù)字稽屏,以為ES6之前,對象的屬性名只能是字符串
無法區(qū)分原數(shù)組中的字符串?dāng)?shù)字和數(shù)字灸促,比如4和'4',會被認(rèn)為是一個
無法統(tǒng)計(jì)對象涵卵,比如[1,2,{name:'li'}]返回的是[1,2,'object']
- 使用ES6 的set方法實(shí)現(xiàn)數(shù)組去重
Array.from()方法從一個類似數(shù)組或可迭代對象創(chuàng)建一個新的淺拷貝的數(shù)組實(shí)例
Set()方法允許存儲任意類型的唯一值浴栽,無論是原始值還是對象引用值
let array = [1,2,3,4,5,3,4,2,5,1,6,8]
function unip(array){
return Array.from(new Set(array))
//語法糖 return [...new Set(array)]
}
unip(array)
- 利用filter()過濾和indexOf的索引
//只將數(shù)組中元素第一次出現(xiàn)的返回
// 之后出現(xiàn)的將被過濾掉
function unip(array){
return array.filter((item,index) => {
console.log(item + '----' + index)
return array.indexOf(item) ===index
})
}
let array = [1,3,5,2,4,6,4,2,4,3,1]
unip(array)
- 利用Map()對象
function unip(array) {
const newArray = [];
const tmp = new Map();
for(let i = 0; i < array.length; i++){
if(!tmp.get(array[i])){
tmp.set(array[i], 1);
newArray.push(array[i]);
}
}
return newArray;
}
什么是 JSONP,什么是 CORS轿偎,什么是跨域典鸡?
- 同源策略
瀏覽器出于安全機(jī)制的考慮,只允許同源相互訪問數(shù)據(jù)坏晦,不允許跨域請求萝玷。同源指的是:同協(xié)議,同域名昆婿,同端口球碉。window.origin / location.origin
可以獲取到當(dāng)前的源。 - 為什么跨域可以使用CSS,JS仓蛆,圖片等
同源策略限制的是數(shù)據(jù)的訪問睁冬,引用CSS,JS看疙,圖片的時候豆拨,不知道內(nèi)容是什么,只是單純的在引用能庆,使用ajax的時候施禾,需要獲取數(shù)據(jù),所以背會瀏覽器限制搁胆。 - CORS 實(shí)現(xiàn)跨域
CORS:跨域資源共享弥搞,主要用過設(shè)置響應(yīng)頭邮绿,決定瀏覽器是否允許跨域請求數(shù)據(jù)。
如果frank.com想訪問11.com里面的數(shù)據(jù)拓巧,就是跨域斯碌,正常瀏覽器出于安全機(jī)制,是不允許訪問的肛度,通過在11.com的服務(wù)器端設(shè)置reponse setHeader('Access-Control-Allow-Origin','http://frank.com')
即可實(shí)現(xiàn)在frank.com訪問11.com數(shù)據(jù).
若要允許多個網(wǎng)站訪問reponse.setHeaders['refers']
Access-Control-Allow-Origin:允許的域名
- JSONP實(shí)現(xiàn)跨域
- JSONP是通過script標(biāo)簽加載數(shù)據(jù)的方式獲取數(shù)據(jù)當(dāng)做JS代碼來執(zhí)行傻唾,提前在頁面上聲明一個函數(shù),函數(shù)名通過接口傳參的方式傳給后臺,后臺解析到函數(shù)名在原始數(shù)據(jù)上(包裹)這個函數(shù)名授霸,發(fā)送給前端片排。換句話說,JSONP需要對應(yīng)接口的后端的匹配才能實(shí)現(xiàn)凛辣。
- 雖然數(shù)據(jù)不能訪問,但是JS 還是可以引用的职烧,所以可以把數(shù)據(jù)放在JS中扁誓,通過引用JS,即可實(shí)現(xiàn)跨域蚀之。因?yàn)?js文件可以被所有網(wǎng)站引用蝗敢,可以對其進(jìn)行一個
referer檢查
,這就是JSONP的定向分享。 - frank.com想訪問11.com中的數(shù)據(jù)足删,在11.com下創(chuàng)建一個index.js文件寿谴,內(nèi)容
widnow.xxx = {{data}}
設(shè)置后臺
if(path === '/index.js'){
if(request.headers['referer'].indexOf('http://frank.com') === 0 ){
reponse.statusCode = 200;
reponse.setHeader('Content-type',"text/javascript",'charset = utf-8')
const string = fs.readFileSync('/index.js').toString()
const data = fs.readFileSync('./index.json').toString()
const string1 = string.replace({data},data)
reponse.write(string1)
reponse.send()
}else {
response.statusCode = 404
reponse.send()
}
}
在frank.com中只要引用index.js即可<script src = "http://11.com/index.js"></script>
拿到數(shù)據(jù)之后,要移除script失受,防止頁面一直在請求數(shù)據(jù),script只有onloa事件
script.onload = function(){
script.remove()
}
- JSONP封裝
function jsonp(url) {
return new Promise((resolve, reject) => {
let random = Math.random();
window[random] = (data) => {
resolve(data);
};
let script = document.createElement("script");
script.src = `${url}?callback=${random}`;
script.onload = () => {
script.remove();
};
script.onerror = () => {
reject();
};
document.body.appendChild(script);
});
}
// 使用
jsonp("http://localhost:9991/friends.js").then((data) => {
console.log(data);
});
對11.com服務(wù)器后臺的改變
if (path === "/index.js") {
if (request.headers["referer"].indexOf("http://frank.com") === 0) {
response.statusCode = 200;
//query查詢字符串
console.log(query.callback);
response.setHeader("Content-Type", "text/javascript;charset=utf-8");
const string = fs.readFileSync("./index.js").toString();
const data = fs.readFileSync("./index.json").toString();
const string2 = string
.replace("{{data}}", data)
.replace("{{xxx}}", query.callback);
response.write(string2);
response.end();
} else {
response.statusCode = 404;
response.send();
}
- 一定要進(jìn)行后臺設(shè)置讶泰,才能拿到數(shù)據(jù)(主動溝通才有可能實(shí)現(xiàn)跨域)
- 面試題JSONP
在跨域請求的時候,由于當(dāng)前瀏覽器的某些原因不支持CORS拂到,所以需要采用JSONP
JSONP原理:請求JS文件痪署,JS文件匯之星一個回調(diào)函數(shù),回到里面就有需要的數(shù)據(jù)兄旬。回調(diào)函數(shù)的函數(shù)名是隨機(jī)生成辜王,把這個函數(shù)名以callback的形式傳遞給后臺罐孝,后臺會執(zhí)行callback并在次返回給我們莲兢。
JSONP優(yōu)點(diǎn):1,IE支持 2,實(shí)現(xiàn)跨域
JSONP缺點(diǎn): 由于它是script標(biāo)簽汹来,讀取不到ajax那么精確的狀態(tài)坟岔,也不知道狀態(tài)碼是什么社付,也不知道響應(yīng)頭是什么,他只知道成功和失敗。并且他只能發(fā)送get請求.
CORS是在服務(wù)器端加上響應(yīng)頭鸥拧,采用的是ajax請求钠绍。CORS支持所有類型的HTTP請求柳爽。
手寫ajax
- 瀏覽器提供的XMLHttpRequest對象,這個對象使得瀏覽器可以發(fā)出HTTP請求與接收HTTP響應(yīng)娩脾,實(shí)現(xiàn)在頁面不刷新的情況下和服務(wù)端進(jìn)行數(shù)據(jù)交互俩功。使用XMLHttpRequest對象來發(fā)送一個Ajax請求。
let xml = new XMLHttpRequest()
xml.open('get','/xxx')
xml.onreadystatechange = function(){
if (xml.readyState === 4){
if((xml.response.status >= 200 && xml.response.status < 300) || (xml.response.status === 304)){
let data = xml.reponseText
}else {
console.log('失敗')
}
}
}
xml.send()
//post請求只需要在 xml.send()中寫入傳遞參數(shù)即可
xml.send('userbane=lili&passwoed=123')
- readyState:存有XMLHttpRequest的狀態(tài)椿肩。從0~4發(fā)生變化
0:請求未初始化,尚未調(diào)用open()方法
1:服務(wù)器連接已建立,啟動噪沙,已經(jīng)調(diào)用open()方法拷橘,但尚未調(diào)用send()方法萄唇。
2:發(fā)送,已經(jīng)調(diào)用send()方法,但尚未接收到響應(yīng)。
3:請求處理中铺厨,已經(jīng)接收到部分響應(yīng)數(shù)據(jù)筝家。
4:請求處理完成且響應(yīng)就緒逸邦。此時雷客,觸發(fā)load事件裹芝。
new一個函數(shù)發(fā)生了什么兄朋?
new命令的作用:執(zhí)行構(gòu)造函數(shù),返回一個實(shí)例對象,this指對象實(shí)例。未使用new命令,構(gòu)造函數(shù)就是普通函數(shù)萤衰,this指的就是window對象洒擦。
var fn = new Fn()
//new Fn()生成的實(shí)例對象保存在變量fn中
- 創(chuàng)建一個空對象,作為將要返回的對象實(shí)例
var a = {}
- 將這個空對象的原型指向構(gòu)造函數(shù)的prototype屬性
a.__proto__ = FN.prototype
- 將這個空對象賦值給構(gòu)造函數(shù)內(nèi)部的this
this = a
- 執(zhí)行構(gòu)造函數(shù)內(nèi)部代碼
如果構(gòu)造函數(shù)內(nèi)部有return語句椅邓,并且return一個對象逗鸣,那么new構(gòu)造函數(shù)返回的對象就是return的對象透葛,否則不管return語句繁调。對普通函數(shù)门岔,內(nèi)部沒有this的函數(shù)帮坚,new會返回一個空對象讯泣。
總結(jié):new一個函數(shù)节视,總是會返回一個對象霍掺,要么是實(shí)例對象,要么是return語句的對象.
閉包,立即執(zhí)行函數(shù),異步
- 閉包
- 閉包:函數(shù)及內(nèi)部函數(shù)的總和就構(gòu)成了閉包
- 作用:隱藏變量。
function foo(){
var local = 1
function bar(){
local ++
}
return bar()
}
var f = foo()
f() //訪問到了閉包
- 立即執(zhí)行函數(shù)
- 立即執(zhí)行函數(shù):創(chuàng)建一個匿名函數(shù),立即執(zhí)行這個匿名函數(shù)
- 作用: 創(chuàng)建一個獨(dú)立作用域,防止產(chǎn)生全局fn
(function(){alert('聲明一個立即執(zhí)行函數(shù)')})()
- 異步函數(shù)
- 異步:一種并行處理機(jī)制掌实,不等待結(jié)果滋将,例如:數(shù)據(jù)加載過程
- 同步:等待結(jié)果,比如登錄
- 異步的形式: 輪詢和回調(diào)
- 判斷異步的方式
如果函數(shù)的返回值出于以下三個內(nèi),就是異步函數(shù)
1. ajax (XMLHttpRequest)
2. setTimeout()
3. addEventListener()
- 關(guān)于異步和回調(diào)
1. 異步任務(wù)不能拿到結(jié)果
2. 于是傳遞一個回調(diào)給異步任務(wù)
3. 異步任務(wù)完成后調(diào)用這個回調(diào)
4. 異步的結(jié)果為回調(diào)函數(shù)的參數(shù)
- 例子
function f(){
setTimeout(() => {
return 1
},1000)
}
//f函數(shù)并沒有return医寿,默認(rèn)return undefined
//此時這個異步函數(shù)拿不到結(jié)果竖瘾,需要借助一個回調(diào)函數(shù)
function f(fn){
setTimeout(() => {
fn(1)
})
}
function f1(x){console.log(x)}
f(f1)
- setTimeout()關(guān)于this
由setTimeout()調(diào)用的代碼運(yùn)行在與所在函數(shù)完全分離的執(zhí)行環(huán)境上扩劝,這會導(dǎo)致聂示,這些代碼里的this在非嚴(yán)格模式下指向window(全局對象),嚴(yán)格模式下指向undefined趋观。
在嚴(yán)格模式下,setTimeout()的回調(diào)函數(shù)的this扔指向window ,
確定this的值,使用箭頭函數(shù)或bind - 回調(diào)函數(shù)
- 回調(diào),定義一個函數(shù),在另外一個函數(shù)中調(diào)這個函數(shù),這個函數(shù)就是回調(diào)函數(shù)
function f1(fn){
fn()
}
f1(f2)
function f2(){
}
//f2即回調(diào)函數(shù)
.then(這里是回調(diào))
高級函數(shù)
以一個函數(shù)或多個函數(shù)為輸入,返回一個函數(shù)的函數(shù)就是高階函數(shù)柯里化函數(shù)
把多參數(shù)函數(shù)變成接受一個參數(shù)的函數(shù)屋匕,并且返回接受其他參數(shù)的函數(shù)的函數(shù)蔗衡。
bind(),call(),apply()的區(qū)別
作用:改變函數(shù)執(zhí)行時的執(zhí)行上下文,具體一點(diǎn)就是改變函數(shù)運(yùn)行時的this指向.
- bind():返回改變上下文后的一個函數(shù)
- call()和apply()改變執(zhí)行上下文后邊執(zhí)行這個函數(shù)
- call()和apply()的第一個參數(shù)都是this,call的第二個參數(shù)是以參數(shù)列表的形式展示的,apply是把數(shù)組作為第二個參數(shù)的。
這段代碼里的 this 是什么引矩?
- this 的確定看函數(shù)的調(diào)用
1. fn()
this => window/global
2. obj.fn()
this => obj
3. fn.call(xx)
this => xx
4. fn.apply(xx)
this => xx
5. fn.bind(xx)
this => xx
6. new Fn()
this => 新的對象
7. fn = ()=> {}
this => 外面的 this
- this是call的第一個參數(shù)
var obj = {
foo: function(){
console.log(this)
}
}
var bar = obj.foo
obj.foo() //obj === obj.foo.call(obj)
bar() //window === bar.call()
不用 class 如何實(shí)現(xiàn)繼承掏觉?用 class 又如何實(shí)現(xiàn)杨何?
- class關(guān)鍵字是語法糖谋国,JS是基于原型的集畅。
//不用class實(shí)現(xiàn)繼承
function Person(age){
this.age = age
}
Person.prototype.move = function(){console.log('人類會移動')}
function Man(name){
Person.call(this,age) //指定this為Man()。也可以使用Person.apply(this,age)
this.name = name
}
//以下三行代碼實(shí)現(xiàn)Man.prototype.__proto__ = Person.prototype
function temp(){}
temp.prototype = Person.prototype
Man.prototype = new temp()
Man.prototype.run = function(){console.log('男人會跑')}
var man = new Man(18,'li')
//使用class實(shí)現(xiàn)繼承
class Person{
constructor(age){
this.age = age
}
move(){}
}
class Man extends Person{
constructor(age,name){
super(age)
this.name = name
}
run(){}
}
原生JS有哪些獲取元素的方法
1. 通過ID獲取:document.getElementById('id')
2. 通過標(biāo)簽獲取:document.getElementsByTageName()
3. 通過class獲缺罘蟆:document.getElementsByClassName('class')
4. 通過name獲取: document.getElementsByName('name')
5. 獲取HTML:document.document.element()
6. 獲取body:document.body
7. 選擇器選擇一個元素:querySelector()
8. 選擇器選擇一組元素:querySelectorAll()
數(shù)組拷貝
1.擴(kuò)展運(yùn)算符淺拷貝數(shù)組
let a = [1,2,3,4,5,6]
let array = [...a]
console.log(array) //[1,2,3,4,5,6]
- for循環(huán)淺拷貝數(shù)組
let a = [1,2,3,4,5,6]
let array = []
for(let i = 0; i < a.length; i++){
array.push(a[i])
}
console.log(array) //[1,2,3,4,5,6]
- Array.map()淺拷貝數(shù)組,map()接受一個回調(diào)函數(shù),作為對數(shù)組的處理
let a = [1,2,3,4,5,6]
let array = a.map(x => x)
console.log(array) //[1,2,3,4,5,6]
- Array.filter()淺拷貝數(shù)組,filter()也接受一個回調(diào)函數(shù)
let a = [1,2,3,4,5,6]
let array = a.filter(x => x)
console.log(array) //[1,2,3,4,5,6]
- Array.slice()淺拷貝至扰,指定start绷杜,end對原數(shù)組進(jìn)行拷貝,包括start瑰剃,不包括end
let a = [1,2,3,4,5,6]
let array = a.slice(2,5)
console.log(array) //[3,4,5]
- Array.concat()淺拷貝晌姚,將原數(shù)組和其他數(shù)組結(jié)合
let a = [1,2,3,4,5,6]
let array = a.concat(2,5)
console.log(array) //[1, 2, 3, 4, 5, 6, 2, 5]
- Array.from()淺拷貝粤剧,可以將任何一個可迭代對象轉(zhuǎn)化為數(shù)組
let a = 'foo'
let array = Array.from(a)
console.log(array) //["f", "o", "o"]
//實(shí)例2
let a = [1,2,3,4,5,6]
let array = Array.from(a)
console.log(array) //[1,2,3,4,5,6]
數(shù)組翻轉(zhuǎn),使用reverse()即可實(shí)現(xiàn)數(shù)組的翻轉(zhuǎn)
let a = [1,2,3,4,56]
let array = a.reverse()
console.log(array) // [56, 4, 3, 2, 1]
JS的原型是什么挥唠?
- 原型鏈?zhǔn)菍?shí)現(xiàn)JS對象之間共有屬性的繼承
typeof的結(jié)果有哪些?typeof null?為什么宝磨?
- typeof的結(jié)果
1. string 2.number 3. boolean 4. symbol 5. undefined 6. object 7. function
- typeof null
typeof null: object
原因:在JS最初的版本中弧关,使用的是32位系統(tǒng),為了性能考慮唤锉,使用地位存儲性能變量的信息世囊,對象是000開頭,null全是0腌紧,所以誤將null認(rèn)為是對象了茸习。
- typeof object
typeof 判斷對象,除了function 顯示function 之外壁肋,其他都顯示對象号胚,所以typeof不能很
好的判斷對象。
instanceof的作用是什么浸遗?實(shí)現(xiàn)原理的思路是什么猫胁?
- instanceof 運(yùn)算符用于檢測構(gòu)造函數(shù)的 prototype 屬性是否出現(xiàn)在某個實(shí)例對象的原型鏈上。
- 可以通過instanceof判斷對象的類型跛锌,它的內(nèi)部機(jī)制是通過原型鏈來判斷的弃秆。
- 判斷對象
let Person = function(){}
let p1 = new Person()
console.log(p1 instanceof Person) //true
- 判斷原始類型
let a = 'acb'
console.log(a instanceof String) //false
- 正確的判斷方法
let a = 'acb'
let b = new String(a)
console.log(b instanceof String) //true
如何用正則實(shí)現(xiàn) trim()?
String.prototype.trim = function(){
return this.replace(/^\s+|\s+$/g, '')
}
//或者
function trim(string){
return string.replace(/^\s+|\s+$/g, '')
}
手寫函數(shù)防抖和函數(shù)節(jié)流
防抖和節(jié)流都是為了防止函數(shù)的高頻復(fù)用
- debounce(防抖函數(shù)):連續(xù)wait毫秒內(nèi)多次調(diào)用髓帽,只觸發(fā)最后一個
let timerId;
function debounce(fn,wait = 0){
if(timerId){
clearTimeout(timerId)
timerId = null
}else {
timerId = setTimeout(() => {
fn()
timerId = null
},wait)
}
}
- throttle(節(jié)流函數(shù)):連續(xù)多次調(diào)用菠赚,在指定時間內(nèi)按照指定的時間間隔來執(zhí)行.
function throttle(fn,wait = 200){
let last = 1;
let timerId;
const now = + new Date()
return function(...rest){
//在時間間隔之內(nèi),不觸發(fā)
if(last && now-last < wait){
clearTimeout(timerId)
setTimeout(() => {
last = now
fn.apply(this,rest);
},wait)
}else {
fn.apply(this,rest)
clearTimeout(timerId)
}
}
}
null和undefined的區(qū)別是什么郑藏?
Object.create()原理衡查?
ES6引入的新方法,用來創(chuàng)建一個對象必盖,這個對象的原型就是調(diào)用create方法時傳入的參數(shù)
var a = Object.create(b)
//a 的原型就是b
hasOwnPrototype()
是JS中唯一處理屬性且不會遍歷整個原型鏈的方法
必考 Promise拌牲、Promise.all俱饿、Promise.race 分別怎么用?
手寫一個 Promise
移動端適配方案
常見的移動端兼容問題
用過token么塌忽?他有啥通拍埠,你把token放在那邊了?
DOM相關(guān)
事件委托
用mouse事件寫一個可拖曳的div
HTTP相關(guān)
一個URL從輸入到頁面加載共發(fā)生了什么?
無論是地址欄輸入還是代碼里加載土居,都會有一個URL枣购,通過這個URL可以發(fā)送HTTP/HTTPS請求。請求過程装盯,先查看緩存:瀏覽器緩存-系統(tǒng)緩存-路由緩存坷虑,如果緩存有甲馋,直接在緩存中獲取埂奈,沒有的話,對這個URL進(jìn)行解析定躏,提取信息账磺,在進(jìn)行DNS解析,得到對應(yīng)域名的IP地址痊远,通過三次握手垮抗,建立TCP連接,通過GET/POST等方式發(fā)送HTTP/HTTPS請求碧聪,服務(wù)器處理請求并響應(yīng)請求冒版,返回資源,瀏覽器拿到資源進(jìn)行解析渲染逞姿,四次揮手辞嗡,斷開連接。
三次握手
- 客服端發(fā)送SYN報(bào)文
SYN = 1, seq = x
進(jìn)入SYN_SEND
階段 - 服務(wù)器端接受SYN報(bào)文滞造,返回一個ACK響應(yīng)
ACK = 1,SYN = 1,ack = x+1,seq = y
進(jìn)入SYN_RECV
階段 - 客戶端接受服務(wù)器的SYN報(bào)文续室,返回一個ACK響應(yīng)
axk = y+1,seq = x+1.ACK=1
進(jìn)入Etablished
階段
四次揮手
- 客戶端發(fā)送FIN=1,請求關(guān)閉連接
SYN=1,seq = x
進(jìn)入FIN-WAIT-1
階段 - 服務(wù)器端返回ACK,
ACK =1,seq = y,sck = x+1,
進(jìn)入CLOSE_WAIT
階段谒养,客服端進(jìn)入FIN-WAIT-2
階段 - 服務(wù)器通知應(yīng)用程序關(guān)系連接挺狰,之后返回給客戶端
ACK=1,seq = z,ack = x+1,FIN=1
進(jìn)入LAST_ACK
階段 - 客戶端返回
ACK = 1,FIN = 1,seq = x+1,ack = z+1
進(jìn)入TIME_WAIT
,服務(wù)端進(jìn)入CLOSED
階段
為什么是三次握手买窟,四次揮手呢丰泊?
因?yàn)榉?wù)器在接收到客戶端關(guān)閉連接的請求時,是先返回一個應(yīng)答ACK,表示收到這個請求了始绍,之后通知應(yīng)用程序去關(guān)閉連接瞳购,當(dāng)應(yīng)用程序關(guān)閉連接后,服務(wù)器才會通知客戶端疆虚,已關(guān)閉苛败,所以這個地方是分兩步走的满葛,所以比握手建立連接多了一步。
HTTP的狀態(tài)碼及意思
- 狀態(tài)碼:
- 1XX:Informational(信息性狀態(tài)碼)罢屈,接收的請求正在處理嘀韧。
- 2XX:Success(成功狀態(tài)碼),請求正常處理完畢缠捌。
- 3XX:Redirection(重定向狀態(tài)碼)锄贷,需要進(jìn)行附加操作以完成請求。
- 4XX:Client Erroe(客戶端錯誤狀態(tài)碼)曼月,服務(wù)器無法處理請求谊却。
- 5XX:Server Error(服務(wù)器錯誤狀態(tài)碼),服務(wù)器處理請求出錯哑芹。
- 200狀態(tài)碼:(成功) 服務(wù)器已成功處理了請求炎辨。 通常,這表示服務(wù)器提供了請求的網(wǎng)頁聪姿。
- 301狀態(tài)碼:(永久移動) 請求的網(wǎng)頁已永久移動到新位置碴萧。 服務(wù)器返回此響應(yīng)(對 GET 或 HEAD 請求的響應(yīng))時,會自動將請求者轉(zhuǎn)到新位置末购。
- 302狀態(tài)碼:(臨時移動) 服務(wù)器目前從不同位置的網(wǎng)頁響應(yīng)請求破喻,但請求者應(yīng)繼續(xù)使用原有位置來進(jìn)行以后的請求。
- 304狀態(tài)碼:(未修改) 自從上次請求后盟榴,請求的網(wǎng)頁未修改過曹质。 服務(wù)器返回此響應(yīng)時,不會返回網(wǎng)頁內(nèi)容擎场。
- 403:狀態(tài)碼:(禁止) 服務(wù)器拒絕請求羽德。
- 404狀態(tài)碼:(未找到) 服務(wù)器找不到請求的網(wǎng)頁。
- 500狀態(tài)碼:(服務(wù)器內(nèi)部錯誤) 服務(wù)器遇到錯誤顶籽,無法完成請求玩般。
- 503狀態(tài)碼:(服務(wù)不可用) 服務(wù)器目前無法使用(由于超載或停機(jī)維護(hù))。 通常礼饱,這只是暫時狀態(tài)坏为。
HTTP常見狀態(tài)碼
GET和POST的區(qū)別
GET和POST本質(zhì)上就是TCP鏈接,并無差別镊绪,但是GET產(chǎn)生一個TCP數(shù)據(jù)包匀伏;POST產(chǎn)生兩個TCP數(shù)據(jù)包。
- 作用不同:GET獲取資源蝴韭,像后臺要數(shù)據(jù)够颠;POST傳輸實(shí)體主體,像后臺傳輸數(shù)據(jù)榄鉴。
- 請求參數(shù)的展現(xiàn)發(fā)送不同:GET請求會用
?
將請求參數(shù)拼接成url履磨;POST請求的請求參數(shù)在請求主體內(nèi)蛉抓。 - 傳輸數(shù)據(jù)長度不同:因?yàn)闉g覽器地址欄對自動對url進(jìn)行截取,所以當(dāng)數(shù)據(jù)量過大時剃诅,GET請求會造成數(shù)據(jù)丟失巷送。
- 安全性:因?yàn)镚ET請求會拼接成url展示,但是瀏覽器的歷史記錄和服務(wù)器的請求日志矛辕,都會保存其信息笑跛,造成信息的不安全。
請求的動詞
-
GET
:獲取資源聊品。GET方法用來請求訪問已被URI識別的資源飞蹂,指定的資源經(jīng)服務(wù)器端解析后返回響應(yīng)內(nèi)容。HTTP1.0~1.1 -
POST
:傳輸實(shí)體主體翻屈。HTTP1.0~1.1 -
PUT
:傳輸文件陈哑。就像FTP協(xié)議的文件上傳一樣,要求在請求報(bào)文的主體中包含文件的內(nèi)容妖胀,然后保存到請求URI指定的位置芥颈。HTTP1.0~1.1 -
HEAD
:獲取報(bào)文首部惠勒。與GET方法類似赚抡,用于確認(rèn)URI的有效性及資源更新的日期時間等等。HTTP1.0~1.1 -
DELETE
:刪除文件纠屋。是與PUT方法相反的涂臣。HTTP1.0~1.1 -
OPTIONS
:詢問支持的方法。用來查詢針對請求URI指定的資源支持的方法售担。HTTP1.1 -
TRACE
:追蹤路徑赁遗。是讓W(xué)eb服務(wù)器端將之前的請求通信返回給客戶端。HTTP1.1 -
CINNECT
:要求用隧道協(xié)議連接代理族铆。實(shí)現(xiàn)用隧道協(xié)議進(jìn)行TCP通信岩四。HTTP1.1 -
LINK
:建立和資源之間的連接。 -
UNLINK
:斷開連接關(guān)系哥攘。
OSI的七層模型是什么剖煌?TCP/IP是哪四層模型?
- OSI七層模型
七層模型逝淹,也叫OSI(OPen System Interconnection)參考模型耕姊,是國際標(biāo)準(zhǔn)化組織(ISO)指定的一個用于計(jì)算機(jī)或通信系統(tǒng)間互聯(lián)的標(biāo)準(zhǔn)體系。其中包括:- 應(yīng)用層
- 表示層
- 會話層
- 傳輸層
- 網(wǎng)絡(luò)層
- 數(shù)據(jù)鏈路層
- 物理層
- TCP/IP四層模型
其中主要包括:
- 應(yīng)用層:
應(yīng)用層決定了向用戶提供應(yīng)用服務(wù)時通信的活動栅葡。下述的三層負(fù)責(zé)處理網(wǎng)絡(luò)通訊的相關(guān)細(xì)節(jié)茉兰,這部分需要穩(wěn)定高效,因此它們是在操作系統(tǒng)的內(nèi)核空間中欣簇,而應(yīng)用層是在用戶空間實(shí)現(xiàn)的规脸,負(fù)責(zé)處理眾多業(yè)務(wù)邏輯坯约,如文件傳輸、網(wǎng)絡(luò)管理莫鸭。
應(yīng)用層的協(xié)議眾多:- 運(yùn)行在TCP協(xié)議上的協(xié)議
1.1 HTTP(80端口):主要用于普通瀏覽鬼店。
1.2 HTTPS(443端口):HTTP協(xié)議的安全版本。
1.3 FTP(20和21端口):用于傳輸文件黔龟。
1.4 POP3(110端口):收郵件用妇智。
1.5 SMTP(25端口):用來發(fā)送電子郵件。
1.6 SSH(22端口):用于加密安全登錄用氏身。 - 運(yùn)行在UDP協(xié)議上的協(xié)議
2.1 DCHP(67端口巍棱,動態(tài)主機(jī)配置協(xié)議),動態(tài)配置IP地址蛋欣。 - 其他
3.1 DNS(域名服務(wù)):用于完成地址查找航徙,郵件轉(zhuǎn)發(fā)等工作(運(yùn)行在TCP/IP協(xié)議上)。
3.2 SNMP(簡單網(wǎng)絡(luò)管理協(xié)議):用于網(wǎng)絡(luò)信息的收集和網(wǎng)絡(luò)管理陷虎。
3.3 ARP(地址解析協(xié)議):用于動態(tài)解析以太網(wǎng)硬件的地址到踏。
- 運(yùn)行在TCP協(xié)議上的協(xié)議
- 傳輸層:
傳輸層對上層應(yīng)用層,提供處于網(wǎng)絡(luò)連接中的兩臺計(jì)算機(jī)之間的數(shù)據(jù)傳輸尚猿,即為應(yīng)用程序隱藏了數(shù)據(jù)包跳轉(zhuǎn)的細(xì)節(jié)窝稿,負(fù)責(zé)數(shù)據(jù)包的收發(fā)、鏈路超時重連等凿掂。
傳輸層的協(xié)議:- TCP協(xié)議:傳輸控制協(xié)議伴榔,是一種面向連接的,可靠的庄萎,基于字節(jié)流的傳輸層通信協(xié)議踪少。
- UDP協(xié)議:用戶數(shù)據(jù)報(bào)協(xié)議,不可靠的傳輸層協(xié)議糠涛。
- 網(wǎng)絡(luò)層:
網(wǎng)絡(luò)層用來處理在網(wǎng)絡(luò)上流動的數(shù)據(jù)包援奢。
網(wǎng)絡(luò)層協(xié)議:- IP協(xié)議: 是網(wǎng)絡(luò)層最核心的協(xié)議,它根據(jù)數(shù)據(jù)包的目的IP地址來決定如何投遞該數(shù)據(jù)包忍捡。若數(shù)據(jù)包不可直接發(fā)送給目標(biāo)主機(jī)集漾,那么IP協(xié)議就為它尋找一個合適的下一跳路由器,并將數(shù)據(jù)包交付給該路由器去轉(zhuǎn)發(fā)锉罐,如此循環(huán)直至到達(dá)目標(biāo)主機(jī)或者發(fā)送失敗而丟棄該數(shù)據(jù)包帆竹。
- ICMP協(xié)議: 因特網(wǎng)控制報(bào)文協(xié)議ICMP,是IP協(xié)議的補(bǔ)充脓规,用于檢測網(wǎng)絡(luò)的連接狀態(tài)栽连,如ping應(yīng)用程序就是ICMP協(xié)議的使用。
- 鏈路層:
用來處理連接網(wǎng)絡(luò)的硬件部分。包括控制操作系統(tǒng)秒紧、硬件設(shè)備驅(qū)動绢陌、NIC(網(wǎng)絡(luò)設(shè)備器即網(wǎng)卡),及光纖等物理課件部分(還包括連接器等一切傳輸媒介)熔恢。
說一下request包括哪些header
- HTTP請求方式
- HOST 請求的web服務(wù)器的域名地址
- User-Agent 客戶端運(yùn)行的瀏覽器的詳細(xì)信息
- Accept 客戶端能夠接受的內(nèi)容類型
- Accept-Language 客戶端展示返回信息所選擇的語言
- Accept-Encoding 客戶端能夠結(jié)束返回信息的編碼方式
- Accept-Charset 客戶端能夠接受的字符編碼集
- Content-type 客戶端顯示提交內(nèi)容的類型
- Connection 是否需要持久連接 keep-alive/HTTP1.1持久連接
- keep-alive: 持久連接的時間
- cookie:請求發(fā)送時脐湾,會把保存在該域名下的cookie一起發(fā)送給服務(wù)器
- referer: 包含URL
說一下reponse包括哪些header
第一行狀態(tài)行: 協(xié)議版本號 狀態(tài)碼 狀態(tài)信息
Content-Length 服務(wù)器返回消息的正文的長度
Content-type 返回的字符類型和字符編碼格式
Date 顯示當(dāng)前的時間
HTTP緩存有哪幾種?
-
緩存相關(guān)的首部字段
-
緩存對比圖
-
Expires
是用時刻來標(biāo)記時間的叙淌,這個時間是相對于服務(wù)器時間而言秤掌,但是用戶可以更改自己電腦的系統(tǒng)時間,導(dǎo)致瀏覽器的時間和服務(wù)器的時間不一致鹰霍,此時設(shè)置過期時間也沒有什么用了闻鉴。Expires
是HTTP1.0提出的,兼容性比較好 -
Cache-Control
:解決了Expires
的問題茂洒,使用時間間隔來標(biāo)記過期時間的孟岛,和本地時間無關(guān),但是是HTTP1.1提出的督勺,兼容性沒那么好渠羞,所以很多時候Cache-Control
和Expires
連起來用纵隔。Cache-Control
的優(yōu)先級高于Expires
-
Last-Modified
服務(wù)器將資源返回給瀏覽器贫悄,也會將資源最后的修改時間一同返回給瀏覽器,下一次請求的時候赂苗,帶著這個If-Modified-Since字段盏触,包含Last-Modified信息渗蟹,先進(jìn)行最后修改時間比較,未發(fā)生改變赞辩,返回304,但是他無法處理文件一秒內(nèi)多次修改的情形授艰,而且只要文件修改了辨嗽,哪怕實(shí)質(zhì)內(nèi)容未更改,也會發(fā)送請求淮腾。 -
ETag
解決了Last-Modified
的問題糟需,服務(wù)器會通過算法計(jì)算出資源的唯一標(biāo)識符,返回給瀏覽器谷朝,下一次進(jìn)行請求時洲押,帶著If-None-Match,這個字段包含ETag圆凰,這個唯一的標(biāo)識杈帐,先對這個標(biāo)識符進(jìn)行比較,為改變返回304.,通過算法計(jì)算表示符也浪費(fèi)性能挑童。ETag是通過對比瀏覽器和服務(wù)器資源的特征值(例如MD5)來決定是否要發(fā)送文件內(nèi)容累铅,如果一樣就只發(fā)送304. - Etag / If-None-Match優(yōu)先級高于Last-Modified / If-Modified-Since,同時存在則只有Etag / If-None-Match生效站叼。
- Expires和Cache-Control都有一個問題就是服務(wù)端作為的修改娃兽,如果還在緩存時效里,那么客戶端是不會去請求服務(wù)端資源的(非刷新)尽楔,這就存在一個資源版本不符的問題投储,而強(qiáng)制刷新一定會發(fā)起HTTP請求并返回資源內(nèi)容,無論該內(nèi)容在這段時間內(nèi)是否修改過阔馋;而Last-Modified和Etag每次請求資源都會發(fā)起請求轻要,哪怕是很久都不會有修改的資源,都至少有一次請求響應(yīng)的消耗垦缅。
對于所有可緩存資源冲泥,指定一個Expires或Cache-Control max-age以及一個Last-Modified或ETag至關(guān)重要。同時使用前者和后者可以很好的相互適應(yīng)壁涎。
前者不需要每次都發(fā)起一次請求來校驗(yàn)資源時效性凡恍,后者保證當(dāng)資源未出現(xiàn)修改的時候不需要重新發(fā)送該資源。而在用戶的不同刷新頁面行為中怔球,二者的結(jié)合也能很好的利用HTTP緩存控制特性嚼酝,無論是在地址欄輸入URI然后輸入回車進(jìn)行訪問,還是點(diǎn)擊刷新按鈕竟坛,瀏覽器都能充分利用緩存內(nèi)容闽巩,避免進(jìn)行不必要的請求與數(shù)據(jù)傳輸。 -
瀏覽器發(fā)送請求過程
HTTP1.0担汤、HTTP1.1 和 HTTP2.0 的區(qū)別
- HTTP1.0(1996年)和HTTP1.1(1999年)的區(qū)別
- 緩存處理
HTTP1.0采用If-Modified-Since
和Expires
HTTP1.1采用更多的信息來保存緩存If-Unmodified-Since 涎跨、 If-Match,If-none-Mach
- 帶寬優(yōu)化及網(wǎng)絡(luò)連接的使用
HTTP1.0會傳輸整個信息崭歧,即使你只需要一部分隅很,并且不支持?jǐn)帱c(diǎn)續(xù)傳功能
HTTP1.1在頭部引入range信息,允許請求某個資源的一部分 - 錯誤通知的管理
HTTP1.1引入了24個狀態(tài)碼率碾,比如410:服務(wù)器上的資源被永久刪除,409請求的資源與當(dāng)前資源沖突 - HOST頭部處理
HTTP1.0 沒有host頭部叔营,只有一個IP地址,但隨著虛擬機(jī)的出現(xiàn)所宰,在HTTP1.1中绒尊,使用HSOT信息,無此信息會報(bào)400錯誤仔粥,bad request - 長連接
在HTTP1.1中支持長連接很請求的流水線處理婴谱,在一個TCP連接上可以傳送多個HTTP請求和響應(yīng) ,減少了建立請求和關(guān)閉請求的時間。在HTTP1,1中勘究,默認(rèn)開啟Connection:keep-alive矮湘,一定成都還是那個,彌補(bǔ)了HTTP1.0每次請求都要建立連接的缺點(diǎn)
- HTTP和HTTPS的區(qū)別
- HTTP是運(yùn)行在TCP協(xié)議之上的口糕,HTTPS是運(yùn)行在SSL/TLS之上的缅阳,是加密的,SSL/TLS是運(yùn)行在TCP協(xié)議之上的景描。
- HTTPS需要到CA申請證書
- HTTP端口是80十办,HTTPS端口是443
- HTTPS可以有效防止運(yùn)營商劫持
- SPDY對HTTP1.x的優(yōu)化
- 降低延遲:多路復(fù)用,解決了瀏覽器阻塞問題
- 設(shè)置了請求優(yōu)先級超棺,重要的請求先解決
- header壓縮向族,對header頭部進(jìn)行壓縮
- 基于HTTPS的加密協(xié)議傳輸,大大提高了數(shù)據(jù)的可靠性
- 服務(wù)端推送
- HTTP2.0和SPDY的區(qū)別
HTTP2.0是對SPDY的升級棠绘,但也有不同
- HTTP2.0 支持明文HTTP傳輸件相,但是SPDY強(qiáng)制使用HTTPS
- HTTP2.0頭部壓縮采用HPACK算法,SPDY采用DEFLATC算法
- HTTP2.0 和HTTP1.x的區(qū)別
- 新的二進(jìn)制格式
HTTP2.0采用二進(jìn)制解析氧苍,HTTP1.x采用文本解析 - 多路復(fù)用夜矗,連接共享。即每一個request都是用作連接共享的機(jī)制让虐,給request添加ID紊撕,便于區(qū)分
- header壓縮
HTTP1.X有大量的header信息,HTTP2.0 對其進(jìn)行了壓縮 - 服務(wù)端推送
支持server push赡突。服務(wù)端推送能把客戶端所需要的資源伴隨著index.html一起發(fā)送到客戶端对扶,省去了客戶端重復(fù)請求的步驟。
HTTP2.0的多路復(fù)用和HTTP1.X中的長連接復(fù)用有什么區(qū)別惭缰?
- HTTP/1.* 一次請求-響應(yīng)浪南,建立一個連接,用完關(guān)閉从媚;每一個請求都要建立一個連接逞泄;
- HTTP/1.1 Pipeling解決方式為,若干個請求排隊(duì)串行化單線程處理拜效,后面的請求等待前面請求的返回才能獲得執(zhí)行機(jī)會,一旦有某請求超時等各谚,后續(xù)請求只能被阻塞紧憾,毫無辦法,也就是人們常說的線頭阻塞昌渤;
- HTTP/2多個請求可同時在一個連接上并行執(zhí)行赴穗。某個請求任務(wù)耗時嚴(yán)重,不會影響到其它連接的正常執(zhí)行;
Cookie VS LocalStorage(本地存儲) VS SessionStorage(會話存儲) VS Session
- Cookie VS LocalStorage
- 主要區(qū)別是Cookie會被發(fā)送到服務(wù)器般眉,而LocalStorage不會
- Cookie的存儲位置:瀏覽器和服務(wù)器了赵,LocalStorage是只讀屬性,并且值存儲在瀏覽器甸赃。
- Cookie一般最大是4k ,LocalStorage可以是5MB,甚至是10MB柿汛,各瀏覽器不同
- LocalStorage VS SessionStorage
- LocalStorage一般不會自動過期,除非手動刪除埠对,而SessionStorage在會話結(jié)束時過期络断,如關(guān)閉瀏覽器
- Cookie VS Session
- Cookie存在瀏覽器的文件里,Session存在服務(wù)器的文件里
- Session是基于Cookie實(shí)現(xiàn)的项玛,具體做法是把SessionID放到Cookie中貌笨。
- SessionId的生成一般采用JWT算法。
框架VUE相關(guān)
watch和method和computed三者的區(qū)別
- computed(計(jì)算屬性),返回一個屬性襟沮,依賴緩存锥惋,緩存的內(nèi)容沒有變化,就不會重新計(jì)算开伏。
- methods(方法)膀跌,沒有緩存,頁面刷新硅则,就重新執(zhí)行該方法
- watch(偵聽屬性)淹父,代碼是命令式和具有復(fù)雜性,可能返回一個屬性怎虫,還可能做別的事情(如上報(bào)數(shù)據(jù))
- 數(shù)據(jù)量大暑认,需要緩存使用computed,每次確實(shí)需要重新加載大审,不用緩存蘸际,使用methods
Vue有哪些鉤子函數(shù),有什么用徒扶?
- 生命周期: 初始化---運(yùn)行中---銷毀(開始創(chuàng)建--初始化數(shù)據(jù)--編輯模板--掛載DOM--渲染->更新->渲染--銷毀)
- 鉤子函數(shù)
-
beforeCreate
:vue對象被創(chuàng)建了粮彤,但是Vue屬性還沒有綁定,template
模板還沒有HTML元素姜骡。 -
created
:vue屬性被綁定了导坟,但此時DOM還沒有生成,$el還沒有值 -
beforeMount
:this.$el有值圈澈,但是數(shù)據(jù)還沒有掛載到頁面上惫周,{{}}內(nèi)的變量還沒有被替換 -
mounted
:模板編譯完成,數(shù)據(jù)掛載完畢.此時可以發(fā)送異步ajax請求 -
beforeUpdate
:數(shù)據(jù)更新之前執(zhí)行的函數(shù)康栈,只有數(shù)據(jù)更新才會觸發(fā)beforeupdate递递。此數(shù)據(jù)一定是在模板上出現(xiàn)的數(shù)據(jù)喷橙,否則,不會登舞,也沒有必要觸發(fā)組件更新(因?yàn)閿?shù)據(jù)不出現(xiàn)在模板里贰逾,就沒有必要再次渲染) -
updated
:組件更新之后執(zhí)行的函數(shù) -
beforeDestory
:組價對象銷毀之前執(zhí)行的函數(shù) -
destoryed
:組件銷毀了執(zhí)行的函數(shù).
Vue如何實(shí)現(xiàn)組件間的通信
- 父組件通過props向下傳遞數(shù)據(jù)給子組件。注:組件中的數(shù)據(jù)共有三種形式:data菠秒、props疙剑、computed
//父組件
<template>
<div id="app">
<HelloWorld v-bind:users = "users"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
data(){
return {
users: ['li','xiao','qi']
}
},
components: {
HelloWorld
}
}
</script>
//子組件
<template>
<div>
<ul>
<li v-for="user in users">{{user}}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: { //通過props接受從父組件傳來的數(shù)據(jù)
users: {
type: Array
}
}
}
</script>
- 父子組件:使用
v-on
通過事件通信
子組件通過events給父組件發(fā)送消息,實(shí)際上就是子組件把自己的數(shù)據(jù)發(fā)送到父組件稽煤。
//子組件
<template>
<div>
<h1 @click = "changeTitle">{{title}}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return {
title: "this is a son"
}
},
methods: {
changeTitle(){
this.$emit('changeTitle','子組件想父組件傳值')
}
}
}
</script>
//父組件
<template>
<div id="app">
<HelloWorld v-on:changeTitle = "updatetitle"/>
<h2>{{title}}</h2>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
data(){
return {
title: "一個值"
}
},
methods: {
updatetitle(e){
this.title = e
}
},
components: {
HelloWorld
}
}
</script>
- 爺孫組件:使用兩次
v-on
通過爺爺爸爸通信核芽,爸爸兒子通信實(shí)現(xiàn)爺孫通信 - 任意組件:使用
eventBus = new Vue()
來通信,eventBus.$on
和eventBus.$emit
是主要的API
var eventBus = new Vue()
eventBus.$emit(事件名酵熙,數(shù)據(jù))
eventBus.$on(事件名轧简,data =>{})
- 任意組件: 使用vuex通信
Vuex的原理及如何使用Vuex
- Vuex是vue的狀態(tài)管理器。存儲的數(shù)據(jù)是響應(yīng)式的匾二。
-
Vuex的組成結(jié)構(gòu)圖
- 含義
-
state
:數(shù)據(jù)處理中心哮独,用來存儲數(shù)據(jù) -
getters
:getters和組件的computed類似,方便生成一些直接可用的數(shù)據(jù)察藐,當(dāng)組裝的數(shù)據(jù)要在多個頁面使用的時候皮璧,使用getters比較好。 -
Mutations
:提交更改數(shù)據(jù)分飞,使用store.commit()
方法更改state的存儲狀態(tài)悴务。 -
Action
:提交的是mutation
,而不是直接更改狀態(tài)譬猫,Action
可以直接包含異步操作讯檐。由組件中的$store.dispatch('action名稱',deta1)來觸發(fā),然后由
commit()`來觸發(fā)mutation的調(diào)用染服,間接更新State别洪。
- 安裝及引用
npm install vuex --save / yarn add vuex
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
- 在Vue組件中獲取Vuex的狀態(tài)(State)
-
this.$store.state
獲取
通過在根實(shí)例中注冊store選項(xiàng),改store實(shí)例會注入到根組件下的所有子組件柳刮,且子組件都能通過this.$store獲取到
this.$store.state.count
- mapState()輔助函數(shù)獲取
當(dāng)一個組件需要多個狀態(tài)時挖垛,推薦使用mapState,他幫助我們生成計(jì)算屬性秉颗。
import {mapState} from "vuex"
computed: mapState({
count: state => state.count,
//穿字符串'count'等同于傳入'state => state.count'
countAlias: 'count'
//為了使用This痢毒,所以不能使用箭頭函數(shù)
countPlusLocalState(state){
return state.count + this.countAlias
}
})
- Getter的獲取方式
Vuex允許我們在store中定義"getter",就像計(jì)算屬性一樣蚕甥,getter的返回值會根據(jù)他的依賴被緩存起來闸准,且只有當(dāng)他的依賴發(fā)生變化時,才會重新計(jì)算
- 通過屬性訪問
store.getters.doneTodos
- 通過方法訪問
getters: {
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
getter在通過方法訪問時梢灭,每次都會去進(jìn)行調(diào)用夷家,而不會緩存。
- mapGetters輔助函數(shù)獲取
import {mapGetters} from "vuex"
export default {
....
computed:{
//使用對象展開符將getters混入computed 對象中
...mapGetters([
'doneTodoCount',
])
}
}
- Mutation
更改vuex的store中的狀態(tài)的唯一辦法是提交mutation敏释,vuex中的mutation非常類似于事件库快,每個Mutation都有一個字符串的事件類型(type)和一個回調(diào)函數(shù)(handler),這個回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方钥顽,并且它接受state作為第一個參數(shù).
- 使用常量替代Mutation事件類型
const store = new Vuex.Store = ({
state: {...},
mutations: {
[SOME_MUTATION](state){
//使用常量作為函數(shù)名
//mutate state
}
}
- 可以在組件中使用this.$store.commit('xxx')提交mutation义屏,或者使用mapMutations輔助函數(shù)將組件中的methods映射為store.commit調(diào)用
export default{
...mapMutaions([
'increment',
//將this.increment映射為this.$store.commit('increment')
])
}
- Action
Action函數(shù)接受一個與Store實(shí)例具有相同方法和屬性的context對象,因此可以調(diào)用context.commit提交一個Mutation或者通過context.state和context.getters來獲取state和getters蜂大。
const store = new Vuex.Store({
state: {count: 0},
mutations: {
increment(state){state.count ++}
},
actions: {
increment(context){
context.commit('increment')
}
}
})
- 分發(fā)action
store.dispatch('increment',{
acount:10
})
store.dispatch({
type: 'increment',
acount: 10
})
- 在組件中分發(fā)action
在組件中使用this.$store.dispatch('xxx')分發(fā)action闽铐,或者使用mapActions輔助函數(shù)將組件中的Methods映射為store.dispatch調(diào)用
export default {
methods: {
...mapMutations([
'increment'
])
}
}
vue數(shù)據(jù)響應(yīng)式是怎么做到的
- Vue.js的特點(diǎn)是非侵入性的響應(yīng)式系統(tǒng),數(shù)據(jù)模型是普通的JS對象奶浦,修改他們時兄墅,視圖會進(jìn)行更新渲染,但是由于JS的限制澳叉,Vue不能檢測數(shù)組和對象的變化隙咸。
- 一個普通的JS對象傳入Vue實(shí)例作為data選項(xiàng)時,Vue將遍歷此對象的所有property成洗,并使用
Object.defineProperty把對象的所有property轉(zhuǎn)化為getter/setter
- 對于對象五督,vue無法檢測到property的添加和刪除
- property必須在data對象上存在才是響應(yīng)式的。
var vm = new Vue({
data: {
a:1
}
})
// vm.a 是響應(yīng)式的
vm.b =1
//vm.b不是響應(yīng)式
- 對于已經(jīng)創(chuàng)建的實(shí)例瓶殃,Vue不允許動態(tài)添加根級別的響應(yīng)式property,但是可以使用
Vue.set(object,propertyName,value)
或者this.$set(object,propertyName,value)
方法嵌套對象添加響應(yīng)式property充包。
Vue.set(vm.object,'b',2)
this.$set(this.object,'b',2)
- 為對象賦值多個屬性時
this.object = Object.assign({},this.object,{a:1,b:2})
- 對于數(shù)組
- vue不能檢測到一下數(shù)組的變動
1.1利用索引直接修改一個數(shù)組的選項(xiàng)時vm.items[indexOf] = newValue
1.2當(dāng)修改數(shù)組的長度時,vn.length = newLength
- 對于1.1的情況遥椿,使用set,并且還可以觸發(fā)響應(yīng)式更新
Vue.set(vm.items,indexOf,newValue)
this.$set(this.items,indexOf,newValue)
- 對于1.2的情況基矮,使用splice
this.$items.splice(newLength)
- 聲明響應(yīng)式property
由于Vue不允許動態(tài)添加根級響應(yīng)式property,所以必須在初始實(shí)例前聲明所有根級響應(yīng)式property修壕,哪怕是一個空值
var vn = new Vue({
data:{
message:''
}
})
- 異步更新隊(duì)列
vue更新DOM是異步的愈捅,主要偵聽到數(shù)據(jù)變化,vue將開啟一個隊(duì)列慈鸠,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)變更蓝谨,如果同一個watcher被多次觸發(fā),只會被推入到隊(duì)列中一次青团,然后在下一次循環(huán)'tick'中譬巫,Vue將刷新隊(duì)列并執(zhí)行實(shí)際操作。
采用技術(shù)Promise.then,MutationObserver,setImmdiate
為了在數(shù)據(jù)變化之后等待Vue完成更新DOM督笆,可以在數(shù)據(jù)變化之后立即使用Vue.nextTick
芦昔,這樣回調(diào)函數(shù)將在DOM更新完成后被調(diào)用
使用Object.defineProperty
把這些全部轉(zhuǎn)為getter/setter
Vue
不能檢測到對象屬性的添加或刪除,解決辦法是手動調(diào)用Vue.set
或者this.$set
Vue set有什么用
vue 是非侵入性響應(yīng)式系統(tǒng)娃肿,所有的數(shù)據(jù)模型都是JS對象咕缎,一個JS對象傳入Vue實(shí)例作為data選項(xiàng)時珠十,VUE會遍歷對象所有的property,使用Object.defineProperty
將他們轉(zhuǎn)化為getter/setter
,凭豪,但是vue不支持動態(tài)添加根級別的響應(yīng)式property焙蹭,無法檢測property的添加或者移除,所以采用set對屬性進(jìn)行添加和移除.
VueRouter怎么用
vue router是vue.js官方的路由管理器
- 相關(guān)API
- router-link
導(dǎo)航嫂伞,根據(jù)to屬性去匹配對應(yīng)的組件孔厉,然后渲染到正確的位置,若使用a標(biāo)簽帖努,頁面會發(fā)生跳轉(zhuǎn)撰豺,router-link默認(rèn)會渲染成a標(biāo)簽
<router-link :to="{path:'/home'}" tag="li" ctive-class="activeClass" event="mouseover" exact>
<span>home</span>
</router-link>
tag: 設(shè)置生成指定的標(biāo)簽名
to:頁面要跳轉(zhuǎn)的文件位置,可以動態(tài)綁定
active-class:設(shè)置單獨(dú)的拼余,獨(dú)有的激活狀態(tài)的顏色
event:指定事件
exact:其他路徑被點(diǎn)亮的時候去掉根路徑的active
redirect:重定向
- router-view
命名視圖污桦,在同級同時展現(xiàn)多個視圖,而不是嵌套展示姿搜,要對router-view起一個名字
<router-view name = "silder"></router-view>
- 路由信息對象的params屬性
路由傳參params ,只有通過路由配置的name跳轉(zhuǎn)寡润,才會生效,即使沒有使用動態(tài)路由舅柜,也可以通過params傳參
如果使用動態(tài)路由梭纹,那么在動態(tài)路由頁面刷新路由,params參數(shù)依然存在致份,
如果沒有使用動態(tài)路由变抽,params參數(shù)只在跳轉(zhuǎn)路由時有效,刷新頁面則會丟失params
this.$route.params 獲取到自己配置的動態(tài)路由參數(shù)氮块,路由ID
一個路由信息對象绍载,表示當(dāng)前激活的路由的狀態(tài)信息,包含當(dāng)前URL解析得到的信息滔蝉,還有URL匹配得到的路由記錄击儡。
- 其他
this.$route.back() //回退一步
this.$route.foreard() //前進(jìn)一步
this.$route.go() //指定回退前進(jìn)的步數(shù)
this.$route.push() //導(dǎo)航到不同的URL,向history棧中添加一個新的記錄
this.$route.replace() //導(dǎo)航到不同的URL蝠引,替換掉棧中當(dāng)前的記錄
this.s4route.meta() //訪問Meta中的數(shù)據(jù)
- 導(dǎo)航鉤子函數(shù)
導(dǎo)航發(fā)生變化時阳谍,導(dǎo)航鉤子主要用來攔截導(dǎo)航,讓他完成跳轉(zhuǎn)或取消
- 鉤子函數(shù)
router實(shí)例上:beforeEach,afterEach
單個路由中: beforeEnter
組件內(nèi)部的鉤子: beforeRouterEnter beforeRouteUpdate BeforeRouteLeave
參數(shù): to from next
- history模式
- vue-router默認(rèn)是Hash模式螃概,當(dāng)URL改變時矫夯,頁面不會重新加載。history模式吊洼,充分利用history.pushState API來完成URL跳轉(zhuǎn)頁面無需重新加載頁面训貌。當(dāng)路由變化時,JS會根據(jù)路由渲染對應(yīng)的VUE組件冒窍。
-
vue-router是為單頁面服務(wù)的需要在服務(wù)端增加一個覆蓋所有情況的候選資源递沪,如果URL匹配不到任何靜態(tài)資源豺鼻,返回一個index.html頁面,也是app依賴的頁面区拳。這個index.html是我們項(xiàng)目的入口拘领,index.html里面會讀取當(dāng)時打包好的app.js,就可以讀取到路由配置了樱调。
hash是不需要配置的,因?yàn)闉g覽器會忽略#和届良?后面的參數(shù)
const router = new VueRouter({
mode:'history',
routes: [...]
})
- 警告:
這么做以后笆凌,服務(wù)器就不在返回404頁面,因?yàn)閷τ谒械穆窂蕉紩祷豂ndex.html士葫,為了避免這種情況乞而,應(yīng)該在vue應(yīng)用里面覆蓋所有的路由情況,然后給出一個404
const router = new VueRouter({
mode:'history',
routes: [{
path: '*',component: NotFoundComponent
}]
})
- 路由懶加載
- 原因:打包構(gòu)建應(yīng)用時慢显,JS包會變得非常大爪模,影響頁面的加載。
- 解決:不同路由對應(yīng)的組件分割成不同的代碼塊荚藻,然后當(dāng)路由被訪問時屋灌,加載對應(yīng)的組件。
- 實(shí)現(xiàn)路由的懶加載:
Vue的異步組件和webpack的代碼分隔功能应狱。 - 步驟
4.1可以將異步組件定義為返回一個Promise的工廠函數(shù)
const Foo = () => Promise.resolve({/*組件定義對象*/})
4.2在webpack2中共郭,使用動態(tài)Import語法來定義代碼分塊點(diǎn)
import ('./Foo.vue')
- 定義一個能夠被webpack自動代碼分隔的異步組件
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{path:'/foo',component: Foo}
]
})
路由守衛(wèi)是什么?
- vue-router提供的導(dǎo)航守衛(wèi)主要用來通過跳轉(zhuǎn)或取消的方式來守衛(wèi)導(dǎo)航疾呻。參數(shù)或查詢的改變并不會觸發(fā)離開/進(jìn)入的導(dǎo)航守衛(wèi)除嘹。可以通過觀察$route對象來觀察這些變化岸蜗,或使用beforeRouteUpdate的組件內(nèi)守衛(wèi)尉咕。
- 守衛(wèi)是異步解析執(zhí)行,此時導(dǎo)航在所有守衛(wèi)resolve之前是出于等待中璃岳。
- 全局前置守衛(wèi)
beforeEach
按照創(chuàng)建順序調(diào)用
const router = new VueRouter({...})
router.beforeEach((to,from,next) => {})
- 各參數(shù)含義
to: Route:即將要進(jìn)入的目標(biāo)對象
from:Route:當(dāng)前導(dǎo)航正要離開的路由
next:Function:一定要調(diào)用這個方法來resolve這個鉤子年缎,執(zhí)行效果依賴Next方法傳遞的參數(shù).
如果鉤子全部執(zhí)行完,導(dǎo)航的狀態(tài)是confirmed(確認(rèn)的)
- 確保next函數(shù)在任何給定的導(dǎo)航守衛(wèi)中都要被嚴(yán)格調(diào)用一次矾睦,他的出現(xiàn)可以多于一次晦款,但是只能在所有的邏輯路徑都不重疊的情況下,否則鉤子永遠(yuǎn)不會被解析或報(bào)錯
router.beforeEach((to,from,next) => {
if(to.name !==Login && !isLogin)next({name: 'Login'})
else next()
})
- 全局前置解析
beforeResolve
在導(dǎo)航被確認(rèn)之前同時在所有組件守衛(wèi)和異步路由組件被解析之后枚冗,解析守衛(wèi)就會調(diào)用(這也是和前置守衛(wèi)的區(qū)別) - 全局后置鉤子afterEach
與守衛(wèi)不同的是缓溅,鉤子不會接受next函數(shù)也不會改變導(dǎo)航本身。 - 路由獨(dú)享守衛(wèi)
beforeEnter
,直接定義在路由上
const router = new VueRouter({
routes: [
{
path: '/foo',
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
- 組件內(nèi)部守衛(wèi):路由組件內(nèi)定義的守衛(wèi)
-
beforeRouteEnter
:不能獲取組件實(shí)例this,此時組件實(shí)例還未創(chuàng)建 -
beforeRouteUpdate
: 組件復(fù)用的時候調(diào)用赁温,可以獲取組件的實(shí)例this -
beforeRouteLeave
:組件離開的時候調(diào)用坛怪,可以獲取組件實(shí)例this -
beforeRouteEnter
不能獲取組件實(shí)例this淤齐,但是可以給next函數(shù)傳遞一個回調(diào)函數(shù)來訪問組件的實(shí)例,在導(dǎo)航被確認(rèn)的時候執(zhí)行回調(diào)袜匿,并且吧實(shí)例作為回調(diào)的參數(shù)
beforeRouteEnter(to,from,next){
next(vm => {})
}
beforeRouteEnter是唯一一個支持next傳遞回調(diào)函數(shù)的導(dǎo)航守衛(wèi)更啄,其他都不可以。
-
beforeRouteLeave
離開守衛(wèi)通過進(jìn)制用戶在還未保存修改前突然離開,next(false)
可以取消該導(dǎo)航.
- 完整的導(dǎo)航解析流程
- 導(dǎo)航被觸發(fā)
- 在失活的組件里調(diào)用
beforeRouteLeave
- 調(diào)用全局的
beforeEach
守衛(wèi) - 在復(fù)用的組件里調(diào)用
beforeRouteUpdate
守衛(wèi) - 在路由配置里調(diào)用
beforeEnter
守衛(wèi) - 解析異步路由組件
- 在被激活的組件里調(diào)用
beforeRouteEnter
- 調(diào)用全局的
beforeResolve
- 導(dǎo)航被確定
- 調(diào)用全局的
afterEach
鉤子 - 觸發(fā)DOM更新
- 用創(chuàng)建好的實(shí)例調(diào)用
beforeEnter
守衛(wèi)中傳給next回調(diào)函數(shù)
Vue有哪些指令
- 指令
- 解釋: 帶有v-前綴的特殊屬性
- 作用: 當(dāng)表達(dá)式的值發(fā)生概念時居灯,將其產(chǎn)生的影響響應(yīng)式的作用于DOM祭务。
-
v-text
:更新元素的textContent -
v-html
:更新元素的innerHTML -
v-bind
:當(dāng)表達(dá)式的值改變時,將其產(chǎn)生的影響響應(yīng)式的作用于DOM -
v-on
:綁定事件
事件修飾符
.stop 阻止冒泡怪嫌,調(diào)用 event.stopPropagation()
.prevent 阻止默認(rèn)事件义锥,調(diào)用 event.preventDefault()
.capture 添加事件偵聽器時使用事件捕獲模式
.self 只當(dāng)事件在該元素本身(比如不是子元素)觸發(fā)時觸發(fā)回調(diào)
.once 事件只觸發(fā)一次
-
v-modal
:在表單元素上創(chuàng)建雙向綁定數(shù)據(jù),作用:監(jiān)聽用戶的輸入事件以更新數(shù)據(jù) -
v-for
:遍歷岩灭,使用V-for的時候拌倍,要使用key屬性 -
v-if
:根據(jù)表達(dá)式的值的真假條件,銷毀或重建元素 -
v-show
:根據(jù)表達(dá)式之真假值噪径,切換元素的 display CSS 屬性 -
v-cloak
:防止網(wǎng)速慢的時候出現(xiàn){{}} -
v-once
:只渲染元素和組件一次
你發(fā)送請求放在哪個生命周期柱恤,beforeDestory應(yīng)用場景
- beforeDestory實(shí)例被銷毀之前調(diào)用,此時實(shí)例還是可以使用的找爱。
- 發(fā)送請求放在created中梗顺,因?yàn)榇藭r已經(jīng)拿到了data。
vue中的filters是干甚用的
- Vue.js允許自定義過濾器缴允,用于一些常見的文本格式化荚守。
- 過濾器可以使用在兩個地方
{{}} --- 雙花括號插值 {{message | capitalize}}
v-bind表達(dá)式 <div v-bind:id = "ravID | formatId"></div>
- 可以在組件內(nèi)定義一個本地過濾器 也可以在創(chuàng)建實(shí)例之前定義一個全局過濾器
filters: {
'capitalize': function(){}
}
Vue.filter('capitalize',function(){})
- 過濾器的作用:
- 過濾器可以通過管道符寫多個過濾器 {{messa | filter1 | fliter2}}而寫多個函數(shù)就是一個很麻煩的事情,可能會產(chǎn)生很多的對象代理练般,依賴收集等一大推降低性能的問題
- Array原型鏈上可以用v-for循環(huán)解決矗漾,沒必要在methods方法上面添加太多
vue 為什么data必須是函數(shù)。
JS的實(shí)例是由構(gòu)造函數(shù)創(chuàng)建的薄料,一個構(gòu)造函數(shù)可以New出很多個實(shí)例敞贡,Vue 的data其實(shí)是vue 原型上的屬性,數(shù)據(jù)是保存在內(nèi)存中的摄职,為了保證數(shù)據(jù)之間是互相獨(dú)立的誊役,互不影響的,使用return即函數(shù)谷市,而不是對象蛔垢,因?yàn)閷ο笫莾?nèi)存引用。
slot的作用
- 插槽: 在2.6.0中為具名插槽和作用域插槽引入了統(tǒng)一語法v-slot.是對組件的擴(kuò)展迫悠,通過slot插槽向組件內(nèi)部指定位置傳遞內(nèi)容鹏漆,通過slot可以父子傳參
- 插槽<slot>作為承載分發(fā)內(nèi)容的出口
- 父級模板里的所有內(nèi)容都是在父級作用域中編譯的;子模板里的所有內(nèi)容都是在子作用域中編譯的。
- 具名插槽,一個不帶 name 的 <slot> 出口會帶有隱含的名字“default”艺玲。
<slot name = "headerr"></slot>
在向具名插槽提供內(nèi)容的時候括蝠,我們可以在一個 <template> 元素上使用 v-slot 指令,并以 v-slot 的參數(shù)的形式提供其名稱: v-slot 只能添加在 <template> 上
<template v-slot = "header'></template>
- 作用域插槽
作用域插槽可以顯著提高組件的通用性和復(fù)用性饭聚。作用域插槽允許你傳遞一個模板忌警,而不是已經(jīng)渲染好的元素給插槽,之所以叫作用域插槽秒梳,是因?yàn)槟0咫m然在父級作用域中渲染法绵,但卻能訪問子組件的數(shù)據(jù)。作用域插槽主要應(yīng)用的是列表組件端幼。
<ul>
<slot name = "item" v-for = "item in items" :text = "item.text" :myname = "item.myname">
slotmore內(nèi)容
</slot>
</ul>
<Child>
<template slot = "item" v-slot = "props">
<li>{{props.myname}}</li>
</template>
</Child>
vue-router你說怎么傳參的礼烈,有幾種方式傳參,他們的區(qū)別是什么婆跑?
- 編程式的導(dǎo)航 router.push
- 直接在路由路徑后面寫參數(shù)${}
//頁面列表傳遞參數(shù)
this.$router.push({
path: '/custome/customeDetailPage/${id}'
})
//對路由的配置
{
path: '/custome/customeDetailPage/:id'
}
//獲取路由參數(shù)
this.$route.params.id
- 通過name屬性來匹配路由,通過params傳遞參數(shù)
//頁面列表參數(shù)
this.$router.push({
name: 'CDetailPage', //name 屬性是必須的
params: {
dataObj: id
}
})
//路由配置
{
path: '/custome/customeDetailPage',
name: 'CDetailPage', //那么屬性必須存在
component: ''
}
//接受參數(shù)
- 通過path匹配路由庭呜,然后通過query傳遞參數(shù)
//頁面列表參數(shù)
this.$router.push({
path: '/custome/customeDetailPage',
query: {
name: 'id',
dataObj: id
}
})
//路由配置,name屬性可有可無
{
path: '/custome/customeDetailPage',
component: ''
}
//接受參數(shù)
this.$route.query.dataObj
- 聲明式的導(dǎo)航 <router-link>
- 字符串
<router-link to = "news"></router-link>
- 命名路由
<router-link :to ={name: 'news',params: {userId: id}}></router-link>
- 查詢參數(shù)
<router-link :to ={path: 'news',query: {userId: id}}></router-link>
- 區(qū)別:
- 命名路由搭配params滑进,刷新頁面數(shù)據(jù)會丟失
- 查詢路由搭配query,舒心頁面數(shù)據(jù)不會丟失募谎。
- 命名路由的URL沒有參數(shù)扶关,只有/news
- 查詢路由的Url帶有參數(shù)届垫,/news?id = 111
vuex的mutation action的作用
- mutation:處理的是同步事物谱轨,必須是同步函數(shù)囊咏。
- 要更改vuex的state的狀態(tài)的唯一辦法就是提交mutation谷浅。
- mutation需要遵守的規(guī)則:
- 最好提前在store中初始化好所有所需的屬性
- 需要在對象上添加屬性時使用set或者展開符[...]
- 組件中可以使用
this.$store.commit('xxx')
提交Mutation箫老,或者使用mapMutations輔助函數(shù)
將methods映射為store.commit()
state: {
num: [1,2,3,4]
}
mutations: {
numChange(state){
state.num[0]++
}
}
- action類似于mutation两踏,但是不同于:
- action提交的是Mutation敦冬,而不是直接更改狀態(tài)
- action可以包含異步操作
- action函數(shù)可以接受一個與store實(shí)例具有相同方法和屬性的context對象庶喜,因此可以使用context.commit()提交一個mutation秸架,或者通過context.state或者context.getters來獲取state或getters
- 觸發(fā)action:
this.store.dispatch()
或者mapMutations輔助函數(shù)