Vue 實例有一個完整的生命週期,也就是從開始建立、初始化數據、編譯模版、掛載Dom -> 渲染、更新 -> 渲染、卸載等一系列過程,咱們稱這是Vue的生命週期
生命週期 | 描述 |
---|---|
beforeCreate | 組件實例被建立之初,組件的屬性生效以前 |
created | 組件實例已經徹底建立,屬性也綁定,但真實dom尚未生成,$el還不可用 |
beforeMount | 在掛載開始以前被調用:相關的 render 函數首次被調用 |
mounted | el 被新建立的 vm.$el 替換,並掛載到實例上去以後調用該鉤子 |
beforeUpdate | 組件數據更新以前調用,發生在虛擬 DOM 打補丁以前 |
update | 組件數據更新以後 |
activited | keep-alive專屬,組件被激活時調用 |
deadctivated | keep-alive專屬,組件被銷燬時調用 |
beforeDestory | 組件銷燬前調用 |
destoryed | 組件銷燬後調用 |
vue 雙向數據綁定是經過 數據劫持
結合 發佈訂閱模式
的方式來實現的,也就是說數據和視圖同步,數據發生變化,視圖跟着變化,視圖變化,數據也隨之發生改變; 核心:Object.defineProperty()
方法。javascript
v-model
本質上是語法糖,v-model在內部爲不一樣的輸入元素使用不一樣的屬性並拋出不一樣的事件css
<input v-model="sth" /><!-- 兩者等價 --> <input :value="sth" @input="sth = $event.target.value" /> 複製代碼
設置在自組件內部的插槽
像一個盒子,位置由子組件決定,放什麼內容由父組件決定。html
實現了內容分發,提升了組件自定義的程度,讓組件變的更加靈活前端
無需name
屬性,取子組件肚子裏第一個元素節點做爲默認插槽。vue
<!-- 子組件,組件名:child-component --> <div class="child-page"> <h1>子頁面</h1> <slot></slot> <!-- 替換爲 <p>hello,world!</p> --> </div> <!-- 父組件 --> <div class="parent-page"> <child-component> <p>hello,world!</p> </child-component> </div> <!-- 渲染結果 --> <div class="parent-page"> <div class="child-page"> <h1>子頁面</h1> <p>hello,world!</p> </div> </div> 複製代碼
在多個插槽的狀況下使用,利用name
標識插槽。java
<!-- 子組件,組件名:child-component --> <div class="child-page"> <h1>子頁面</h1> <slot name="header"></slot> <slot></slot> <!-- 等價於 <slot name="default"></slot> --> <slot name="footer"></slot> </div> <!-- 父組件 --> <div class="parent-page"> <child-component> <template v-slot:header> <p>頭部</p> </template> <template v-slot:footer> <p>腳部</p> </template> <p>身體</p> </child-component> </div> <!-- 渲染結果 --> <div class="parent-page"> <div class="child-page"> <h1>子頁面</h1> <p>頭部</p> <p>身體</p> <p>腳部</p> </div> </div> 複製代碼
子組件給父組件傳遞數據。react
<!-- 子組件,組件名:child-component --> <div class="child-page"> <h1>子頁面</h1> <slot name="header" data="data from child-component."></slot> </div> <!-- 父組件 --> <div class="parent-page"> <child-component> <template v-slot:header="slotProps"> <p>頭部: {{ slotProps.data }}</p> </template> </child-component> </div> <!-- 渲染結果 --> <div class="parent-page"> <div class="child-page"> <h1>子頁面</h1> <p>頭部: data from child-component.</p> </div> </div> 複製代碼
Vue與AngularJS的區別webpack
Watcher
越多越慢;Vue.js使用基於依賴追蹤
的觀察而且使用異步隊列
更新,全部的數據都是獨立觸發的。Vue與React的區別es6
props
是能夠動態變化的,子組件也實時更新,在react中官方建議props要像純函數那樣,輸入輸出一致對應,並且不太建議經過props來更改視圖;插槽
分發內容,使得能夠混合父組件的內容與子組件本身的模板;指令系統
,讓模版能夠實現更豐富的功能,而React只能使用JSX語法;computed
和watch
,而在React中須要本身寫一套邏輯來實現;all in js
,經過js來生成html,因此設計了jsx,還有經過js來操做css,社區的styled-component、jss等;而 vue是把html,css,js組合到一塊兒,用各自的處理方式,vue有單文件組件,能夠把html、css、js寫到一個文件中,html提供了模板引擎來處理。redux
的combineReducer
就對應vuex
的modules
, 好比reselect就對應vuex的getter和vue組件的computed, vuex的mutation是直接改變的原始數據,而redux的reducer是返回一個全新的state,因此redux結合immutable來優化性能,vue不須要。redux-form
,組件的橫向拆分通常是經過高階組件。而vue是數據可變的,雙向綁定,聲明式的寫法,vue組件的橫向拆分不少狀況下用mixin
$route
和$router
的區別路由信息對象
,包括path,params,hash,query,fullPath,matched,name等路由信息參數。路由實例
對象包括了路由的跳轉方法,鉤子函數等。編碼階段web
data
中的數據,data
中的數據都會增長getter
和setter
,會收集對應的watcher
v-if
和v-for
不能連用v-for
給每項元素綁定事件時使用事件代理SPA
頁面採用keep-alive
緩存組件key
保證惟一SEO優化
SSR
,nuxt.js
打包優化
Tree Shaking/Scope Hoisting
cdn
加載第三方模塊happypack
splitChunks
抽離公共文件sourceMap
優化用戶體驗
PWA
漸進式Web應用,使用多種技術來加強web app的功能,讓網頁應用呈現和原生應用類似的體驗。
還可使用緩存(客戶端緩存、服務端緩存)優化、服務端開啓
gzip
壓縮等。
核心緣由:粒度
React
經過setState
知道有變化了,但不知道哪裏變化了,因此須要經過diff
找出變化的地方並更新dom。Vue
已經能夠經過響應式系統知道哪裏發生了變化,可是全部變化都經過響應式會建立大量Watcher
,極其消耗性能,所以vue採用的方式是經過響應式系統知道哪一個組件發生了變化,而後在組件內部使用diff
。這樣的中粒度策略,即不會產生大量的Watcher,也使diff的節點減小了,一箭雙鵰。編譯的核心是把 template 模板編譯成 render 函數,主要分爲以下三個步驟:
MVVM
是Model-View-ViewModel
縮寫,也就是把MVC
中的Controller
演變成ViewModel
。Model
層表明數據模型,View
表明UI組件,ViewModel是View和Model層的橋樑,數據會綁定到viewModel層並自動將數據渲染到頁面中,視圖變化的時候會通知viewModel層更新數據。
Vue2.x
在初始化數據時,會使用Object.defineProperty
從新定義data
中的全部屬性,當頁面使用對應屬性時,首先會進行依賴收集
(收集當前組件的watcher),若是屬性發生變化會通知相關依賴進行派發更細
(發佈訂閱模式)。
vue3.0
採用es6
中的proxy
代替Object.defineProperty
作數據監聽。
Proxy的優點以下:
Object.defineProperty的優點以下:
$nextTick
在下次 DOM
更新循環結束以後執行延遲迴調。nextTick
主要使用了宏任務和微任務。根據執行環境分別嘗試採用
定義了一個異步方法,屢次調用nextTick會將方法存入隊列中,經過這個異步方法清空當前隊列。
複用組件的時候,都會返回一份新的data,至關於每一個組件實例都有本身私有的數據空間,不會共享同一個data
對象。
props
$emit
、ref
EventBus
vue-router
是vue的官方插件,主要用來管理前端路由。 對於 Vue 這類漸進式前端開發框架,爲了構建 SPA(單頁面應用),須要引入前端路由系統,這也就是 Vue-Router 存在的意義。前端路由的核心,就在於:改變視圖的同時不會向後端發出請求。
功能有:
1. 實現原理
hash 模式和 history 模式都屬於瀏覽器自身的特性,Vue-Router 只是利用了這兩個特性(經過調用瀏覽器提供的接口)來實現前端路由。
2. 對比表格
區別 \ mode | hash | history |
---|---|---|
監聽事件 | hashChange | popstate |
缺點 | # 號很差看 | 子路由刷新40四、ie9及如下不兼容 |
push操做 | window.location.assign | window.history.pushState |
replace操做 | window.location.replace | window.history.replaceState |
訪問操做 | window.history.go | window.history.go |
後退操做 | window.history.go(-1) | window.history.go(-1) |
向前操做 | window.history.go(1) | window.history.go(1) |
3. 關於 popstate 事件監聽路由的侷限 history對象的 back(), forward() 和 go() 三個等操做會主動觸發 popstate 事件,可是 pushState 和 replaceState 不會觸發 popstate 事件,這時咱們須要手動觸發頁面跳轉(渲染)。
4. 關於子路由刷新的解決方式
history
模式子路由刷新會404,所以須要後端配合,將未匹配到的路由默認指向html
文件
5. 瀏覽器(環境)兼容處理
history 模式中pushState
、replaceState
是HTML5
的新特性,在 IE9
下會強行降級使用 hash
模式,非瀏覽器環境轉換成abstract
模式。
6. router-link router-link
點擊至關於調用$router.push
方法去修改url
<router-link>
比起寫死的 <a href="...">
會好一些,理由以下:
像 vue 這種單頁面應用,若是沒有路由懶加載,運用 webpack 打包後的文件將會很大,形成進入首頁時,須要加載的內容過多,出現較長時間的白屏,運用路由懶加載則能夠將頁面進行劃分,須要的時候才加載頁面,能夠有效的分擔首頁所承擔的加載壓力,減小首頁加載用時。
vue 路由懶加載有如下三種方式:
1. vue 異步組件 這種方法主要是使用了 resolve 的異步機制,用 require 代替了 import 實現按需加載
export default new Router({ routes: [ { path: '/home',', component: (resolve) => require(['@/components/home'], resolve), }, { path: '/about',', component: (resolve) => require(['@/components/about'], resolve), }, ], }) 複製代碼
2. ES6 的 import() vue-router 在官網提供了一種方法,能夠理解也是爲經過 Promise 的 resolve 機制。由於 Promise 函數返回的 Promise 爲 resolve 組件自己,而咱們又可使用 import 來導入組件。
export default new Router({ routes: [ { path: '/home', component: () => import('@/components/home'), }, { path: '/about', component: () => import('@/components/home'), }, ], }) 複製代碼
1. webpack 的 require.ensure() 這種模式能夠經過參數中的 webpackChunkName 將 js 分開打包。
export default new Router({ routes: [ { path: '/home', component: (resolve) => require.ensure([], () => resolve(require('@/components/home')), 'home'), }, { path: '/about', component: (resolve) => require.ensure([], () => resolve(require('@/components/about')), 'about'), }, ], }) 複製代碼
篇幅有限,還有沒有發出來的題目都前端面試題資料裏,須要完整PDF資料的小夥伴只須要點擊這裏就能夠免費獲取!
有被問到題目的小夥伴們評論區能夠聊聊你是怎麼回答的哦,沒有被問到的更要多看熟記,說不定就會碰到啦~這篇文章對你有幫助請評論點贊支持一波,謝謝!