1.說說vue動態(tài)權(quán)限綁定渲染列表(權(quán)限列表渲染)
-
首先請求服務(wù)器,獲取當(dāng)前用戶的權(quán)限數(shù)據(jù),比如請求 this.$http.get("rights/list");
-
獲取到權(quán)限數(shù)據(jù)之后,在列表中使用v-if v-if-else的組合來展示不同的內(nèi)容
<template> ?<div> ? ?<!-- 面包屑導(dǎo)航區(qū) --> ? ?<el-breadcrumb?separator-class="el-icon-arrow-right"> ? ? ?<el-breadcrumb-item?:to="{ path: '/home' }">首頁</el-breadcrumb-item> ? ? ?<el-breadcrumb-item>權(quán)限管理</el-breadcrumb-item> ? ? ?<el-breadcrumb-item>權(quán)限列表</el-breadcrumb-item> ? ?</el-breadcrumb> ? ?<!-- 卡片視圖 --> ? ?<el-card> ? ? ?<el-table?:data="rightsList"?border?stripe> ? ? ? ?<el-table-column?type="index"?label="#"></el-table-column> ? ? ? ?<el-table-column?label="權(quán)限名稱"?prop="authName"></el-table-column> ? ? ? ?<el-table-column?label="路徑"?prop="path"></el-table-column> ? ? ? ?<el-table-column?label="權(quán)限等級"?prop="level"> ? ? ? ? ?<template?slot-scope="scope"> ? ? ? ? ? ?<el-tag?v-if="scope.row.level === '0'">一級</el-tag> ? ? ? ? ? ?<el-tag?type="success"?v-else-if="scope.row.level === '1'">二級</el-tag> ? ? ? ? ? ?<el-tag?type="danger"?v-else>三級</el-tag> ? ? ? ? ?</template> ? ? ? ?</el-table-column> ? ? ?</el-table> ? ?</el-card> ?</div> </template> <script> export?default?{ ?data() { ? ?return?{ ? ? ?// 權(quán)限列表 ? ? ?rightsList: [] ? }; }, ?created() { ? ?this.getRightsList(); }, ?methods: { ? ?async?getRightsList() { ? ? ?//獲取權(quán)限列表數(shù)據(jù) ? ? ?const?{?data:?res?}?=?await?this.$http.get("rights/list"); ? ? ?if?(res.meta.status?!==?200) { ? ? ? ?return?this.$message.error("獲取權(quán)限列表失敗!"); ? ? } ? ? ?this.rightsList?=?res.data; ? } } }; </script> <style?lang='less'?scoped> </style>
2.Vue用的哪種設(shè)計模式
屬于發(fā)布訂閱模式,在vue中使用observer和definereactive兩個方法的結(jié)合對數(shù)據(jù)進(jìn)行遞歸劫持,然后通過watch這個類來對屬性進(jìn)行訂閱,Dep類用于解耦合,當(dāng)數(shù)據(jù)變更的時候先觸發(fā)數(shù)據(jù)的set方法,然后調(diào)用Dep.notiify通知視圖更新
3.說說vue操作真實dom性能瓶頸
vue性能瓶頸的幾種情況
-
一次渲染大量的數(shù)據(jù)的時候,存在大量數(shù)據(jù)并且都是復(fù)雜類型的時候,會導(dǎo)致vue對數(shù)據(jù)的劫持時間和渲染時間變長, js 連續(xù)執(zhí)行時間過長,會導(dǎo)致頁面長時間無法交互,而且渲染時間太慢,用戶一次交互反饋的時間過長。
優(yōu)化方案:可以使用
requestAnimation
這個方法,將數(shù)據(jù)進(jìn)行分割,分批次渲染,減少了 js 的連續(xù)運行時間,并且加快了渲染時間,利用加長總運行時間換取了渲染時間,用戶既能快速得到反饋,而且不會因為過長時間的 js 運行而無法與頁面交互。 -
當(dāng)頁面中存在大量數(shù)據(jù),只是修改了一小部分導(dǎo)致頁面也會導(dǎo)致頁面卡頓,因為vue的更新以組件為粒度進(jìn)行更新的,只要修改了當(dāng)前組件中所使用的數(shù)據(jù),組件就會整個去進(jìn)行更新,造成大量的時間浪費
優(yōu)化方案:將不同的模塊劃分成不同的組件,這樣有效降低虛擬dom的diff運算時間過長的問題,比如將大量數(shù)據(jù)的模塊單獨放一個組件,其它放一個組件,由于vue是以組件為粒度更新,修改其它組件的情況下不會導(dǎo)致table的重新diff,提升頁面響應(yīng)速度高達(dá)幾百倍
-
動態(tài)插槽作用域或者靜態(tài)插槽的更新
使用插槽作用域來替換這兩種操作方式,一樣能提升性能,因為使用
插槽作用域
之后,插槽內(nèi)容會被封裝到一個函數(shù)中,被子組件渲染,而不是在父組件
4.Vue中如何獲取dom、操作dom、更新dom
如何獲取dom?在Vue中提供了一種特別的方式來獲取dom,即給dom加上個ref屬性,那么就可以通過this.$refs.名字來獲取到該dom元素。
如何操作dom、更新dom?通過refs.名字就可以拿到對應(yīng)的真實dom,然后就可以用原生JS進(jìn)行操作和更新。當(dāng)然vue框架本身就是不需要dom操作的,通過修改相應(yīng)的數(shù)據(jù)并再配合指令、模板語法就可以輕松的操作和更新dom。
5.Vue 的雙向數(shù)據(jù)綁定原理是什么
在Vue2.x中,雙向數(shù)據(jù)綁定是通過 數(shù)據(jù)劫持 結(jié)合 發(fā)布訂閱模式的方式來實現(xiàn)的,也就是說數(shù)據(jù)和視圖同步,數(shù)據(jù)發(fā)生變化,視圖跟著變化,視圖變化,數(shù)據(jù)也隨之發(fā)生改變。核心:關(guān)于VUE雙向數(shù)據(jù)綁定,其核心是 Object.defineProperty()方法。
Vue3.x則是用ES6的語法Proxy對象來實現(xiàn)的。
Object.defineProperty()的缺點:
-
只能監(jiān)聽對象(Object),不能監(jiān)聽數(shù)組的變化,無法觸發(fā)push, pop, shift, unshift,splice, sort, reverse。
-
必須遍歷對象的每個屬性
-
只能劫持當(dāng)前對象屬性,如果想深度劫持,必須深層遍歷嵌套的對象。
?Proxy的優(yōu)點:
-
Proxy 可以直接監(jiān)聽對象而非屬性。
-
Proxy 可以直接監(jiān)聽數(shù)組的變化。
-
Proxy 有多達(dá) 13 種攔截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具備的。
-
Proxy 返回的是一個新對象,我們可以只操作新的對象達(dá)到目的,而 Object.defineProperty 只能遍歷對象屬性直接修改。
-
Proxy 作為新標(biāo)準(zhǔn)將受到瀏覽器廠商重點持續(xù)的性能優(yōu)化,也就是傳說中的新標(biāo)準(zhǔn)的性能紅利。
?let?arr?=?[];
?let?proxy?=?new?Proxy(arr, {
? ?get:?function(obj,?prop){
? ? ?return?obj[prop];
? },
? ?set:?function(obj,?prop,?value){
? ? ?obj[prop]?=?value; ??//可以被監(jiān)聽到變化
? ? ?return?true;
? }
});
?setTimeout(()=>{
? ?proxy.push(1);
},?2000)
6.mvvm框架是什么
MVVM是Model-View-ViewModel的簡寫。它本質(zhì)上就是MVC(Model-View-Controller)的改進(jìn)版。在開發(fā)過程中,由于需求的變更或添加,項目的復(fù)雜度越來越高,代碼量越來越大,此時我們會發(fā)現(xiàn)MVC維護起來有些吃力,尤其Controller控制層非常的厚重,非常的龐大,難以維護。
所以有人想到把Controller的數(shù)據(jù)和邏輯處理部分從中抽離出來,用一個專門的對象去管理,這個對象就是ViewModel。ViewModel 是由前端開發(fā)人員組織生成和維護的視圖數(shù)據(jù)層。在這一層,前端開發(fā)者對從后端獲取的 Model 數(shù)據(jù)進(jìn)行轉(zhuǎn)換處理,做二次封裝,以生成符合 View 層使用預(yù)期的視圖數(shù)據(jù)模型。
由于實現(xiàn)了雙向綁定,ViewModel 的內(nèi)容會實時展現(xiàn)在 View 層,這是激動人心的,因為前端開發(fā)者再也不必低效又麻煩地通過操縱 DOM 去更新視圖,MVVM 框架已經(jīng)把最臟最累的一塊做好了,我們開發(fā)者只需要處理和維護 ViewModel,更新數(shù)據(jù)視圖就會自動得到相應(yīng)更新,真正實現(xiàn)數(shù)據(jù)驅(qū)動開發(fā)。
7.談?wù)刅ue的token存儲
在前后端完全分離的情況下,Vue項目中實現(xiàn)token驗證大致思路如下:
1、第一次登錄的時候,前端調(diào)后端的登陸接口,發(fā)送用戶名和密碼
2、后端收到請求,驗證用戶名和密碼,驗證成功,就給前端返回一個token
3、前端拿到token,將token存儲到localStorage和vuex中,并跳轉(zhuǎn)路由頁面
4、前端每次跳轉(zhuǎn)路由,就判斷 localStroage 中有無 token ,沒有就跳轉(zhuǎn)到登錄頁面,有則跳轉(zhuǎn)到對應(yīng)路由頁面
5、每次調(diào)后端接口,都要在請求頭中加token
6、后端判斷請求頭中有無token,有token,就拿到token并驗證token,驗證成功就返回數(shù)據(jù),驗證失?。ɡ纾簍oken過期)就返回401,請求頭中沒有token也返回401
7、如果前端拿到狀態(tài)碼為401,就清除token信息并跳轉(zhuǎn)到登錄頁面
8.知道nextTick的作用嗎,談?wù)剬λ睦斫?,是什么,怎么?/h4>
當(dāng)你設(shè)置 vm.message = 'new message',該組件不會立即重新渲染。當(dāng)刷新隊列時,組件會在下一個事件循環(huán)“tick”中更新。多數(shù)情況我們不需要關(guān)心這個過程,但是如果你想基于更新后的 DOM 狀態(tài)來做點什么,這就可能會有些棘手。雖然 Vue.js 通常鼓勵開發(fā)人員使用“數(shù)據(jù)驅(qū)動”的方式思考,避免直接接觸 DOM,但是有時我們必須要這么做。為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback)。這樣回調(diào)函數(shù)將在 DOM 更新完成后被調(diào)用。例如:
<div?id="example">{{message}}</div>
var?vm?=?new?Vue({
?el:?'#example',
?data: {
? ?message:?'old message'
}
})
vm.message?=?'new message'?// 更改數(shù)據(jù)
vm.$el.textContent??// 'old message'
Vue.nextTick(function?() {
?vm.$el.textContent??// 'new message'
})
9.nextTick和setTimeout區(qū)別
?首先Vue 在更新 DOM 時是異步執(zhí)行的,也就是說數(shù)據(jù)變了,DOM不會立即改變,那么我們是如何知道DOM什么時候會改變呢?也就是說如何知道異步后的觸發(fā)時機呢?
?可以通過nextTick方法,這個方法在源碼內(nèi),先監(jiān)聽是否具備Promise.then,利用promise來監(jiān)聽,如果當(dāng)前環(huán)境不支持promise,那么就降級采用MutationObserver,如果MutationObserver不支持的話,那么就降級采用setImmediate,如果setImmediate不支持的話,那么就使用setTimeout(fn, 0)。
?所以說nextTick和setTimeout區(qū)別總結(jié)就是:nextTick會先嘗試使用promise、MutationObserver、setImmediate這些技術(shù)去監(jiān)聽,如果都不支持才會采用setTimeout
10.vue中為什么用虛擬dom而不操作真實dom
起初我們在使用JS/JQuery時,不可避免的會大量操作DOM,而DOM的變化又會引發(fā)回流或重繪,從而降低頁面渲染性能。那么怎樣來減少對DOM的操作呢?此時虛擬DOM應(yīng)用而生,所以虛擬DOM出現(xiàn)的主要目的就是為了減少頻繁操作DOM而引起回流重繪所引發(fā)的性能問題的!
虛擬DOM(Virtual Dom),起始本質(zhì)上就是一個JS對象,當(dāng)數(shù)據(jù)發(fā)生變化時,我們不直接操作真實DOM,因為很昂貴,我們?nèi)ゲ僮鬟@個JS對象,就不會觸發(fā)大量回流重繪操作,再加上diff算法,可以找到兩次虛擬DOM之間改變的部分,從而最小量的去一次性更新真實DOM,而不是頻繁操作DOM,性能得到了大大的提升。
虛擬DOM還有一個好處,可以渲染到 DOM 以外的平臺,實現(xiàn) SSR、同構(gòu)渲染這些高級特性,Weex 等框架應(yīng)用的就是這一特性。
11.Vue如何進(jìn)行組件傳值
父向子組件傳值,可以利用prop方式。
子向父組件傳值,可以利用自定義事件$emit方式。
多層級組件傳值,可以使用provide/inject
無關(guān)系的組件傳值,利用vuex狀態(tài)管理
12.說說vue里面的父子通信
父 -> 子: 通過 Prop 向子組件傳遞數(shù)據(jù),子組件通過props屬性來接收。
<blog-post?title="My journey with Vue"></blog-post>
Vue.component('blog-post', {
?props: ['title'],
?template:?'<h3>{{ title }}</h3>'??//獲取父組件的值
})
子 -> 父: 父組件自定義事件,子組件利用$emit來完成。
<!--拿到子組件傳遞的數(shù)據(jù)$event即0.1-->
<blog-post?v-on:enlarge-text="postFontSize += $event"></blog-post>
Vue.component('blog-post', {
props: ['title'],
template: '<h3?v-on:click="$emit('enlarge-text', 0.1)">{{ title }}</h3>'
})
13.談?wù)勅绾螌崿F(xiàn)vue組件通信和傳值方式 (兩個問題為同一個答案問法不一樣)
這類問題 首先分類 表明了解的比較多 ? 具體就沒說完 或者漏了 面試官也不會計較很多 組件通信的四大類 ? 父與子 ? 子與父 ? 子與子 ? ? 跨層級 ? 在細(xì)說各種方式 加入自己的理解 1、props和$emit 父組件向子組件傳遞數(shù)據(jù)是通過prop傳遞的,子組件傳遞數(shù)據(jù)給父組件是通過$emit觸發(fā)事件 2、$attrs和$listeners 3、中央事件總線 bus 上面兩種方式處理的都是父子組件之間的數(shù)據(jù)傳遞,而如果兩個組件不是父子關(guān)系呢?這種情況下可以使用中央事件總線的方式。新建一個Vue事件bus對象,然后通過bus.$emit觸發(fā)事件,bus.$on監(jiān)聽觸發(fā)的事件。 4、provide和inject 父組件中通過provider來提供變量,然后在子組件中通過inject來注入變量。不論子組件有多深,只要調(diào)用了inject那么就可以注入provider中的數(shù)據(jù)。而不是局限于只能從當(dāng)前父組件的prop屬性來獲取數(shù)據(jù),只要在父組件的生命周期內(nèi),子組件都可以調(diào)用。 5、v-model 父組件通過v-model傳遞值給子組件時,會自動傳遞一個value的prop屬性,在子組件中通過this.$emit(‘input’,val)自動修改v-model綁定的值 6、$parent和$children 7、boradcast和dispatch 8、vuex處理組件之間的數(shù)據(jù)交互 如果業(yè)務(wù)邏輯復(fù)雜,很多組件之間需要同時處理一些公共的數(shù)據(jù),這個時候才有上面這一些方法可能不利于項目的維護,vuex的做法就是將這一些公共的數(shù)據(jù)抽離出來,然后其他組件就可以對這個公共數(shù)據(jù)進(jìn)行讀寫操作,這樣達(dá)到了解耦的目的。
14.說說vue中Key值的作用
關(guān)于這個可以的key的作用 首先表明 key 不是一定要有的 不寫可以代碼也可以跑 但是建議加上 然后指出可以用的地方 key在v-for循環(huán)可以用用 ? 在表單元素中也可以用key 減少緩存 一般說key 只要說配合v-for的使用 key是為Vue中的vnode標(biāo)記的唯一id,通過這個key,我們的diff操作可以更準(zhǔn)確、更快速 diff算法的過程中,先會進(jìn)行新舊節(jié)點的首尾交叉對比,當(dāng)無法匹配的時候會用新節(jié)點的key與舊節(jié)點進(jìn)行比對,然后超出差異能講清楚diff算法就繼續(xù)講 diff程可以概括為:oldCh和newCh各有兩個頭尾的變量StartIdx和EndIdx,它們的2個變量相互比較,一共有4種比較方式。如果4種比較都沒匹配,如果設(shè)置了key,就會用key進(jìn)行比較,在比較的過程中,變量會往中間靠,一旦StartIdx>EndIdx表明oldCh和newCh至少有一個已經(jīng)遍歷完了,就會結(jié)束比較,這四種比較方式就是首、尾、舊尾新頭、舊頭新尾. 準(zhǔn)確: 如果不加key,那么vue會選擇復(fù)用節(jié)點(Vue的就地更新策略),導(dǎo)致之前節(jié)點的狀態(tài)被保留下來,會產(chǎn)生一系列的bug. 快速: key的唯一性可以被Map數(shù)據(jù)結(jié)構(gòu)充分利用,相比于遍歷查找的時間復(fù)雜度O(n),Map的時間復(fù)雜度僅僅為O(1) 講完以后 還要補充一點自己的看法 建議使用主鍵比如id ?
15.說說vue中的虛擬dom和diff算法
Virtual DOM 其實就是一棵以 JavaScript 對象( VNode 節(jié)點)作為基礎(chǔ)的樹,用對象屬性來描述節(jié)點,實際上它只是一層對真實 DOM 的抽象。最終可以通過一系列操作使這棵樹映射到真實的DOM上 下面就是一個真實DOM映射到虛擬DOM的例子:
<ul id='list'>
? ? ? ? <li class='item'>Item 1</li>
? ? ? ? <li class='item'>Item 2</li>
? ? ? ? <li class='item'>Item 3</li>
? ? ? </ul>
? ? ? ?
var element = {
? ? ? tagName: 'ul', // 節(jié)點標(biāo)簽名
? ? ? props: { // DOM的屬性,用一個對象存儲鍵值對
? ? ? ? ? id: 'list'
? ? ? },
? ? ? children: [ // 該節(jié)點的子節(jié)點
? ? ? ? {tagName: 'li', props: {class: 'item'}, children: ["Item 1"]},
? ? ? ? {tagName: 'li', props: {class: 'item'}, children: ["Item 2"]},
? ? ? ? {tagName: 'li', props: {class: 'item'}, children: ["Item 3"]},
? ? ? ]
? }
在補充點虛擬DOM的好處 具備跨平臺的優(yōu)勢 由于 Virtual DOM 是以 JavaScript 對象為基礎(chǔ)而不依賴真實平臺環(huán)境,所以使它具有了跨平臺的能力,比如說瀏覽器平臺、Weex、Node 等。 操作原生DOM慢,js運行效率高。我們可以將DOM對比操作放在JS層,提高效率。 因為DOM操作的執(zhí)行速度遠(yuǎn)不如Javascript的運算速度快,因此,把大量的DOM操作搬運到Javascript中,運用patching算法來計算出真正需要更新的節(jié)點,最大限度地減少DOM操作,從而顯著提高性能。 Virtual DOM 本質(zhì)上就是在 JS 和 DOM 之間做了一個緩存??梢灶惐?CPU 和硬盤,既然硬盤這么慢,我們就在它們之間加個緩存:既然 DOM 這么慢,我們就在它們 JS 和 DOM 之間加個緩存。CPU(JS)只操作內(nèi)存(Virtual DOM),最后的時候再把變更寫入硬盤(DOM) 提升渲染性能 Virtual DOM的優(yōu)勢不在于單次的操作,而是在大量、頻繁的數(shù)據(jù)更新下,能夠?qū)σ晥D進(jìn)行合理、高效的更新。 diff算法 vdom因為是純粹的JS對象,所以操作它會很高效,但是vdom的變更最終會轉(zhuǎn)換成DOM操作,為了實現(xiàn)高效的DOM操作,一套高效的虛擬DOM diff算法顯得很有必要 diff算法包括一下幾個步驟: 用 JavaScript 對象結(jié)構(gòu)表示 DOM 樹的結(jié)構(gòu);然后用這個樹構(gòu)建一個真正的 DOM 樹,插到文 檔當(dāng)中 當(dāng)狀態(tài)變更的時候,重新構(gòu)造一棵新的對象樹。然后用新的樹和舊的樹進(jìn)行比較(diff),記錄兩棵樹差異 把2所記錄的差異應(yīng)用到步驟1所構(gòu)建的真正的DOM樹上(patch),視圖就更新了 diff算法是通過同層的樹節(jié)點進(jìn)行比較而非對樹進(jìn)行逐層搜索遍歷的方式,所以時間復(fù)雜度只有O(n),是一種相當(dāng)高效的算法
實現(xiàn)虛擬DOM的過程
16.vue3.0有了解過嗎,你覺得vue3.0好嗎,好在哪
這種問題 是開放的 ? 多說就是都是對的 ? ?可以講差異 ?也可以講新增 的知識點 ?
比如說 常用的api特別好用
-
ref、toRefs、toRef、isRef
-
ref 用于定義響應(yīng)式變量、快捷DOM訪問。
-
基本語法:
const a = ref(1) // {value:1}
-
基礎(chǔ)使用: 一般用于定義 String、Number、Boolean 這種基于數(shù)據(jù)類型,外在表現(xiàn)統(tǒng)一使用 .value 訪問。
-
補充:ref 還可以訪問 DOM對象或者組件實例對象,可做DOM操作。
-
toRef、toRefs 用于把一個object的變量,變成響應(yīng)式的變量。
-
基本語法:
const msg = toRef(obj, key)
// 把obj[key]變成響應(yīng)式的 -
基本語法:
const { msg } = toRefs(obj)
?// 把整個obj都變成響應(yīng)式的 -
unref 返回一個變量的值
-
基本語法:
const x = unref(x)
?// 如果x是ref變量則返回x.value,如果x不是ref變量則直接返回x。 -
isRef 用于判斷一個變量是不是ref響應(yīng)式變量
-
基本語法:
const bol = isRef(x)
function?useUpdBoxStyle() {
?const?el?=?ref(null)
?const?updateStyle?=?color?=>?{
? ?el.value.style.color?=?color
}
?return?[el,?updateStyle]
}
-
shallowRef、triggerRef
-
shallowRef 用于性能優(yōu)化,只對對象的第一層進(jìn)行proxy
-
基本語法:
const obj = shallowRef({a:1,b:{c:{d:{e:2}}}})
-
triggerRef 用于手動觸發(fā)那些shallowRef的變量進(jìn)行更新視圖
-
基本語法:
triggerRef(obj)
?// 當(dāng)obj.value.b.c.d發(fā)生變化,triggerRef(obj) 強制更新視圖。 -
customRef 自定義ref,把ref變量拆成get/set的寫法
-
基本語法:
customRef((track, trigger) =>({get,set})
function?useObj() {
?const?obj?=?{?a:?1,?b: {?c: {?d:?2?}}}
?const?obj1?=?ref(obj)
?const?obj2?=?shallowRef(obj)
?// console.log('obj1', obj1)
?// console.log('obj2', obj2)
?const?changeObj?=?(obj,?newD)?=>?{
? ?// obj1.value.b.c.d = 100
? ?obj.value.b.c.d?=?newD
? ?triggerRef(obj)
}
?return?[[obj1,?obj2],?changeObj]
}
-
reactive、readonly
-
reactive 用于定義響應(yīng)式變量(引用數(shù)據(jù)類型)
-
基本語法:
const arr = reactive([]) // {value: []}
-
ref和reactive是什么關(guān)系呢?ref背后是使用reactive來實現(xiàn)的。
-
shallowReactive 用于性能優(yōu)化,只對對象的第一層進(jìn)行proxy
-
基本語法:
const c = shallowReactive({a:{b:{c:100}}})
?// 只對這個對象的第一層進(jìn)行proxy -
readonly 把響應(yīng)式變量變成“只讀的”,如果修改就報警告。
-
基本語法:
const user = readonly({name:1,age:2})
-
isReadonly 用于判斷一個變量是否是readonly的,返回布爾值
-
基本語法:
const bol = isReadonly(x)
-
isProxy 用于判斷一個變量是否是響應(yīng)式的,返回布爾值
-
基本語法:
const bol = isProxy(x)
-
isReactive 用于判斷一個變量是否是reactive響應(yīng)式變量,返回布爾值
-
基本語法:
const bol = isReactive(x)
function?useUser() {
?const?user?=?readonly(reactive({name:'list',age:30}))
?console.log('user',?user)
?// setTimeout(()=>user.age=40, 2000)
?const?x?=?1
?const?y?=?readonly({a:1,b:{c:3}})
?console.log('是否被proxy攔截過',?isProxy(user),?isProxy(x),?isProxy(y.b))
?return?user
}
-
toRaw、markRaw
-
toRaw 用于返回一個響應(yīng)式變量的原始值
-
function?useRaw() { ?const?a1?=?{?title:?100?} ?const?a2?=?reactive(a1) ?const?a3?=?toRaw(a2) ?console.log('toRow(a2)===a1',?a3===a1) ?console.log('a2===a1',?a2===a1) ?return?[a1,a2,a3] }
基本語法:
const a3 = toRow(reactive(a1))
// a1===a3是true -
markRaw 用于把一個普通變量標(biāo)記成“不可proxy”的
-
基本語法:
const b2 = markRaw(b1)
// b2是無法被reactive的
-
computed、watch、watchEffect
-
computed 用于對響應(yīng)式變量進(jìn)行二次計算,當(dāng)它依賴的響應(yīng)式變量發(fā)生變化時會重新計算
-
基本語法:
const c = computed(()=>c1.value*c2.value)
// 只讀 -
基本語法:
const c = computed({get:()=>c1.value*c2.value,set:(newVal)=>c1.value=newVal})
?// 可寫可讀 -
watch 用于監(jiān)聽響應(yīng)式變量的變化,組件初始化它不執(zhí)行
-
基本語法:
const stop = watch(x, (new,old)=>{})
?// 調(diào)用stop()可以停止監(jiān)聽 -
基本語法:
const stop = watch([x,y], ([newX,newY],[oldX,oldY])=>{})
-
watchEffect 用于監(jiān)聽響應(yīng)式變量的變化,組件初始化會執(zhí)行
-
基本語法:
const stop = watchEffect(()=>ajax({cate,page,size}))
export default function useWatchComputed() {
const c1 = ref(10)
const c2 = ref(20)
const c3 = computed(()=>c1.value*c2.value) // 只讀
// 可讀也可寫
const c4 = computed({
? get: ()=>c1.value*c2.value,
? set: (newVal)=>{
? ? c1.value = parseInt(newVal) / c2.value
? }
})
const stop1 = watch(c4, (newC4, oldC4)=>console.log('c4變了', newC4, oldC4))
const stop2 = watch([c1,c2], ([newC1,newC2],[oldC1,oldC2])=>{
? console.log('[c1,c2] 新值:', [newC1, newC2])
? console.log('[c1,c2] 舊值:', [oldC1, oldC2])
})
const stop3 = watchEffect(()=>{console.log('watch effect', c1.value, c2.value)})
const update = (c,v) => c.value = v
return [[c1,c2,c3,c4],[stop1,stop2,stop3,update]]
}
2:也可以說亮點
-
性能比vue2.x快1.2~2倍
-
支持tree-shaking,按需編譯,體積比vue2.x更小
-
支持組合API
-
更好的支持TS
-
更先進(jìn)的組
3.更可以說性能
1.diff算法更快
vue2.0是需要全局去比較每個節(jié)點的,若發(fā)現(xiàn)有節(jié)點發(fā)生變化后,就去更新該節(jié)點
vue3.0是在創(chuàng)建虛擬dom中,會根據(jù)DOM的的內(nèi)容會不會發(fā)生內(nèi)容變化,添加靜態(tài)標(biāo)記, 誰有flag!比較誰。
2、靜態(tài)提升
vue2中無論元素是否參與更新,每次都會重新創(chuàng)建,然后再渲染 vue3中對于不參與更新的元素,會做靜態(tài)提升,只被創(chuàng)建一次,在渲染時直接復(fù)用即可
3、事件偵聽緩存
默認(rèn)情況下,onclick為動態(tài)綁定,所以每次都會追蹤它的變化,但是因為是同一函數(shù),沒有必要追蹤變化,直接緩存復(fù)用即可
在之前會添加靜態(tài)標(biāo)記8 會把點擊事件當(dāng)做動態(tài)屬性 會進(jìn)行diff算法比較, 但是在事件監(jiān)聽緩存之后就沒有靜態(tài)標(biāo)記了,就會進(jìn)行緩存復(fù)用
17.v-model有了解過嗎,原理是什么
這種原理性問題 ?不要直接說不清楚 不了解 ?
先講下使用
v-model本質(zhì)上是一個語法糖,可以看成是value + input 方法的語法糖??梢酝ㄟ^model的prop屬性和event事件來進(jìn)行自定義。
2、v-model是vue的雙向綁定的指令,能將頁面上控件輸入的值同步更新到相關(guān)綁定的data屬性, 也會在更新data
綁定屬性時候,更新頁面上輸入控件的值。
然后再來講細(xì)節(jié)
vue的雙向綁定是由數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式實現(xiàn)的,那么什么是數(shù)據(jù)劫持?vue是如何進(jìn)行數(shù)據(jù)劫持的?說白了就是通過Object.defineProperty()來劫持對象屬性的setter和getter操作,在數(shù)據(jù)變動時做你想要做的事情
我們已經(jīng)知道實現(xiàn)數(shù)據(jù)的雙向綁定,首先要對數(shù)據(jù)進(jìn)行劫持監(jiān)聽,所以我們需要設(shè)置一個監(jiān)聽器Observer,用來監(jiān)聽所有屬性。如果屬性發(fā)生變化了,就需要告訴訂閱者Watcher看是否需要更新。因為訂閱者是有很多個,所以我們需要有一個消息訂閱器Dep來專門收集這些訂閱者,然后在監(jiān)聽器Observer和訂閱者Watcher之間進(jìn)行統(tǒng)一管理的。接著,我們還需要有一個指令解析器Compile,對每個節(jié)點元素進(jìn)行掃描和解析,將相關(guān)指令(如v-model,v-on)對應(yīng)初始化成一個訂閱者Watcher,并替換模板數(shù)據(jù)或者綁定相應(yīng)的函數(shù),此時當(dāng)訂閱者Watcher接收到相應(yīng)屬性的變化,就會執(zhí)行對應(yīng)的更新函數(shù),從而更新視圖。因此接下去我們執(zhí)行以下3個步驟,實現(xiàn)數(shù)據(jù)的雙向綁定:
1.實現(xiàn)一個監(jiān)聽器Observer,用來劫持并監(jiān)聽所有屬性,如果有變動的,就通知訂閱者。
2.實現(xiàn)一個訂閱者Watcher,每一個Watcher都綁定一個更新函數(shù),watcher可以收到屬性的變化通知并執(zhí)行相應(yīng)的函數(shù),從而更新視圖。
3.實現(xiàn)一個解析器Compile,可以掃描和解析每個節(jié)點的相關(guān)指令(v-model,v-on等指令),如果節(jié)點存在v-model,v-on等指令,則解析器Compile初始化這類節(jié)點的模板數(shù)據(jù),使之可以顯示在視圖上,然后初始化相應(yīng)的訂閱者(Watcher)
3:最后補一下 vue2.0里面用Object.defineProperty ?3.0里面用new ?Proxy ? ? 一個監(jiān)聽每個屬性 一個監(jiān)聽整個對象
18.VUE組件如何與iframe通信問題
像這種問題其實問的不是特別詳情 ?面試者可能不懂題目的意思 ? 但是我們要學(xué)會揣摩 面試官的問題
如果不知道 你就直說vue的組件通信 在講iframe的頁面獲取v
vue組件內(nèi)嵌一個iframe,現(xiàn)在想要在iframe內(nèi)獲取父組件內(nèi)信息,采用的是H5新特性PostMessage來解決跨域問題
采用postMessage內(nèi)涵兩個API:
onMessage:消息監(jiān)聽
postMessage:消息發(fā)送
代碼和例子
<div class="mapbox">
? ? <iframe name="map" src="http://localhost:8083/setposition.html?add='add'"></iframe>
</div>
clearMap(){
? ? let map = document.getElementsByName("map")[0].contentWindow
? ? map.postMessage("clearMap","*")
? }
iframe內(nèi):
window.addEventListener('message', function (evt) {
?
? if (evt.data == 'clearMap'){
? ? ? clearMap()
? }
? //event.data獲取傳過來的數(shù)據(jù)
});
19.用過VUE 的自定義指令嗎?自定義指令的方法有哪些
這種問題一樣的 ?先回答經(jīng)常用的一些指定 比如 v-for ?v-if ?v-model ? v-show等等之類的 ?指令分為全局和局部的
然后在回答自定義指令
通過directive來自定義指令,自定義指令分為全局指令和局部指令,自定義指令也有幾個的鉤子函數(shù),常用的有bind和update,當(dāng)?bind?和?update?時觸發(fā)相同行為,而不關(guān)心其它的鉤子時可以簡寫。一個表達(dá)式可以使用多個過濾器。過濾器之間需要用管道符“|”隔開。其執(zhí)行順序從左往右。??
20.當(dāng)修改data時Vue的組件重渲染是異步還是同步
這個問題很有意思 ?因為平時我們一般問題異步和同步指的是 數(shù)據(jù)請求 同步和異步問題
這里加上了組件 ?還有修改data ? ? 這里給大家寫個例子
<body>
? <div id="app">
? ? ? <div id="main">{{num}}</div>
? ? ? <button @click="add">更新</button>
? </div>
</body>
<script>
? new Vue({
? ? ? el:"#app",
? ? ? data:{
? ? ? ? ? num:10
? ? ? },
? ? ? methods:{
? ? ? ? ? add(){
? ? ? ? ? ? ? this.num++;
? ? ? ? ? ? ? console.log(this.num)//11
? ? ? ? ? ? ? console.log(document.getElementById("main").innerHTML);//10
? ? ? ? ?
? ? ? ? ? }
? ? ? }
? })
</script>
以此可以說明 ?
數(shù)據(jù)更新是同步的 ?但是視圖更新是異步的
解決這個問題需要使用 $nextTick 解決視圖異步更新的問題
21. .sync修飾器的作用是
首先看到 .sync ?我們需要知道這是個修飾器 ? 類似修飾器還有 ?.stop ?.prevent ?之類
其實這個修飾符就是vue封裝了 子組件要修改父組件傳過來的動態(tài)值的語法糖,省去了父組件需要寫的方法,但是子組件emit時要加上update
在有些情況下,我們可能需要對一個 prop 進(jìn)行“雙向綁定”。不幸的是,真正的雙向綁定會帶來維護上的問題,因為子組件可以修改父組件,且在父組件和子組件都沒有明顯的改動來源
代碼解釋
// 這里父組件,要給子組件傳一個title的值
<template>
? <div> ?
? ? ? <t-title :title.sync="fatherTitle"></t-title>
? </div>
</template>
<script>
import tTitle from './blocks/list';
export default {
? name: 'test1',
? components: { tTitle },
? data() {
? ? ? return {
? ? ? ? ? fatherTitle: '父組件給的標(biāo)題'
? ? ? };
? },
}
</script>
// 子組件
<template>
? <div>
? ? ? <h3>{{ title }}</h3>
? ? ? <button @click="changeTitle">改變</button>
? </div>
</template>
<script>
export default {
? props:{
? ? ? title: {type: String, default: '默認(rèn)值11'}
? },
? methods: {
? ? ? changeTitle() {
? ? ? ? ? this.$emit("update:title", "子組件要改自己的標(biāo)題");
? ? ? }
? }
};
</script>
這里關(guān)鍵就是emit里的參數(shù)要寫成'update'+ ':' +'要修改的props'
以前是用的this.$emit("自定義方法")
22.vue多組件嵌套通信方式
這個問題其實也是屬于組件通信 ? 常見的組件通信有 父傳子 ?子傳父 ?子傳子 ?以及跨層級
這個多組件嵌套通信其實就是跨層級的另一種問法
多組件通信
方法一:props ?一層 一層的傳遞
方法二:依賴注入 ?provide 聲明 ?inject接收
方法三:利用公共的bus = new ?Vue() ? bus.$on ?聲明 ?bus.$emit() ? 調(diào)用
方法四:使用vuex 全局的狀態(tài)管理
23.vue如何讓css只在當(dāng)前組件生效
當(dāng)前組件<style>寫成<style scoped> ? 加上scoped就可以了 這個style中一般還有l(wèi)ang ? lang可以是less scss stylus 等等 不加scoped就是全局的樣式
24.Vue 的 keep-live 用過嗎?作用是什么?
-
沒有用過
-
用過,它的作用是可以在組件切換時,保存其包裹的組件的狀態(tài),使其不被銷毀,防止多次渲染。
25.keepalive,添加這個會比平常多生命周期嗎? keepalive 已經(jīng)緩存了,但是想跳回去的時候添加新的屬性在哪個生命周期里實現(xiàn)
?會比平常的組件多兩個生命周期鉤子函數(shù),分別是:activated 和 deactivated。使用keep-alive
包裹的組件在切換時不會被銷毀,而是緩存到內(nèi)存中并執(zhí)行 deactivated 鉤子函數(shù),再次渲染后會執(zhí)行 activated 鉤子函數(shù)。如果再一次跳回顯示組件的時候可以在 activated 中做處理
26.說一下 keep-alive 的關(guān)聯(lián)生命周期
?會比平常的組件多兩個生命周期鉤子函數(shù),分別是:activated 和 deactivated。使用keep-alive
包裹的組件在切換時不會被銷毀,而是緩存到內(nèi)存中并執(zhí)行 deactivated 鉤子函數(shù),再次渲染后會執(zhí)行 activated 鉤子函數(shù)。
27.Vue 創(chuàng)建項目的指令是什么
-
使用的官方 cli 腳手架,如果是低于 3.0 的版本,使用
npm init
-
cli 的版本大于 3.0 的使用
vue create
-
可以使用 vite 直接搭建項目,命令為
npm init vite@latest
,根據(jù)提示,一步一步操作就好
28.vue 中如何使用 ref 綁定
?通過為組件或者標(biāo)簽添加 ref 屬性,可以在 js 代碼中使用全局 api$refs
獲取 dom 元素或者組件,其上的方法或者屬性可以直接進(jìn)行操作。
29.vue 導(dǎo)航守衛(wèi)與 jq 導(dǎo)航攔截器的介紹
?vue 的導(dǎo)航守衛(wèi)一般指的是路由導(dǎo)航守衛(wèi),作用是在頁面跳轉(zhuǎn)的時候可以執(zhí)行一個鉤子函數(shù)。
?導(dǎo)航守衛(wèi)使用最多的是全局守衛(wèi) router.beforeEach 主要是用來驗證用戶的登陸狀態(tài)。它接收三個參數(shù) to, from, next
-
to: 即將要進(jìn)入的路由對象
-
from: 當(dāng)前導(dǎo)航要離開的路由
-
next: 一個回調(diào)函數(shù), 一定要調(diào)用這個方法,不然路由不會繼續(xù)往下
jq 導(dǎo)航攔截器沒有聽過,一般在 jQuery 的作用就是對 dom 元素做操作,jQuery 的核心功能是元素選擇器。至于提到的導(dǎo)航器可能是一類第三方 jQuery 插件?或者網(wǎng)絡(luò)請求攔截,如果是網(wǎng)絡(luò)請求攔截,那么 jQuery 發(fā)起請求的話,可以封裝一個全局 ajax 請求插件,通過設(shè)置 ajaxSetup 實現(xiàn)
?// 參考這個 https://www.runoob.com/jquery/ajax-ajaxsetup.html
?$.ajaxSetup({
? ?// url: 'demo_ajax_load.txt',
? ?beforeSend() {
? ? ?// 發(fā)起請求之前執(zhí)行
? },
? ?complete() {
? ? ?// 所有的請求成功之后執(zhí)行
? },
});
30.vue 常用哪些命令
-
v-model 指令,用于表單輸入。
-
v-on 指令,用于事件綁定。
-
v-bind 指令,用于動態(tài)綁定一個值和傳入變量。
-
v-once 指令,事件只能用一次,無論點擊幾次,執(zhí)行一次之后都不會再執(zhí)行。
-
v-html 指令,會將 span 的內(nèi)容替換成 rawHtml 的屬性值,直接作為 HTML 代碼解析。
-
v-for 指令,與 HTML 標(biāo)簽結(jié)合使用,用于數(shù)據(jù)的遍歷擺放。
-
v-if 指令,用來進(jìn)行條件判斷的,直接操作 dom。
-
v-else 指令,用來進(jìn)行條件判斷的,與 v-if 指令連用,意義為條件不成立時執(zhí)行。
-
v-show 指令,根據(jù)真假切換元素的顯示狀態(tài)。
31.vue 中插槽共有幾種,及插槽的作用
?三種:默認(rèn)插槽、具名插槽、作用域插槽
-
默認(rèn)插槽
默認(rèn)插槽就是指<slot>,<slot>的作用類似于占符。
//定義一個全局子組件 Vue.component('child', { ?template:?'<div><slot></slot></div>', }); var?vm?=?new?Vue({ ?el:?'#root', }); <!--引用child組件--> <div?id="root"> ?<child> ? ?<span>我是占位符</span> ?</child> </div>
上述的子組件 child 里定義的 slot 被 span 標(biāo)簽給代替了,如果子組件里沒有定義 slot,則 span 標(biāo)簽會被直接忽略,且一個子組件里只能定義一個單個插槽。
-
具名插槽
可以通過設(shè)置 name 屬性,指定顯示的位置
定義一個<base-layout>?組件:
<div?class="container"> ?<header> ? ?<slot?name="header"></slot> ?</header> ?<main> ? ?<slot></slot> ?</main> ?<footer> ? ?<slot?name="footer"></slot> ?</footer> </div> <base-layout> ?<template?v-slot:header> ? ?<h1>Here might be a page title</h1> ?</template> ?<p>A paragraph for the main content.</p> ?<p>And another one.</p> ?<template?v-slot:footer> ? ?<p>Here's some contact info</p> ?</template> </base-layout>
-
作用域插槽
父組件替換插槽標(biāo)簽,但是內(nèi)容由子組件來提供
<body> ?<div?id="root"> ? ?<child> ? ? ?<!--定義一個插槽,該插槽必須放在template標(biāo)簽內(nèi)--> ? ? ?<template?slot-scope="props"> ? ? ? ?<li>{{props.value}}</li> ? ? ?</template> ? ?</child> ? ?<!--!--定義不同的渲染方式--> ? ?<child> ? ? ?<!--slot-scope="props"作用是使props指向子組件中定義的<slot>--> ? ? ?<template?slot-scope="props"> ? ? ? ?<h1>{{props.value}}</h1> ? ? ?</template> ? ?</child> ?</div> </body> <script> ?//定義一個全局子組件 ?Vue.component('child', { ? ?data:?function?() { ? ? ?return?{ ? ? ? ?list: [1,?2,?3,?4], ? ? }; ? }, ? ?template: ? ? ?'<div><ul><slot v-for="value in list" :value=value></slot></ul></div>', }); ?var?vm?=?new?Vue({ ? ?el:?'#root', }); </script>
32.vue 如何使用插件
?直接安裝,引入就能使用。vue 還是 js,只要是 js 那么所有的插件使用都是相同的方式,引入綁定到對應(yīng)的節(jié)點或者操作對應(yīng)的節(jié)點就好。
33.Vue 組件懶加載,圖片懶加載
組件懶加載
-
結(jié)合路由插件使用的時候使用 import 方式實現(xiàn)
// 第一步注釋import導(dǎo)入的文件
// import About from '../components/About.vue';
// 第二步將引入組件的方式以箭頭函數(shù)的方式異步引入
const?routes?=?[
{
? ?path:?'/about',
? ?component: ()?=>?import(?/* webpackChunkName: 'about' */?'../components/About.vue'?)
}
]
````
2.?引入組件的時候使用回調(diào)函數(shù)的方式引入,比如
```js
// 組件懶加載
const IconList = () => import('components/base/icon-list');
export default {
?components: {
? ?IconList,
?},
};
````
圖片懶加載
就是在加載頁面的時候,如果頁面中的圖片過多,可以使用占位符的方式替換沒有在可是區(qū)域內(nèi)的圖片,只加載當(dāng)前需要現(xiàn)實的圖片。監(jiān)聽滾動條的位置,當(dāng)圖片標(biāo)簽出現(xiàn)在可視區(qū)域的時候,重置圖片的路徑為真是路徑,然后展示圖片地址。一般在實際開發(fā)的時候都直接使用圖片懶加載插件實現(xiàn)。還有一種解決方案就是使用頁面骨架屏效果,也是類似占位顯示,當(dāng)數(shù)據(jù)加載完成之后替換掉占位顯示的內(nèi)容
34.使用Vue封裝過組件嗎?有哪些?講一下他們是怎么實現(xiàn)的
比如做后臺管理中,很多模塊經(jīng)常會復(fù)用,比如側(cè)邊導(dǎo)航組件、項目中常用的 echarts圖表的封裝(比如折線圖、柱狀圖等)
封裝組件需要考慮復(fù)用性:
-
預(yù)留插槽slot, 多次調(diào)用如果 子組件視圖結(jié)構(gòu)不一樣那么就要 在 子組件template預(yù)留好 插槽(單個插槽、具名插槽,作用域插槽)
-
考慮到數(shù)據(jù)傳遞,定義props 組件接收父組件傳遞的數(shù)據(jù),同時需要注意單向數(shù)據(jù)流,props不能直接修改,$emit自定義事件,父組件修改
-
業(yè)務(wù)邏輯不要在子組件中處理,子組件在不同父組件中調(diào)用時,業(yè)務(wù)處理代碼不同,切記不要直接在子組件中處理業(yè)務(wù),應(yīng)該子組件 $emit自定義事件,將數(shù)據(jù)傳遞給父組件,父組件處理業(yè)務(wù)。
35.說說vuex的管理操作或理解
vuex是 vue的一個狀態(tài)管理插件,采用集中式管理方式,來管理項目中多個組件的公共狀態(tài)。
vuex有一個倉庫概念,將組件公共的state存儲在倉庫的state屬性中,state是只讀的,組件只能使用,不能直接修改,修改需要通過 倉庫中的mutations模塊來修改,這樣的好處是 當(dāng)數(shù)據(jù)修改便于溯源,且不會因為 多個組件 直接修改數(shù)據(jù),導(dǎo)致 組件間數(shù)據(jù)的互相影響, 同時 當(dāng)我們倉庫中有一個state 數(shù)據(jù)需要請求 數(shù)據(jù)接口才能獲取時,vuex 設(shè)計了一個action模塊,在action模塊中發(fā)送異步請求,得到數(shù)據(jù)后,提交mutation來修改state。當(dāng)state發(fā)生改變后組件自動刷新,在組件中可以commit mutation或者dispatch action來修改state。
具體工作流程如下圖
36.說說Vuex的工作流程
vuex的倉庫有5個模塊,分別是 state,mutations, actions, getters, modules
我們將組件的公共狀態(tài)定義在 vuex倉庫的state中,state是只讀的,無法直接修改,必須調(diào)動倉庫中的某個mutation才能修改狀態(tài),getters可以理解為vuex中的計算屬性,當(dāng)我們在某個組件中使用vuex中的某個state時,不是直接使用原值,而是需要派生出一個新的值,就可以定義getters,可以在組件中獲取。當(dāng)依賴的state發(fā)生改變,此時getters會重新計算得到新值,同時 action中可以發(fā)送異步請求,得到數(shù)據(jù)后,commit mutation來給state賦值
具體代碼如下:
倉庫代碼
const?store?=?new?Vuex.Store({
? ?state: {
? ? ? ?items: []?// 定義一個公共的購物車數(shù)據(jù)
? },
? ?getters: {
? ? ? ?// 可以基于已有的state 派生新的狀態(tài)
? ? ? ?selectedItems?(state) {
? ? ? ? ? ?// 過濾購物車中未選中的商品
? ? ? ? ? ?return?state.items.filter(item?=>?item.selected)
? ? ? }
? },
? ?mutations: {
? ? ? ?// 定義mutation來修改state
? ? ? ?INIT_ITEMS(state,?items){
? ? ? ? ? ?state.items?=?items
? ? ? }
? },
? ?actions: {
? ? ? ?// action可以發(fā)送異步請求,得到數(shù)據(jù)后commit mutation將請求結(jié)果傳入
? ? ? ?FETCH_ITEMS({commit},?params?=?{}){
? ? ? ? ? ?// 調(diào)用封裝好的 接口函數(shù)
? ? ? ? ? ?fetchItem(params).then(res?=>?{
? ? ? ? ? ? ? ?if(res.data.code?===?200) {
? ? ? ? ? ? ? ? ? ?commit('INIT_ITEMS',?res.data.data)
? ? ? ? ? ? ? }
? ? ? ? ? })
? ? ? }
? }
})
組件中使用 使用vuex
// 獲取state
this.$store.state.items?// 直接獲取
{
? ?computed: {
...mapState(['items'])?// 助手函數(shù)獲取
? }
}
// 獲取getters
this.$store.getters.selectedItems?// 直接獲取
{
? ?computed: {
? ? ? ?...mapGetters(['selectedItems'])?// 助手函數(shù)獲取
? }
}
// 組件中提交action
this.$store.dispatch('FETCH_ITEMS', {token:?'xxx'})
{
? ?methods: {
? ? ? ?...mapActions(['FETCH_ITEMS'])?// 助手函數(shù) 直接調(diào)用this.FETCH_ITEMS(params)觸發(fā)
? }
}
// 組件中也可以直接commit mutation
this.$store.commit('INIT_ITEMS'[,參數(shù)])
{
? ?methods:{
? ? ? ?...mapMutations(['INIT_ITEMS'])?// 助手函數(shù) 直接調(diào)用this.INIT_ITEMS(參數(shù))
? }
}
37.vuex項目中怎么使用?工作原理是什么?
原則:
中小型項目中,如果組件的公共狀態(tài)不多的情況下,不建議使用vuex,反而會增加代碼復(fù)雜度,想要組件通信,直接通過event bus即可,中大型項目中,多個組件公共狀態(tài)較多情況下,建議使用vuex文章來源:http://www.zghlxwxcb.cn/news/detail-686778.html
vuex的具體工作流程如下:
在倉庫state中定義公共狀態(tài),action中發(fā)送異步請求,得到數(shù)據(jù)后調(diào)用mutation 賦值給state,組件中使用state,也可以在組件中 dispatch action和觸發(fā)mutation來修改state,視圖刷新
具體代碼如下:
倉庫代碼
const?store?=?new?Vuex.Store({
? ?state: {
? ? ? ?items: []?// 定義一個公共的購物車數(shù)據(jù)
? },
? ?getters: {
? ? ? ?// 可以基于已有的state 派生新的狀態(tài)
? ? ? ?selectedItems?(state) {
? ? ? ? ? ?// 過濾購物車中未選中的商品
? ? ? ? ? ?return?state.items.filter(item?=>?item.selected)
? ? ? }
? },
? ?mutations: {
? ? ? ?// 定義mutation來修改state
? ? ? ?INIT_ITEMS(state,?items){
? ? ? ? ? ?state.items?=?items
? ? ? }
? },
? ?actions: {
? ? ? ?// action可以發(fā)送異步請求,得到數(shù)據(jù)后commit mutation將請求結(jié)果傳入
? ? ? ?FETCH_ITEMS({commit},?params?=?{}){
? ? ? ? ? ?// 調(diào)用封裝好的 接口函數(shù)
? ? ? ? ? ?fetchItem(params).then(res?=>?{
? ? ? ? ? ? ? ?if(res.data.code?===?200) {
? ? ? ? ? ? ? ? ? ?commit('INIT_ITEMS',?res.data.data)
? ? ? ? ? ? ? }
? ? ? ? ? })
? ? ? }
? }
})
組件中使用 使用vuex
// 獲取state
this.$store.state.items?// 直接獲取
{
? ?computed: {
...mapState(['items'])?// 助手函數(shù)獲取
? }
}
// 獲取getters
this.$store.getters.selectedItems?// 直接獲取
{
? ?computed: {
? ? ? ?...mapGetters(['selectedItems'])?// 助手函數(shù)獲取
? }
}
// 組件中提交action
this.$store.dispatch('FETCH_ITEMS', {token:?'xxx'})
{
? ?methods: {
? ? ? ?...mapActions(['FETCH_ITEMS'])?// 助手函數(shù) 直接調(diào)用this.FETCH_ITEMS(params)觸發(fā)
? }
}
// 組件中也可以直接commit mutation
this.$store.commit('INIT_ITEMS'[,參數(shù)])
{
? ?methods:{
? ? ? ?...mapMutations(['INIT_ITEMS'])?// 助手函數(shù) 直接調(diào)用this.INIT_ITEMS(參數(shù))
? }
}
38.Vuex中處理異步需要在什么地方寫
異步處理需要在 倉庫的actions中定義
Action 類似于 mutation,不同在于:
-
Action 提交的是 mutation,而不是直接變更狀態(tài)。
-
Action 可以包含任意異步操作。
我們可以在action中發(fā)送異步請求,成功后觸發(fā)mutation 將結(jié)果傳入,在mutation賦值給state
const?store?=?new?Vuex.Store({
? ?state: {
? ? ? ?items: []?// 定義一個公共的購物車數(shù)據(jù)
? },
? ?mutations: {
? ? ? ?// 定義mutation來修改state
? ? ? ?INIT_ITEMS(state,?items){
? ? ? ? ? ?state.items?=?items
? ? ? }
? },
? ?actions: {
? ? ? ?// action可以發(fā)送異步請求,得到數(shù)據(jù)后commit mutation將請求結(jié)果傳入
? ? ? ?FETCH_ITEMS({commit},?params?=?{}){
? ? ? ? ? ?// 調(diào)用封裝好的 接口函數(shù)
? ? ? ? ? ?fetchItem(params).then(res?=>?{
? ? ? ? ? ? ? ?if(res.data.code?===?200) {
? ? ? ? ? ? ? ? ? ?commit('INIT_ITEMS',?res.data.data)
? ? ? ? ? ? ? }
? ? ? ? ? })
? ? ? }
? }
})
39.請你談?wù)勀銓uex的理解
vuex是專為vue設(shè)計的狀態(tài)管理工具,可用于父子組件和非父子組件的全局組件通信。應(yīng)用的狀態(tài)集中放在store中,改變狀態(tài)必須要經(jīng)過commit,同步改變狀態(tài)是提交mutations,異步是先通過actions再通過mutations。
一共有5大模塊- state存放狀態(tài)- getters就像計算屬性一樣,getter 的返回值會根據(jù)它的依賴被緩存起來,且只有當(dāng)它的依賴值發(fā)生了改變才會被重新計算??梢詫tate中的數(shù)據(jù)做一些處理- mutations更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation,通過store.commit提交到mutations模塊- actionsactions是異步的改變state中狀態(tài)的方法,通過store.dispatch來提交到mutations模塊,再通過提交commit來更改state中的狀態(tài)- modulesVuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割
40.vuex—個模塊中改變state中數(shù)據(jù),其他模塊如何獲取
由于使用單一狀態(tài)樹,應(yīng)用的所有狀態(tài)會集中到一個比較大的對象。當(dāng)應(yīng)用變得非常復(fù)雜時,store 對象就有可能變得相當(dāng)臃腫。
為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割:
vuex模塊化后,需要另一個模塊的state變化,可以在這個模塊中定義getters 獲取,具體代碼如下
// 模塊a
const?modulea?=?{
? ?namespaced:?true,
? ?state: {
? ? ? ?num:?10
? },
? ?mutations: {
? ? ? ?ADD_NUM(state,?n) {
? ? ? ? ? ?state.num?+=?n
? ? ? }
? }
}
// 模塊b
const?moduleb?=?{
? ?namespaced:?true,
? ?state: {
? ? ? ?num:?10
? },
? ?getters: {
? ? ? ?// 在這里拿到 模塊a numstate
? ? ?moduleaNum?(state,?getters,?rootState,?rootGetters) {
? ? ? ? ?// 模塊下的getter有四個參數(shù)分別是當(dāng)前模塊的state,當(dāng)前模塊的getters,以及根state個根getters可以通過rootState獲取其他模塊的state
? ? ? ? ?return?rootState.modulea.num
? ? ? ? ?
? ? } ?
? },
? ?mutations: {
? ? ? ?ADD_NUM(state,?n) {
? ? ? ? ? ?state.num?+=?n
? ? ? }
? }
}
41.vuex的狀態(tài)是怎樣的,怎么改變狀態(tài)
vuex的狀態(tài)儲存在倉庫的state屬性中,state是只讀的,無法直接修改必須調(diào)用mutation才能修改
const?store?=?new?Vuex.Store({
? ?state: {
? ? ? ?num:?10
? },
? ?mutations: {
? ? ? ?ADD_NUM?(state,?n) {
? ? ? ? ? ?state.num?+=?n
? ? ? }
? }
})
// 在組件中直接出發(fā)mutaion
this.$store.commit('ADD_NUM',?10)
// 或者助手函數(shù) 提交 mutation
{
? ?methods: {
? ? ? ?...mapMutations(['ADD_NUM'])
? }
}
// 直接調(diào)用即可
this.ADD_NUM(10)
42.你在項目中哪里使用vuex,vuex的應(yīng)用場景
原則:
中小型項目中,如果組件的公共狀態(tài)不多的情況下,不建議使用vuex,反而會增加代碼復(fù)雜度,想要組件通信,直接通過event bus即可,中大型項目中,多個組件公共狀態(tài)較多情況下,建議使用vuex
在項目中,多個組件的公共狀態(tài)可以存儲的vuex中,比如電商網(wǎng)站的購物車數(shù)據(jù),可以存儲在vuex中。后臺管理角色鑒權(quán)中的 不同角色的側(cè)邊欄數(shù)據(jù),以及 不同角色可以訪問的路由數(shù)據(jù)可以存儲的vuex中,拿到數(shù)據(jù)儲存。文章來源地址http://www.zghlxwxcb.cn/news/detail-686778.html
到了這里,關(guān)于【直接收藏】前端 VUE 高階面試題(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!