資源下載站 wordpress軟文營銷ppt
vue面試題
MVVM
-
概念
model view viewModel
本質(zhì)上是mvc(程序分層開發(fā)思想)
將viewModel的狀態(tài)和行為抽象化,viewmodel將視圖ui和業(yè)務(wù)邏輯分開,去除model的數(shù)據(jù),同時處理view中需要展示的內(nèi)容和業(yè)務(wù)邏輯 -
view視圖層
html和css構(gòu)成
展示頁面和承載數(shù)據(jù) -
model數(shù)據(jù)模型
axios請求的部分、數(shù)據(jù)和業(yè)務(wù)邏輯的處理
后端進行數(shù)據(jù)操作和業(yè)務(wù)邏輯處理 -
viewModel視圖模型
前端人員生成和維護 視圖和數(shù)據(jù)層,承上啟下
處理view上的事件和輸入,轉(zhuǎn)化為對model的操作;model層獲取數(shù)據(jù),在view層進行數(shù)據(jù)處理、重構(gòu)、渲染 -
MVVM特點
-
低耦合,內(nèi)容可以獨立分成單獨模塊,model和view互不影響
-
可復用性較強
-
分層開發(fā),提高開發(fā)效率
-
測試容易
-
增加了應(yīng)用程序的復雜性,雙向數(shù)據(jù)綁定可能造成額外的開銷
單頁面應(yīng)用
-
概念
SPA,加載單個html頁面,在用戶與應(yīng)用程序交互時,動態(tài)更新頁面 -
工作原理
- 瀏覽器發(fā)送請求,服務(wù)器返回index.html
- index.html中的js腳本控制顯示頁面
- 通過路由,在頁面顯示不同的模板和數(shù)據(jù),調(diào)用切換僅返回json數(shù)據(jù)
- 應(yīng)用程序通過json動態(tài)更新頁面,頁面不會重新加載
- 優(yōu)點
- 前后端分離,開發(fā)效率高
- 用戶體驗好,無需重新加載頁面,同一套后端程序可以支持web、手機等
- 組件化,可復用性
- 減輕服務(wù)器壓力
- 缺點
- 首頁加載較慢
- 導航功能無法使用瀏覽器自帶的頁面前進、后退
- 不利于SEO(因為頁面內(nèi)容是異步請求顯示的)
vue2和vue3的區(qū)別
雙向綁定數(shù)據(jù)的原理不同
- vue2:通過Object.defineProperty實現(xiàn)
//數(shù)據(jù)更新,但是視圖沒更新
//添加下面的代碼用來更新視圖
this.$set(this.data, 'name', 'newName')
-
vue3:通過Proxy實現(xiàn)
-
defineProperty和Proxy的異同
- defineProperty改變對象的內(nèi)部屬性描述符
- proxy創(chuàng)建新代理對象,對原始對象的操作都重定向到這個代理對象上
- defineProperty只能修改對象本身,而proxy可以修改對象本身和原型鏈上的屬性
生命周期不同
-
vue2:beforeCreate created beforeMount mounted beforeUpdate updated beforeDestory destroyed
-
vue3:setup onBeforeMount onMounted onBeforeUpdate onUpdated onBeforeUnmount onUnmounted
keep-alive中多兩個鉤子函數(shù)
onActivated
onDeactivated
父子傳值不同
- vue2:props this.$emits
- vue3:props defineEmits
API選型不同
- vue2是選項式API,代碼中分割不同屬性 data methods computed …
- vue3是組合式API
vue3支持多根節(jié)點,vue2只支持單根節(jié)點
數(shù)據(jù)定義
vue2在data中定義,vue3使用ref或reactive
數(shù)據(jù)雙向綁定原理
了解常用方法
- reduce
-
參數(shù):(第一個值/上次計算的結(jié)果,當前項目,當前項目下標,調(diào)用的數(shù)組)
-
求和
const total=arr.reduce((a,b)=>a+b) -
鏈式獲取對象屬性
const a=arr.reduce((newObj,k)=>{//每次調(diào)用之后的newObj都是上一次返回的結(jié)果return newObj[k]
})
-
發(fā)布訂閱模式
-
名詞
setter屬性 -> set方法 有參,無需return
getter屬性 -> get方法 無參
用來訪問和設(shè)置對象的屬性 -
object.defineProperty
可以定義新屬性或修改原有屬性
參數(shù):defineProperty(目標對象,屬性名,特性)
Object.defineProperty(obj,'name',{//當前屬性可以被循環(huán)遍歷enumerable:true,//當前屬性允許被設(shè)置configurable:true,//get方法get(){return 1},//setset(newVal){console.log('set',newVal)}
})
在設(shè)置或獲取屬性的時候,自動調(diào)用其中的get和set方法
33:54
插槽
-
概念:決定將所攜帶的內(nèi)容插入到某個指定的位置,模板在父組件中定義,傳遞到子組件顯示
-
默認插槽
-
具名插槽
-
作用域插槽
數(shù)據(jù)在子組件上,但是表現(xiàn)由父組件決定
<template #name=“{data}”>
混入mixin
-
概念:可復用的代碼片段,包含函數(shù)/功能/輔助的業(yè)務(wù)邏輯,寫在單獨的文件中
-
使用
定義在src/mixins/minxin.js中,導出function
在組件中導入mixin,解構(gòu)其中值,可以讀取數(shù)據(jù)和調(diào)用函數(shù)
注意:混入中的數(shù)據(jù)不共享
-
優(yōu)點:使用方便,減少重復代碼,可以實現(xiàn)復雜的業(yè)務(wù)邏輯
-
缺點:組件之間不能共享數(shù)據(jù);混入的變量和方法很難找到來源;多個mixin容易引起沖突
nextTick
-
概念:下次DOM更新循環(huán)結(jié)束之后,延遲回調(diào)函數(shù)執(zhí)行
-
異步更新隊列
vue觀察到更新數(shù)據(jù)后,不是直接更新dom,而是開啟隊列,緩存數(shù)據(jù)并去重,避免不必要的計算和更新
keep-alive
-
緩存組件,避免重復渲染
-
優(yōu)勢:組件切換過程中將狀態(tài)保存在內(nèi)存中,防止重復渲染DOM,減少加載時間和性能消耗,提高用戶體驗
-
使用router-view
<!-- vue3寫法 -->
<router-view v-slot="{Component}"><!-- 控制只緩存home --><keep-alive include="homt"><Component :is="Component" /></keep-alive>
</router-view>
-
控制緩存頁面
include:只緩存xx
exclude:排除xx
max:最大緩存數(shù) -
激活新鉤子函數(shù)
- onActivated 激活組件時
- onDeactivated 停用組件時
vuex和pinia
vuex使用
- 基礎(chǔ)
import { useStore } from 'vuex'
const store = useStore()
調(diào)用mutation 要用commit
調(diào)用action 要用dispatch
數(shù)據(jù)持久化使用vuex-persistedstate
- 常用方法
state:數(shù)據(jù)源
getters:返回被依賴的數(shù)據(jù)
mutations:同步更新數(shù)據(jù)源
actions:異步更新數(shù)據(jù)源
module:對多模塊進行管理
pinia使用
- 基礎(chǔ)使用
import {defineStore} from 'pinia'export default defineStore('name',()=>{const name="jack"return {name}
},{//持久化persist:true
})
vuex和pinia的區(qū)別
-
方法區(qū)別
vuex:state getters mutations actions module
pinia:state getters actions -
pinia調(diào)用更方便,可以直接對數(shù)據(jù)進行讀寫,不需要commit和dispatch
-
vuex中缺少模塊屬性支持,pinia中支持
-
pinia有更好的ts支持
vue源碼
目錄分析
- src/compiler 模板解析和編譯相關(guān)的文件
- src/core 核心文件,包括vue架構(gòu)、內(nèi)置組件、全局API封裝等
- src/platforms 平臺相關(guān)文件
- src/server 服務(wù)端渲染相關(guān)文件
- src/sfc .vue的解析文件
- src/shared 公共工具
過程
-
npm run server之后,創(chuàng)建一個new Vue實例 --> 最核心是用到了instance/index
-
function vue 為什么不是class,因為有mixins或其他的公共方法,都在vue.prototype上,而new Vue實例,就相當于一個對象,所以用function
-
三種渲染方式:render template el,最終都得到render函數(shù)
render函數(shù)通過watcher綁定,數(shù)據(jù)發(fā)生變化時,執(zhí)行update方法,調(diào)用vm._render(),產(chǎn)生虛擬DOM,patch對比新舊vnode,diff算法增刪改真正的DOM元素 -
instance/init做了什么
- 為當前vue實例(vm)添加唯一uid
- vm._isVue設(shè)置為true(監(jiān)聽對象變化時過濾vm)
- 初始化組件
- 初始化各種內(nèi)容,包括生命周期,事件,虛擬DOM等
- 如果有el屬性,就調(diào)用vm.$mount掛載vue實例
vue渲染小結(jié)
- new vue執(zhí)行初始化
- 掛載$mount,通過render函數(shù)生成渲染樹
- watcher監(jiān)聽數(shù)據(jù)變化
- 數(shù)據(jù)變化時,render函數(shù)生成vnode
- 通過patch對新舊node進行比較,通過diff算法,增刪改dom
為什么vue3性能比vue2好
- vue3向下兼容vue2,官方測試:vue3打包速度比vue2快41%,初次渲染提升50%,內(nèi)存使用減少50%;一些基礎(chǔ)API和方法進行了優(yōu)化
- vue3在setup中的函數(shù)和變量優(yōu)化了程序副作用
- vue2劫持數(shù)據(jù)使用defineProperty+發(fā)布訂閱模式實現(xiàn),數(shù)組和新增屬性需要額外開銷;vue3使用proxy進行數(shù)據(jù)代理,實現(xiàn)整個對象進行響應(yīng)式觀測,數(shù)據(jù)變化不需要額外開銷
- vue3在依賴手機、程序運行做了性能優(yōu)化,還增加了異步渲染和懶加載的特性
代理和環(huán)境變量
-
代理:接口數(shù)據(jù)請求中,由于違反同源策略,導致cors跨域問題,需要配置代理,在vue.config.js中,添加devserver配置項及參數(shù)
-
環(huán)境變量:開發(fā)中使用開發(fā)環(huán)境,打包上線后使用生產(chǎn)環(huán)境
process.env.環(huán)境變量名稱
computed和watch
- computed計算屬性
必須有返回值,不支持異步,返回值會緩存,初始化會執(zhí)行
const nums=computed(()=>{return num.value*2
})
- watch
被監(jiān)聽的數(shù)據(jù)變化時,watch執(zhí)行,初始化不會執(zhí)行
watch(num,(newValue,oldValue)=>{console.log(oldValue,newValue)
})
- 區(qū)別
- computed必須有return,watch無需
- computed不支持異步,watch支持
- computed初始化執(zhí)行,watch不執(zhí)行
- computed會緩存數(shù)據(jù),watch不會
vue2和vue3響應(yīng)式的區(qū)別
- vue2:defineProperty+發(fā)布訂閱模式實現(xiàn)
在對象上定義新屬性或修改現(xiàn)有對象的屬性
三個參數(shù):target,key,descriptor
Object.defineProperty(定義屬性的對象,屬性名稱,屬性描述)
缺點:遞歸遍歷對象屬性,消耗大;新增或刪除屬性不能立即響應(yīng),需要通過額外的方法(比如this.$set);數(shù)組修改也需要額外方法
- vue3:proxy實現(xiàn)
攔截對象中任何屬性變化,可以隨時監(jiān)聽
需要兩個參數(shù) proxy(代理的目標對象,對象的handler處理函數(shù))
實現(xiàn)了深層檢測
formily自定義組件,子組件通知父組件更改數(shù)據(jù)
- 使用formily的field.set方法直接設(shè)置當前表單域的值,并通知父組件更新
- 使用vue的v-model綁定子組件,子組件通過props的modelValue和emit方法通知父組件更新
- 使用attrs的listeners,通知父組件更新
listeners存儲所有未被聲明為prop的事件監(jiān)聽器
底層是基于js的事件機制和proxy實現(xiàn),vue在編譯階段收集事件監(jiān)聽器,運行時通過attrs.listeners觸發(fā)
diff算法
-
應(yīng)用場景:虛擬dom渲染為真實dom的新舊VNode節(jié)點比較
-
比較方式:深度優(yōu)先、同層比較
-
原理:數(shù)據(jù)發(fā)生變化時,set調(diào)用Dep.notify通知訂閱者,訂閱者調(diào)用patch給真實的DOM打補丁
- 如果isSameVnode相同,調(diào)用patchVnode
vue性能優(yōu)化
- 選用正確的架構(gòu),避免部署純客戶端的SPA(存在首屏加載緩慢的問題),可以通過SSR或SSG緩解
- 壓縮js打包文件體積,許多vue的API是可以被tree-shake的;按需引入依賴項
- 代碼分割:構(gòu)建工具將js包拆分為多個小的,可以按需加載或并行加載的文件,vite默認支持
- props穩(wěn)定性:vue組件中,一個子組件只會在至少一個props改變時才更新
比如一個list列表,其中很多l(xiāng)istitem組件,根據(jù)active-id判斷當前組件是否是選中的激活組件,如果active-id改變,每個組件都會重新更新!可以改為 :active=“item.id === activeId” - v-once 只渲染一次,不響應(yīng)數(shù)據(jù)變化,v-memo跳過大型子樹或v-for列表更新
- 列表虛擬化,比如vue-virtual-scroll
- 減少大型不可變數(shù)據(jù)的響應(yīng)性開銷,可以通過shallowRef 和 shallowReactive 來繞開深度響應(yīng)
- 避免不必要的組件抽象,組件實例比普通DOM節(jié)點昂貴的多