這篇文章為大家總結分享一些Vue面試題(附答案解析),帶你梳理基礎知識,增強Vue知識儲備,值得收藏,快來看看吧!
#答案想法:
#回答範例:
生命週期這個詞應該是很好理解的,在我們生活中就會常常碰到,例如談到一個人的生命週期,我們會說人這一生會經歷嬰兒、兒童、青少年、青年、中年、老年這幾個階段。
而Vue
的生命週期也是如此,在Vue
中的每個元件都會經歷從建立到掛載到更新再到銷毀這幾個階段,而在這些階段中,Vue
會運行一種叫做生命週期鉤子的函數,方便我們在特定的階段有機會添加我們自己的程式碼。
Vue 生命週期總共可以分為8
各階段:建立前後、掛載前後、更新前後、銷毀前後,以及一些特殊場景的生命週期(keep-alive
激活時、捕獲後代組件錯誤時)。 Vue3
中也新增了三個用於偵錯和服務端渲染場景。
這幾個階段對應的鉤子函數API依序為:#beforeCreate
create
beforeMount
#mounted
beforeUpdate
updated
activated(keep-alive 啟動時呼叫)
deactivated(keep-alive 停用時呼叫)
beforeDestory
destoryed
errorCaptured(捕獲子孫元件錯誤時呼叫)
。
在Vue3 中的變化絕大多數只要加上前綴on 即可,例如mounted
變成onMounted
,除了beforeDestroy
和destroyed
被重新命名為 beforeUnmount
# 和unMounted
(這樣與前面的beforeMount
和mounted
對應,強迫症表示很讚?)
beforeCreate
# 在元件建立前調用,通常用於外掛程式開發中執行一些初始化任務; created
元件建立完畢調用,可以存取各種數據,請求介面資料等;mounted
元件掛載時調用可以存取資料、dom
元素、子元件等;beforeUpdate
更新前呼叫此時view
層尚未更新,可用來取得更新前的各種狀態;updated
完成更新時調用此時view層已經完成更新,所有狀態已經是最新的了;beforeUnmount
實例被銷毀前調用,可用於一些定時器或訂閱的取消;unMounted
銷毀一個實例時調用可以清理與其他實例的鏈接,解綁它的全部指令以及事件監聽器。
在Vue3 中:setup
是比created
先執行的;而且沒有 beforeCreate
和 created
。
權限管理一般需求就是對頁面權限和按鈕權限的管理
具體實作的時候分前端實作與後端實作兩種方案:
前端方案會把所有路由資訊在前端配置,透過路由守衛要求使用者登錄,使用者登入後根據角色過濾出路由表,然後在動態加入路由。例如我會設定一個asyncRoutes
數組,需要認證的頁面在路由的meta
中加入一個#roles
字段,等取得使用者角色之後取兩者的交集,若結果不為空則說明可以存取。過濾結束後剩下的路由就是使用者能存取的頁面,最後透過 router.addRoutes(accessRoutes)
方式動態加入路由即可。
後端方案會把所有頁面路由資訊存在資料庫中,使用者登入的時候會根據其角色查詢得到其能存取的所有路由資訊回傳給前端,前端再透過addRoute
動態新增路由資訊。
按鈕權限的控制通常會實作一個指令,例如v-permission
,將按鈕要求角色透過值傳給 v-permission
指令,在指令的mounted
鉤子中可以判斷目前使用者角色和按鈕是否存在交集,有就保留按鈕,沒有就移除按鈕。
純前端方案的優點是實作簡單,不需要額外權限管理頁面,但是維護起來問題比較大,有新的頁面和角色需求就要修改前端程式碼和重新打包部署;服務端方案就不存在這個問題,透過專門的角色和權限管理頁面,配置頁面和按鈕權限信息到資料庫,應用每次登陸時所獲取的都是最新的路由資訊。
自己的話:權限管理一般分頁面權限和按鈕權限,而具體實現方案又分前端實現和後端實現,前端實現就是會在前端維護一份動態的路由數組,透過使用者登入後的角色來篩選它所擁有權限的頁面,最後透過addRoute
將動態加入router
中;而後端實現的不同點就是這些路由是後端回傳給前端,前端再動態加入進去的。
按鈕權限一般會實作一個 v-permission
,透過判斷使用者有沒有權限來控制按鈕是否顯示。
純前端方案的優點是實現簡單,但是維護問題大,有新的頁面和角色需求都需要改程式碼重新打包部署,服務端則不存在這個問題。
#回答思路:
回答:
v-model ,它可以綁定一個響應式數據到視圖,同時視圖中變化也能改變該值。
v-model 是語法糖,它的原理(預設請情況下)就是透過
:value 將變數掛到
dom 上,再透過
input事件監聽
dom 的變化改變變數的值。使用
v-model的好處是方便呀,減少了大量的繁瑣的事件處理,提高開發效率。
v-model,也可以在自訂元件上使用,表示某個值得輸入和輸出控制。
modelValue 的屬性和
update:modelValue 的事件; 在Vue3 中也可以用參數形式指定多個不同的綁定,如
v-model:foo 這時候就相當於給了子元件一個
foo 的屬性和
update:foo 的事件。
v-model作為一個指令,它的原理就是Vue 編譯器會把它轉換成
value屬性綁定和input的監聽事件,上面說過是預設情況下,實際上編譯器會根據表單元素的不同分配不同的事件,例如checkbox 和
radio 類型的
input 會轉換為
checked 和
change 事件。
Vue 元件之間通訊有以下這麼多種:
props#
$emit
、$on
、$off
、$once
(後三者在Vue3中已被廢除)
$children
(Vue3中廢除)、$parent
$attrs
、$listeners
(Vue3中廢除)
ref
$root
eventbus
(Vue3中不好使了,需要自己包裝)
#vuex
、pinia
provide inject
父子元件之間可以使用
props
/$emit
/
/
$attrs#兄弟元件之間可以使用
#跨層及元件之間可以使用
/ provide inject
#路由懶載入:有效分割
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">const router = createRouter({
routes: [
{ path : &#39;/foo&#39;, component: () => import(&#39;./foo.vue)}
]
})</pre><div class="contentsignin">登入後複製</div></div>
#<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;"><keep-alive>
<router-view v-if="$route.meta.keepAlive == true"></router-view>
</keep-alive>
<router-view v-if="$route.meta.keepAlive != true"></router-view></pre><div class="contentsignin">登入後複製</div></div>
使用
v-show
重複使用DOM
:避免重複建立元件
#v-for
遍歷避免同時使用v-if
(實際上這在Vue3 中是錯誤的寫法)
#:不再變化的資料使用v-once
;按條件跳過更新時使用v-memo
#長列表效能最佳化:如果是大數據長列表,可採用虛擬滾動,只渲染一小部分區域的內容。一些開源程式庫(vue-virtual-scroller
/
圖片懶加載,自訂
v-lazy
element-plus 避免體積太大
SSR
服務端渲染解決首屏渲染慢的問題為什麼刷新後 Vuex 狀態為什麼會遺失?
第三方函式庫以及原理探討
##個人理解
##回答:
因為Vuex 只是在記憶體中儲存狀態,刷新後就會遺失,如果要持久化就要存起來。
可以是用
localStorage 儲存
Vuex 的狀態,
store 中把值取出來當作
state 的初始值,提交
mutation 的時候就存入
localStorage。
vuex-persist、
vuex-persistedstate
mutation 變化做統一處理。
localStorage API 的原因只能儲存字串,所以我們只能將資料透過JSON.stringify
轉換為字串,而當我們儲存的資料為Set
、JSON.stringify
轉換後會變味storage
事件來清除資料window.addEventListener("storage", function () { localStorage.clear(); window.location.href = '/login' console.error("不要修改localStorage的值~~~"); });
Map 和Set
這種引用類型。7. Vue3 為什麼用Proxy 取代defineProperty ?#思路:
##屬性攔截的幾種方式
Vue2
中使用 defineProperty
的原因是, 2013 年只能使用这种方式,由于该 API
存在一些局限性,比如对于数组的拦截有问题,为此 Vue
需要专门为数组响应式做一套实现。另外不能拦截那些新增、删除属性;最后 defineProperty
方案在初始化时需要深度递归遍历处理对象才能对它进行完全拦截,明显增加了初始化的时间。
以上两点在 Proxy
出现后迎刃而解,不仅可以对数组实现拦截,还能对 Map
、Set
实现拦截;另外 Proxy
的拦截也是懒处理行为,如果用户没有访问嵌套对象,那么也不会实施拦截,这就让初始化的速度和内存占用改善了。
Proxy
有兼容性问题,完全不支持IE
思路:
必要性
何时用
怎么用
使用细节
回答:
当打包构建时,Javascript 抱回变得非常大,影响页面加载。利用路由懒加载我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应最贱,这样更加高效,是一种优化手段。
一般来说,对于所有的路由都使用动态导入是个好主意
给 component
选项配置一个返回 Promise组件的函数就可以定义懒加载路由.例如:
{ path: '/login', component: () => import('../views/login/Login.vue') },
结合注释
{ path: '/login', component: () => import(/* webpackChunkName: "login" */'../views/login/Login.vue') },
vite中结合rollupOptions定义分块 5. 路由中不能使用异步组件
Vue-Router 有三个模式,其中 history 和 hash 更为常用。两者差别主要在显示形式和部署上,
hash模式在地址栏现实的时候有一个 #
,这种方式使用和部署都较简单;history模式url看起来更优雅没关,但是应用在部署时需要做特殊配置,web服务器需要做回退处理,否则会出现刷新页面404的问题。
在实现上 hash
模式是监听hashchange
事件触发路由跳转,history
模式是监听popstate
事件触发路由跳转。
在 Vue
中 nextTick
是等待下一次 DOM
更新刷新的工具方法。
Vue
有一个异步更新策略,意思是如果数据变化,Vue
不会立刻更新 DOM
,而是开启一个队列,把组件更新函数保存在队列中,在同一时间循环中发生的所有数据变更会异步的批量更新。这一策略导致我们对数据的修改不会立刻体现在 DOM
上,此时如果想要获取更新后的 DOM
状态,就需要使用 nextTick
nextTick
接受一个函数,我们可以在这个函数内部访问最新的 DOM
状态
在开发时,有两个场景我们会用到 nextTick
:
created
中想要获取 DOM
;DOM
更新后的状态;nextTick
的原理:在 Vue
内部,nextTick
之所以能够让我们看到 DOM
更新后的结果,是因为我们传入的 callback
会被添加到队列刷新函数的后面,这样等队列内部的更新函数都执行完毕,所有 DOM
操作也就结束了,callback
自然能够获取最新的 DOM
值。
先回答答案:在 vue2
中, v-for
的优先级更高
但是在 vue3
中, v-if
的优先级更高
拓展:无论什么时候,我们都不应该把 v-for
和 v-if
放在一起,
怎么解决呢?一是可以定义一个计算属性,让 v-for
遍历计算属性。二是可以把 if
移到内部容器里(ul
ol
)或者把v-for
移植外部容器(template
)中
watch
store.subscribe()
watch
方式,可以以字串形式監聽$store.state.xx
; subscribe
方法參數是一個回呼函數,回呼函數接受mutation
物件和state
對象,可以透過mutation.type
判斷監聽的目標。
wtach 方法更簡單好用, subscribe
會略繁瑣,一般用vuex
插件中(可以提一下vuex的持久化插件vuex-persist
、vuex-persistedstate
)
不支援持久化,頁面刷新狀態就會遺失
使用模組比較繁瑣
#不支援ts
(或很不友善)
vue3 pinia 會是更好的組合。
#兩者都能傳回響應式對象,ref
傳回的是一個響應式Ref
對象, reactive
傳回的是響應式代理對象。
ref
通常是處理單一值得響應式,reactive
用於處理物件類型的資料響應式
ref
需要透過.value
訪問, 在視圖中會自動脫ref
,不需要.value
,ref
可以接收物件或陣列但內部仍然是reactive
實現的;reactive
如果接收Ref
物件會自動脫ref
;使用展開運算子展開reactive
傳回的響應式物件會使其失去回應性,可以結合toRefs()
將值轉換為Ref
物件後再展開。
reactive
內部使用 Prxoy
# 代理攔截物件各種操作,而ref
內部封裝一個RefImpl
類,設定get value/set value
,攔截使用者對值得存取。
邏輯擴充:mixins
、extends
、composition api
:
內容擴充:slots
mixins
很靈活,但會衝突很混亂。 extends
是一個不太常用的選項,更 mixins
的不同是它只能擴展單個對象,優先權比 mixins
高。
混入的資料和方法 不能明確判斷來源 而且可能和目前元件內變數 產生命名衝突,composition api 可以很好地解決這些問題,利用獨立出來的響應式模組可以很方便的編寫獨立邏輯並提供響應式資料局,增強程式碼的可讀性和維護性。
擴充:Vue.mixin(全域混入) Vue.extend(有點像是類別/元件的繼承建立一個子類別)
vue-loader
是用來處理單一檔案元件(SFC)的webpack loader
因為有了vue-loader
,我們才能用.vue
檔案形式編寫程式碼,將程式碼分割為template
script
style
webpack
在打包的時候,會以loader
的方式呼叫vue-loader
vue-loader
被執行時,它會對SFC
中的每個語言區塊用單獨的loader
鏈處理,最後將這些單獨的區塊組裝成最終的元件模組
#不能直接改。
元件化開發中有一個單向資料流原則,不在子元件修改父元件資料是個常識
如果你確實需要改,請透過emit向父元件發送事件,在父元件中修改
我麼可以在路徑中使用一個動態欄位來實現,例如/users/:id
其中 :id
是路徑參數。
可以透過 this.$route.parmas
取得,參數還可以有多個,$route
物件也公開了其他有用的資訊如query
hash
等。
想法:
什麼是響應式?
為什麼vue需要響應式?
有什麼好處?
vue的響應式怎麼實現的,有哪些優缺點?
vue3中的回應式的新變化
#回答:
vue 中要解決的一個核心問題就是連接資料層和視圖層,透過資料變化驅動視圖更新,要做到這點就需要對資料做響應式處理。
DOM 和
patch 演算法,我們只需要操作數據,關心業務,完全不需要接觸繁瑣的
DOM 操作,打打提升了開發效率,降低開發難度。
vue2 中實作資料回應式的核心是透過
Object.defineProperty() 方法對資料進行攔截,當
get 資料時做依賴收集
set 資料時做更新通知。這種機制很好的及絕了資料響應式的問題,但是實際使用也存在缺點,例如在
初始化時的遞歸遍歷會造成效能損失;無法監聽新增或刪除屬性,在vue 中要透過像
Vue.set/delete 這種特定的
API 才能實現對物件陣列屬性的新增和刪除,而且也不支援
Ma、
Set這些資料結構,
Vue3 重寫了這部分實現,利用的是
ES6 中的
Proxy 代理要回應化的資料。它有很多好處,初始化效能和記憶體都大幅改善,也不需要特殊的
API ,但不支援
IE 瀏覽器。
template 到
render 的過程其實是問的vue
編譯器 工作原理。
想法:
回答:
Vue 中有一個獨特的編譯模組,稱為
compiler,它的主要作用是將
template 編譯為
js# 可執行的
render 函數
HTML來寫視圖,直覺且有效率。手寫
render 函數不僅效率低下,而且失去了被編譯器的最佳化能力。
Vue 編譯器首先會對
template進行解析(
Parse ),結束後會得到一個抽象語法樹
AST,然後對
AST 進行深度加工轉換(
transform),最後將得到的
AST 產生為
js 程式碼,也就是
render 函數
元件,include 和exclude 可以指定包含不包含哪些元件。
結合vue-router
使用變化非常大,之前是keep-alive
包含router -view
,現在是router-view
包含keep-alive
鉤子或beforeRouteEnter
( vue-router
的一個守衛)
是一個通用元件,它內部定義了一個map
,快取創建過的元件實例,它傳回的渲染函數內部會尋找內嵌的component
元件對應元件的vnode
,如果改組件在map中存在就直接回傳它。由於component
的is
屬性是一個響應式數據,因此只要它變化,keep-alive
的render
函數就會重新執行。 </li></ul><h2><strong>23. 虛擬DOM</strong></h2><ul style="list-style-type: disc;"><li><p>#虛擬 <code>DOM
是什麼?
虛擬 DOM
的本質就是一個 Javascript
物件。
為什麼要引入虛擬 DOM
? (好處)
它能有效減少操作 DOM
的次數,方便實現跨平台
#虛擬DOM如何產生? compiler
編譯器會把template
模版編譯成渲染函數,接下來在mount
掛載的過程會呼叫這個渲染函數,回傳的物件就是虛擬DOM
。掛載結束後,會進入更新流程。如果某些響應式資料發生變化,將會造成元件重新render
,此時會產生新的虛擬DOM
,和上次渲染結果做diff
#操作,最小量的操作dom
,從而有效率地更新視圖。
非同步元件就是不會立即載入而是會在需要的時候載入的組件。在大型應用中,我們需要分割程式碼為更小的區塊試就可以用非同步元件。
不僅可以在路由切換時懶載入元件,還可以在元件中使用非同步元件,從而更細的分割程式碼。
使用非同步元件最簡單的方式是直接給defineAsyncComponet
指定一個loader
函數,結合ES 模組動態導入函數import
可以快速實現。 Vue3
也可以結合 Suspense
元件使用非同步元件。
非同步元件容易和路由懶加載混淆,實際上不是一個東西。非同步元件不能用來定義懶載入路由上,處理它的是 Vue
框架,處理路由元件載入的是 vue-router
。但是可以在懶加載的路由組件中使用非同步組件。
v-once
方式只渲染一次懶載入
方式,在用戶需要的時候在載入資料。 #computed
是計算屬性,watch
#是偵聽器。
computed
通常用於處理模版中複雜的邏輯,而watch
通常用於需要監聽一個響應式物件的變化而做一些操作的時候
watch
可以進行非同步操作,computed
不行。
計算屬性傳遞一個物件有set
和get
兩個選項,是它稱為即可讀又可寫的計算屬性,如果傳遞的是函數的話預設就是get
選項,watch
可以傳遞一個對象,設定deep、immediate等選項
vue3
中watch
發生了一些變化,例如不能再偵測一個點操符之外的字串表達式,reactivity API
中新出的 watch
、watchEffect
可以完全取代watch
選項,而且功能更強大
SPA
(Single Page Application)是單一頁面應用程式。一般也稱為客戶端渲染,簡稱 CSR
。 SSR(Server Side Render) 即服務端渲染。一般也稱為多頁面應用程式(Mulpile Page Application),簡稱 MPA。
SPA
只會首次要求html
文件,後續只需要請求JSON
資料即可,因此使用者體驗更好,節約流量,服務端壓力也較小。但是首屏載入的時間會變長,而且 SEO
不友善。為了解決以上缺點,就有了 SSR
方案,由於 HTML
內容在伺服器一次生成出來,首屏加載快,搜尋引擎也可以很方便的抓取頁面資訊。但同時 SSR
方案也會有效能,開發受限等問題。
選擇上,如果有首屏載入優化需求,SEO需求時,就可以考慮SSR。
但不是只有這一種替代方案,例如對一些不常變化的靜態網站,SSR反而浪費資源,我們可以考慮預先渲染的方案。另外 nuxt.js/next.js
中給我們提供了SSG靜態網站產生方案也是很好的靜態網站解決方案,結合一些CI手段,可以起到很好的最佳化效果。
回答思路:
diff算法是干什么的?
必要性
何时执行
具体执行方式
拔高:说一下vue3中的优化
回答:
Vue
中的 diff
算法称为 patching
算法,虚拟DOM要想转化为真实DOM就需要通过 patch
方法转换。
最初 Vue1.x
视图中农每个依赖均有更新函数对应,可以做到精确更新,因此不需要 虚拟DOM
和 patching
算法支持,但是这样粒度过细导致 Vue1.x
无法承载较大应用;Vue2.x
中为了降低 Watcher
粒度,每个组件只有一个 Watcher
与之对应,此时就需要引入 patching
算法才能精确找到发生变化的地方并高效更新。
vue
中 diff
执行的时刻是组件内响应式数据变更触发实例执行其更新函数时,更新函数会再次执行 render函数
获得最新的 虚拟DOM
,然后执行 patch函数
,对比新旧虚拟DOM,将其转化为对应的 DOM
操作。
patch
过程是一个递归过程,遵循深度优先、同层比较的策略;以 vue3
的patch
为例:
vue3
中引入的更新策略:编译期优化 patchFlags
、block
等
从 0 创建项目我大致会做以下事情:项目构建、引入必要插件、代码规范、提交规范、常用库和组件
目前vue3项目我会用vite或者create-vue创建项目
接下来引入必要插件:vue-router、vuex/pinia、element-plus、antd-vue、axios等等
其他常用的库有 像lodash、dayjs、nprogress等等..
下面是代码规范: editorconfig、prettier、eslint
最后是提交规范,可以使用husky、Commitizen
目录结构我喜欢按照下面的结构来
+ |- /src + |- /assets 存放资源 + |- /img + |- /css + |- /font + |- /data + |- base-ui 存放多个项目中都会用到的公共组件 + |- components 存放这个项目用到的公共组件 + |- hooks 存放自定义hook + |- views 视图 + |- store 状态管理 + |- router 路由 + |- service 网络请求 + |- utils 工具 + |- global 全局注册、全局常量..
一个 SPA
应用的路由需要解决的问题时页面跳转内容改变同时不刷新,同时路由还需要已插件形式存在,所以:
首先我会定义一个 createRouter
函数,返回路由器实例,实例内部做几件事;
hash
或者 popstate
事件path
匹配对应路由将 router
定义成一个 Vue
插件,即实现 install
方法,内部做两件事:
router-link
和 router-view
,分别实现页面跳转和内容显示$router
和 $route
,组件内可以访问当前路由和路由器实例在项目规模变大的之后,单独一个store对象会过于庞大臃肿,此时通过模块方式可以拆分来便于维护
可以按之前规则单独编写资规模代码,然后在主文件中通过 modules
选项组织起来:createStore({modules: {...}})
使用時需要注意存取子模組狀態時需要加上註冊模組名稱。但同時getters
、mutations
和 actions
又在全域空間中,使用方式和之前一樣。如果要做到完全拆分,需要在子模組加上 namespace
選項,此時再訪問它們就要加上命名空間前綴。
模組的方式可以分割程式碼,但是缺點也很明顯,使用起來比較繁瑣,容易出錯,而且類型系統支援很差,不能給我們帶來幫助。 pinia 顯然在這方面有了很大改進,是時候切換過去了。
vue2
中元件確實只能有一個跟,但vue3
中元件已經可以多根元件了。
之所以需要這樣是因為vdom
是一顆單根樹狀結構,patch
方法在遍歷的時候從根節點開始遍歷,它要求只有一個根節點。元件也會轉換為一個 vdom
,自然應該滿足這個要求。
vue3
中之所以可以寫多個根節點,是因為引入了Fragment
的概念,這是一個抽象的節點,如果發現元件時多根的,就建立一個Fragment
節點,把多個根節點當作它的children
。將來 pathch
的時候,如果發現是一個 Fragment
節點,則直接遍歷 children
建立或更新。
v-once
是vue
的內建指令,作用是只渲染指定元件或元素一次,並跳過未來對其更新。
如果我們有一些元素或元件再初始化渲染之後不再需要變化,這種情況下適合使用v-once
,這樣哪怕這些資料變化, vue
也會跳過更新,是一種程式碼最佳化手段。
我們只需要作用的元件或元素上加上 v-once
即可。
補充:
vue3.2
之後,又增加了v-memo
,這個指令可以有條件的快取模板並控制他們的更新。
v-once
的原理:編譯器發現有v-once
時,將第一次計算結果存入快取對象,元件再次渲染時就會從快取獲取,從而避免再次計算。
url
各部分通常對應某個嵌套的元件,vue-router
中可以使用巢狀路由表示這種關係。 view-router
,從而形成物理上的嵌套,和邏輯上的嵌套對應起來。定義嵌套路由時使用children
屬性組織嵌套關係router-view
元件內部判斷其所處嵌套的深度,將這個深度作為匹配元件數組matched
的索引,取得對應渲染元件並渲染之。 如果你說不出來,可以直接舉例。當我開發一個頁面時,如果需要顯示一個頂部導覽欄,透過導覽列跳到不同的頁面,而頂部的導覽列又必須要在每個頁面顯示時,就可以使用嵌套路由;還可以舉例,當我需要查看某個清單的詳情頁面時,往往需要嵌套路由(detail/:id
)
watch
store.subscribe()
watch
方式,可以以字串形式監聽$store.state.xx
; subscribe
方法參數是一個回呼函數,回呼函數接受mutation
物件和state
對象,可以透過mutation.type
判斷監聽的目標。
wtach 方法更簡單好用, subscribe
會略繁瑣,一般
掛載實例的過程就是app.mount()的過程,整體上就做了兩件事:初始化和建立更新機制
初始化會建立元件實例、初始化元件狀態、建立各種響應式資料
簡歷更新機制這一步驟會立即執行一次元件更新函數,這會首次執行渲染函數並執行patch
將前面獲得vnode
轉換為dom
;同時會建立它內部響應式資料和元件更新函數之間的依賴關係,這使得以後資料變更時會執行對應的更新函數。
key
的作用主要是為了更有效率的更新虛擬DOM
。
key
是vue
在patch
過程中判斷兩個節點是否為相同節點的關鍵條件(另一個是元素類型),如果不設定key
,它的值就是undefined
#,vue
則可能永遠認為這是兩個相同節點,只能去做更新操作,這造成了大量的dom
更新操作,明顯是不可取的。
實際使用的過程中必須設定 key
,而且應該盡量避免使用陣列索引,這可能導致一些隱藏 bug
。
watchEffect
立刻執行函數,被動地追蹤它的依賴,傳入的函數即是依賴收集的資料來源,也是回呼函數;watch
偵測一個或多個響應式資料來源,在資料來源變更時呼叫一個回呼函數,透過immediate
選項也可以設定立即執行一次。
watchEffect
是一種特殊的 watch
。如果不關心響應式資料前後的值,可以使用 watchEffect
。其他情況都可以用 watch
。
parent created -> child created -> child mounted -> parent mounted
原因:Vue
創建是一個遞歸的過程,先建立父元件,有子元件就會建立子元件,因此創建時先有父元件再有子元件;子元件首次建立時會加入Mounted
鉤子到佇列,等到patch
結束再執行它們,可見子元件的mounted
鉤子是選進入到佇列中的,因此等到patch
結束執行這些鉤子時也先執行。
#vuex是專門為vue應用程式開發的狀態管理模式庫,
當你遇到多個元件共享狀態時或專案中的元件難以管理的時候就可以使用vuex,它以一個全域單例模式管理全域的狀態。
基本核心概念有state、mutation、action、getters、module等
說些使用過程的感受ts不友善模組使用繁瑣頁面刷新資料也會消失
如果某個元件透過元件名稱來引用它自己,這種情況就是遞迴元件。
類似Tree
、Menu
這類元件,它們的節點往往包含子節點,子節點結構和父節點往往是相同的。這類組件的資料往往也是樹狀結構,這種都是使用遞迴元件的典型場景。
使用自訂指令分為定義、註冊、和使用
#定義有兩種方式,物件和函數形式,前者類似元件定義,有各種生命週期;後者只會在mounted
和updated
時執行
註冊:可以使用app.directive
全域註冊也可以透過選項局部註冊
使用時在註冊名稱前加上v-即可。
v-copy
複製貼上
#v-lazy
圖片懶載入
v-debounce
防手震
#v-permission
按鈕權限
#v-longpress
長按
API 層面
Composition API
#setup
語法糖
Teleport
傳送門
#Fragments
可以多個根節點
Emits
createRenderer
自訂渲染器
SFC
狀態驅動css
變數(v-bind in <style>
)
##此外,Vue3在框架層級也有很多兩點和改進
DOM
重寫patchFlags
、block
等Proxy
的響應式系統Vue2,為了實現這一點,
Vue3 在以下幾個方面做了很大改進,如:易用性,框架性能、擴展性、可維護性、開發體驗等
API 簡化
v-model 變成了
v-model 和
sync 修飾符的結合體。類似的還有
h(type,props,children) 函數中的
props 不用考慮區分屬性、特性、事件等,框架替我們判斷,易用性增。
Teleport
Fragment
Suspense 等都會簡化特定場景的程式碼編寫。
setup 語法糖更是大幅提升了我們的開發體驗。
reactivity 模組,
custom render API等
Composition API,更容易寫出高復用性的業務邏輯。還有對TS支援的提升。
Proxy 的響應式系統。
Proxy 實現,初始化事件和記憶體佔用均大幅改進;
tree-shaking ,因此體積更小,載入更快.(
因為vue3 所有的API都透過ES6模組化的方式引入,這樣就能讓webpack或rollup等打包工具在打包時對沒有用到API進行剔除,最小化bundle體積)
和
$listeners 是做什麼的?
$attrs 取得沒有在
props 中定義的屬性,
v-bind="$attrs" 可以用於屬性透傳
$listeners 用來取得事件,
vue3 中已經移除合併到
attrs 中,使用起來更方便
Composition API 是一組API,包括
Reactivity API、生命鉤子、依賴注入,使用戶可以透過匯入函數方式編寫元件,而
Options API 則透過宣告元件選項的物件形式編寫元件。
Composition API 更簡潔、邏輯重複使用更有效率。解決的過去
Options API 中
mixins 的各種缺點(會衝突很混亂);另外
Composition API 更自由,沒有
Options API 那樣固定的寫法,並且可以更有效的將邏輯代碼組織在一起,而不用東一塊西一塊搞得很混亂,最後
Composition API 擁有更好的類型推斷,對
ts 支持友好。
#編碼風格方面:
減少首屏載入事件
v-memo
或shallowReactive
降低開銷
stateaction
用來提交一個
mutation,而且
action 可以包含非同步操作
50. 如何從0實作vuex
dispatch(type,payload)
實作Store
,可以定義Store
類,建構函式接受選項options
,設定屬性state
對外暴露狀態,提供commit
和dispatch
修改屬性。這裡需要設定 state
為響應式對象,同時將 Store
定義為一個 Vue
外掛(install方法)。
commit
可以取得使用者傳入mutations
並執行它,這樣可以依照使用者提供的方法修改狀態,dispatch
類似,但dispatch
需要傳回一個Promise
給使用者用於處理非同步結果。
以上是【整理總結】45+個Vue面試題,帶你鞏固知識點!的詳細內容。更多資訊請關注PHP中文網其他相關文章!