整理中高級前端系列,能夠看成面試複習,也能夠看成實戰來看,分享一下 方便本身,方便他人。有不足的地方歡迎評論~css
第二趴:js進階vue
第三趴:vue框架進階node
第四趴:工程化react
優勢:面試
缺點:算法
vue.js 是採用數據劫持結合發佈者-訂閱者模式的方式,經過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變更時發佈消息給訂閱者,觸發相應的監聽回調。segmentfault
Vue實現這種數據雙向綁定的效果,須要三大模塊:數組
組件通訊:
這個插件是必須的! 將你定義過的其餘規則賦址並應用到 .vue文件裏相應語言的塊。例如:你有一條匹配/\.js$/
的規則,那麼它會應用到 .vue文件裏的 <script>
塊
window.addEventListener("hashchange", funcRef, false)
hash(window.location.hash)
都會在瀏覽器的訪問歷史中增長一個記錄利用這幾點特性,就能夠實現前端路由 【更新視圖但不從新請求頁面】的功能了
HashHistory.push()
從設置路由改變到視圖更新的流程以下: $router.push() --> HashHistory.push() --> History.transitionTo() --> History.updateRoute() --> {app._route = route} --> vm.render()
HashHistory.replace()
其實和push()相似,不一樣就是 替換掉當前路由,調用的是window.location.replace方法。
利用HTML5中新增的方法pushState\replaceState
window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
複製代碼
實現原理:代碼結構以及更新視圖的邏輯與hash模式基本相似,只不過將對window.location.hash
直接進行賦值window.location.replace()
,改成了調用history.pushState()和history.replaceState()
方法。
咱們設置在state中的屬性會被存儲在根元素中, this._modules = new ModuleCollection(options)
//初始化
const state = this._modules.root.state
// 獲取定義的state
vuex初始化時先去獲取定義在state屬性的值 new ModuleCollection(options)
進行模塊收集(從新組裝 store中的相關屬性),最終造成一顆module樹。
視圖經過點擊事件,觸發 mutattions中的方法,能夠更改state中的數據,此時 getters把數據反映到視圖。
那麼action 能夠理解是 爲了處理異步,單純多加的一層。
在vue中 咱們觸發 click事件,就能觸發 methods中的方法。可是 vuex就不行,必定要有個東西來觸發才行,就至關於自定義事件on\emit。
關係就是,經過dispatch來觸發actions中得方法,action中commi去觸發mutions中方法。
Proxy的優點:
Object.defineProperty
只能遍歷對象屬性直接修改Object.defineProperty的優點以下:
Virtual DOM是對DOM的抽象,本質上是JavaScript對象,這個對象就是更加輕量級的對DOM的描述.
Virtual DOM最初的目的,就是更好的跨平臺,好比Node.js就沒有DOM,若是想實現SSR(服務端渲染),那麼一個方式就是藉助Virtual DOM,由於Virtual DOM自己是JavaScript對象.
現代前端框架的一個基本要求就是無須手動操做DOM, 一方面是由於手動操做DOM沒法保證程序性能,多人協做的項目中若是review不嚴格,可能會有開發者寫出性能較低的代碼, 另外一方面更重要的是省略手動DOM操做能夠大大提升開發效率.
一、須要一個**函數建立單個Virtual DOM **,這個函數很簡單,接受必定的參數,再根據這些參數返回一個對象,這個對象就是DOM的抽象.
/**
* 生成 vnode
* @param {String} type 類型,如 'div'
* @param {String} key key vnode的惟一id
* @param {Object} data data,包括屬性,事件等等
* @param {Array} children 子 vnode
* @param {String} text 文本
* @param {Element} elm 對應的 dom
* @return {Object} vnode
*/
function vnode(type, key, data, children, text, elm) {
const element = {
__type: VNODE_TYPE,
type, key, data, children, text, elm
}
return element
}
複製代碼
二、DOM實際上是一個Tree,咱們接下來要作的就是聲明一個函數用於建立DOM Tree的抽象 -- Virtual DOM Tree.
三、Virtual DOM 歸根究竟是JavaScript對象,咱們得想辦法將Virtual DOM與真實的DOM對應起來,也就是說,須要咱們聲明一個函數,此函數能夠將vnode轉化爲真實DOM.
四、Virtual DOM 的 diff纔是整個Virtual DOM 中最難理解也最核心的部分,diff的目的就是比較新舊Virtual DOM Tree找出差別並更新.
snabbdom.js已是社區內主流的Virtual DOM實現了**,vue 2.0階段與snabbdom.js同樣**都採用了上面講解的 「雙端比較算法」,那麼有沒有一些優化方案可使其更快?
其實,社區內有更快的算法,例如inferno.js就號稱最快react-like框架(雖然inferno.js性能強悍的緣由不只僅是算法,可是其diff算法的確是目前最快的),而vue 3.0就會借鑑inferno.js的算法進行優化.
diff算法的過程當中,先會進行新舊節點的首尾交叉對比,當沒法匹配的時候會用新節點的key
與舊節點進行比對,而後超出差別.
快速: key的惟一性能夠被Map數據結構充分利用,相比於遍歷查找的時間複雜度O(n),Map的時間複雜度僅僅爲O(1).
將回調延遲到下次DOM更新循環以後執行。在修改數據以後當即使用它,而後等待DOM更新。
<template>
<div id="example">{{message}}</div>
</template>
<script>
var vm = new Vue({
el: '##example',
data: {
message: '123'
}
})
vm.message = 'new message' // 更改數據
console.log(vm.$el.innerHTML) // '123'
Vue.nextTick(function () {
console.log(vm.$el.innerHTML) // 'new message'
})
</script>
複製代碼
在上面這個例子中,當咱們經過vm.message = 'new message'
更新數據時,此時該組件不會當即從新渲染。當刷新事件隊列時,組件會在下一個事件循環「tick」中從新渲染。因此當咱們更新完數據後,此時又想基於更新後的DOM
狀態來作點什麼,此時咱們就須要使用Vue.nextTick(callback)
,把基於更新後的DOM
狀態所須要的操做放入回調函數callback
中,這樣回調函數將在DOM
更新完成後被調用。
vue異步執行DOM更新
此點其實在說的是 白屏問題,白屏時間就是 當用戶地址欄按下確認鍵開始到首次內容繪製(即看到第一個內容)。 因此 解決 白屏問題 纔是關鍵 優化點。 ** 咱們先梳理下白屏時間內發生了什麼:
同窗以爲有幫助的能夠點個贊哈,以示鼓勵 😊