目錄
- 閉包
- jwt-token的優缺點
- vue的生命週期
- vue數據雙向綁定的底層實現
- 回調函數,Promise,async/await三者的區別
- Vue-Router模式
- 前端測試和web壓力測試
- XSS和CSRF以及如何防範
- SPA如何計算PV
- js domlist如何轉array
- generator函數和async函數的區別
- css3圓型頭像
- 排序的幾種方法
- 哈希如何解決衝突
- 如何保存路由信息呢,比如刷新?
- 如何實現一個文本和一個輸入框的兩端對齊
1. 閉包
2. jwt-token的優缺點
JWT的優點:
- 體積小,因而傳輸速度更快
- 多樣化的傳輸方式,可以通過
URL
傳輸、POST
傳輸、請求頭Header
傳輸(常用) - 簡單方便,服務端拿到
jwt
後無需再次查詢數據庫校驗token
可用性,也無需進行redis
緩存校驗 - 在分佈式系統中,很好地解決了單點登錄問題
- 很方便的解決了跨域授權問題,因爲跨域無法共享
cookie
JWT的缺點:
- 因爲
JWT
是無狀態的,因此服務端無法控制已經生成的Token
失效,這是不可控的 - 獲取到
JWT
也就擁有了登錄權限,因此JWT
是不可泄露的,網站最好使用https
,防止中間攻擊偷取JWT
實現登錄狀態保持的方法:cookie session token jwt
3. vue的生命週期
每個vue
實例在被創建之前,都要經過一系列的初始化過程,這個過程就是vue
的生命週期。
vue整個生命週期中的鉤子函數如下:
鉤子函數 | 組件狀態 | 最佳實踐 |
---|---|---|
beforeCreate | 實例初始化之後,this指向創建的實例,不能訪問到data,computed,watch,methods上的方法和數據 | 常用於初始化非響應式變量 |
created | 實例創建完成,可訪問data,computed,watch,methods上的方法和數據,未掛載到DOM,不能訪問到el屬性,ref屬性內容爲空數組 | 常用於簡單的ajax請求,頁面的初始化 |
beforeMount | 在掛載開始之前被調用,beforeMount之前,會找到對應的template,並編譯成render函數 | |
mounted | 實例掛載在DOM上,此時可以通過DOM API獲取到DOM節點,$ref屬性可以訪問 | 常用於獲取VNode信息和操作,ajax請求 |
beforeupdate | 響應式數據更新時調用,發生在虛擬DOM打補丁之前 | 適合在更新之前訪問現有的DOM,比如手動移除已添加的事件監聽器 |
updated | 虛擬DOM重新渲染和打補丁之後調用,組件DOM已經更新,可執行依賴於DOM的操作 | 避免在這個鉤子函數中操作數據,可能陷入死循環 |
beforeDestroy | 實例銷燬之前調用。這一步,實例仍然完全可用,this仍能獲取到實例 | 常用於銷燬定時器,解綁全局事件,銷燬插件對象等操作 |
destroyed | 實例銷燬後調用,調用後,Vue實例指示的所有東西都會解綁,所有的事件監聽器會被移除,所有的子實例也會被銷燬 |
注意:
created
階段的ajax
請求與mounted
請求的區別:前者頁面視圖未出現,如果請求信息過多,頁面會長時間處於白屏狀態mounted
不會承諾所有的子組件也都一起被掛載。如果你希望等到整個視圖都渲染完畢,可以用vm.$nextTick
- vue2.0之後主動調用
$destroy()
不會移除dom
節點,作者不推薦直接destroy
這種做法,如果實在需要這樣用可以在這個生命週期鉤子中手動移除dom
節點
4. vue數據雙向綁定的底層實現
vue
實現數據雙向綁定主要是:採用 數據劫持結合發佈者-訂閱者模式的方式,通過 Object.defineProperty()
來劫持各個屬性的setter
,getter
,在數據變動時發佈消息給訂閱者,觸發相應監聽回調。當把一個普通 Javascript
對象傳給 Vue
實例來作爲它的 data
選項時,Vue
將遍歷它的屬性,用 Object.defineProperty()
將它們轉爲getter/setter
。用戶看不到 getter/setter
,但是在內部它們讓 Vue
追蹤依賴,在屬性被訪問和修改時通知變化。
vue
的數據雙向綁定 將MVVM
作爲數據綁定的入口,整合Observer
,Compile
和Watcher
三者,通過Observer
來監聽自己的model
的數據變化,通過Compile
來解析編譯模板指令(vue
中是用來解析 {{}}
),最終利用watcher
搭起observer
和Compile
之間的通信橋樑,達到數據變化 —>視圖更新;視圖交互變化(input
)—>數據model
變更雙向綁定效果。
5. 回調函數,Promise,async/await三者的區別
傳統的回調函數
當一個函數需要依賴上一個回調函數的值的時候,就會形成回調函數嵌套(如setTimeout
,ajax
等)
傳統的回調函數處理方式會產生“回調地獄”,代碼橫向發展
setTimeout(function () {
//do something
setTimeout(function () {
//do something
setTimeout(function () {
//do something
setTimeout(function () {
//do something
}, 1000)
}, 1000)
}, 1000)
}, 1000)
Promise
Promise
(ES2015) 是異步編程的一種解決方案,其實是一個構造函數,自己身上有all、reject、resolve
這幾個方法,原型上有then、catch
等方法。
如下,鏈式操作,代碼縱向發展
let p = new Promise(function(resolve,reject){
resolve(1)
})
p.then(function(value){
console.log(value) // 1
return value*2
}).then(function(value){
console.log(value) // 2
}).then(function(value){
console.log(value) // undefined
return Promise.resolve('resolve')
}).then(function(value){
console.log(value) // resolve
return Promise.reject('reject')
}).then(function(value){
console.log(value)
},function(err){
console.log(err) // reject
})
async/await
儘管Promise
解決了地獄回調問題,但是還是不夠簡潔,一個是橫向發展,一個是縱向發展。
所以ES2017增加了異步函數,async/await
使代碼看起來像是同步的,但它在後臺是異步和非阻塞的。
async
是一個修飾符,async
定義的函數會默認的返回一個Promise
對象resolve
的值,因此對async
函數可以直接進行then
操作,返回的值即爲then
方法的傳入函數
async function funa() {
console.log('a')
return 'a'
}
funa().then( x => { console.log(x) }) // 輸出: a a
async function funp() {
console.log('Promise')
return new Promise(function(resolve, reject){
resolve('Promise')
})
}
funp().then( x => { console.log(x) }) // 輸出: Promise Promise
await
也是一個修飾符,
await
關鍵字 只能放在 async
函數內部, await
關鍵字的作用 就是獲取 Promise
中返回的內容, 獲取的是Promise
函數中resolve
或者reject
的值
如果await
後面並不是一個Promise
的返回值,則會按照同步程序返回值處理
const text1 = () => {
return new Promise(resolve => {
setTimeout(() => resolve('I did something'), 10000)
})
}
const text2 = async () => {
const something = await text1()
return something + ' and I watched'
}
const text3 = async () => {
const something = await text2()
const s = await '啊'
return something + ' and I watched as well'+ s
}
text3().then((res) => {
console.log(res) //I did something and I watched and I watched as well啊
})
6. Vue-Router模式
vue-router
中的模式選項主要在router
實例化的時候定義:
示例代碼:
export default new Router({
mode: 'history', // 兩種類型:history 或者 hash
routes
})
模式 | 優點 | 缺點 |
---|---|---|
hash | 使用簡單,無需後臺支持 | 在url中以hash形式存在,不會傳到後臺 |
history | 地址明確,便於理解和後臺處理 | 需要後臺配合 |
vue-router
默認hash
模式 ;
例如:http://yoursite.com/#/index
,hash
值爲#/index
。hash
模式的特點在於hash
出現在url
中,但是不會被包括在HTTP
請求中,對後端沒有影響,不會重新加載頁面。- 當你使用
history
模式時,URL
就像正常的url
,例如http://yoursite.com/user/id
,相比hash模式更加好看 - 不過這種模式要玩好,還需要後臺配置支持。因爲我們的應用是個單頁客戶端應用,如果後臺沒有正確的配置,當用戶在瀏覽器直接訪問
http://oursite.com/user/id
就會返回 404,這就不好看了。 - 所以呢,你要在服務端增加一個覆蓋所有情況的候選資源:如果
URL
匹配不到任何靜態資源,則應該返回同一個index.html
頁面,這個頁面就是你app
依賴的頁面。
7. 前端測試和web壓力測試
這方面還沒涉及到,好像是使用很多測試工具的樣子,容我緩緩,後續補上。。。
8. XSS和CSRF以及如何防範
9. SPA如何計算PV
單頁面應用 SPA(Single Page Application)
概念: Web
應用即使不刷新也在不同的頁面間切換,解決瀏覽器前進,後退等機制被破壞等問題
實現方法:
Node+Html5
實現React/Vue
等MVVM
框架
頁面訪問量 PV(PageView)
那麼,SPA如何計算PV?
利用 Page Visibility
和History API
來準確統計 Page View
的基本思路如下(這種思路適用於傳統網站、SPA
、PWA
):
- 頁面加載時,如果頁面的
visibilityState
是可見的,發送Page View
統計; - 如果頁面的
visibilityState
是隱藏的,就監聽visibilitychange
事件,並在visibilityState
變爲可見時發送Page View
統計; - 如果
visibilityState
由隱藏變爲可見,並且自上次用戶交互之後已經過了“足夠長”的時間,就發送新的Page View
統計; - 如果
URL
發生變化(僅限於pathname
或search
部分發送變化,hash
部分則應該忽略,因爲它是用來標記頁面內跳轉的) 發送新的Page View
統計;
以上內容來源自:爲什麼你統計 PV 的方式是錯的?感興趣的可以看看
總結: 統計PV
,可以自己寫腳本,可以用別人寫的腳本,也可以使用一些平臺的API
(如:百度統計開放平臺等)
10. js domlist如何轉array
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
var allP = document.querySelectorAll('p')
console.log(allP)
console.log([...allP])
控制檯輸出如下:
我們可以使用擴展運算符將NodeList
對象轉換爲數組:
形式如下:[...document.querySelectorAll('p')]
注意: 擴展運算符實際上調用的是遍歷器接口,如果一個對象沒有部署此接口就無法完成轉換
JS解構和 … 運算符
11. generator函數和async函數的區別
async
函數只能用來處理Promise
,而generator
則可以處理任何函數async
函數返回Promise
;generator
返回{ value, done }
類型的對象generator
屬於一種生成器,用來生成Iterator
對象,在配合co
的時候能用來解決異步- 而
async
則是爲了更簡潔的使用Promise
而提出的語法,專門爲了解決異步而提出
12. css3圓型頭像
如果圖片是正方形,直接設置圖片的寬高和border-radius
<img src="img/favicon.png" alt="">
img{
width:50px;
height: 50px;
border-radius: 25px;
}
如果圖片不是正方形,可以使用CSS背景圖片來顯示
<div class="img"></div>
.img{
width:50px;
height: 50px;
border-radius: 25px;
background: url("img/img78.jpg") no-repeat center;
background-size:50px;
}
background
相關屬性,自行百度
13. 排序的幾種方法
14. 哈希如何解決衝突
誒呦我去,後續補上,感興趣的自行百度!
15. 如何保存路由信息呢,比如刷新?
問題: Vue
單頁面應用中,在某個具體頁面下點擊刷新,那麼刷新後,頁面的狀態信息可能就會丟失掉
解決辦法: 監聽頁面的加載和刷新;頁面加載時,讀取sessionStorage
裏的狀態信息到vuex
;頁面刷新時,讀取vuex
裏的信息保存到sessionStorage
;
在App.vue
的created
鉤子函數裏寫:
created () {
//在頁面加載時讀取sessionStorage裏的狀態信息
if (sessionStorage.getItem("store") ) {
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("store"))))
}
//在頁面刷新時將vuex裏的信息保存到sessionStorage裏
window.addEventListener("beforeunload",()=>{
sessionStorage.setItem("store",JSON.stringify(this.$store.state))
})
}
16. 如何實現一個文本和一個輸入框的兩端對齊
可以添加兩個空格轉義符&nbap;
來到達此效果
label{
display: inline-block;
width:50px;
}
<form action="">
<label for="username">用戶名</label>
<input type="text" id="username">
<br/>
<label for="password">密 碼</label>
<input type="password" id="password">
</form>