爬vue

1、$nextTick

(1)原理
說法一:
Vue在更新DOM時(shí)是異步執(zhí)行的。
只要監(jiān)聽到數(shù)據(jù)變化,vue就會(huì)開啟一個(gè)隊(duì)列,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)變化。
如果同一個(gè)監(jiān)聽,被多次觸發(fā)了,只會(huì)被推入隊(duì)列一次。這種會(huì)在緩沖時(shí)去除重復(fù)數(shù)據(jù),避免不必要的計(jì)算和DOM操作。
這樣是為了提高性能,因?yàn)橹骶€程中更新DOM,循環(huán)100次就要更新100次DOM,如果事件循環(huán)之后,就只需要更新一次。
為了數(shù)據(jù)更新操作之后操作DOM,那在數(shù)據(jù)變化之后,用Vue.$nextTick,這樣回調(diào)函數(shù)會(huì)在DOm更新完成后被調(diào)用,就可以拿到最新的DOM元素了

說法二:
由于Vue DOM更新是異步執(zhí)行的,
即修改數(shù)據(jù)時(shí),視圖不會(huì)立即更新,而是會(huì)監(jiān)聽數(shù)據(jù)變化,
并緩存在同一事件循環(huán)中,等同一數(shù)據(jù)循環(huán)中的所有數(shù)據(jù)變化完成之后,再統(tǒng)一進(jìn)行視圖更新。
這樣是為了提高性能,因?yàn)樵谥骶€程中更新DOM,循環(huán)100次,就要更新100次DOM,如果事件循環(huán)完之后,就只需要更新一次。
為了確保得到更新后的DOM,就用$nextTick

應(yīng)用場(chǎng)景:
(1)在created鉤子函數(shù)中,要進(jìn)行DOM操作
在created鉤子函數(shù),DOM都還沒有渲染,所以此時(shí)要進(jìn)行DOM操作的話,就要用到nextTick 在工作中,后臺(tái)管理系統(tǒng),在created請(qǐng)求數(shù)據(jù),并進(jìn)行頁(yè)面渲染時(shí),要勾選上表格復(fù)選框的值,進(jìn)行此操作要放到nextTick中
(2)要改變DOM元素結(jié)構(gòu)時(shí),對(duì)DOM進(jìn)行的操作都要放到$nextTick的回調(diào)函數(shù)中。

2、新技術(shù)

vite (打包機(jī),熱加載很快,比webpack要快)

3、vue項(xiàng)目,為什么要在列表組件中寫key,作用是?

(1)渲染真實(shí)的dom開銷很大,如果修改某個(gè)數(shù)據(jù),在vue中,采用diff算法,diff算法就會(huì)比較新舊節(jié)點(diǎn)的變化,如果某個(gè)節(jié)點(diǎn)修改了,就重新渲染節(jié)點(diǎn),其它節(jié)點(diǎn)就復(fù)用舊節(jié)點(diǎn),這樣大大減少了開銷,diff算法只會(huì)比較同一層次的節(jié)點(diǎn)。
(2)如果節(jié)點(diǎn)類型不同,直接干掉前面的節(jié)點(diǎn)了,并創(chuàng)建,插入新節(jié)點(diǎn),不會(huì)再比較這個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)了。
(3)當(dāng)要插入一條數(shù)據(jù)時(shí),節(jié)點(diǎn)都有key值為唯一標(biāo)識(shí),那么diff算法就可以正確識(shí)別此節(jié)點(diǎn),找到正確的位置插入新的節(jié)點(diǎn)。

總:需要使用key來給每個(gè)節(jié)點(diǎn)做唯一標(biāo)識(shí),Diff算法就可以正常識(shí)別些節(jié)點(diǎn)。
主要為了高效的更新虛擬DOM。

4、vue的自定義指令(待看)

自定義指令分為全局指令和組件指令,其中全局指令需要使用directive來進(jìn)行定義,組件指令需要使用directives來進(jìn)行定義,具體定義方法同過濾器filter或者其他生命周期,具體使用方法如下:

全局自定義指令 directive(name,{}),其中name表示定義的指令名稱(定義指令的時(shí)候不需要帶v-,但是在調(diào)用的時(shí)候需要哦帶v-),第二個(gè)參數(shù)是一個(gè)對(duì)象,對(duì)象中包括五個(gè)自定義組件的鉤子函數(shù),具體包括:

bind函數(shù):只調(diào)用一次,指令第一次綁定在元素上調(diào)用,即初始化調(diào)用一次,

inserted函數(shù):并綁定元素插入父級(jí)元素(即new vue中el綁定的元素)時(shí)調(diào)用(此時(shí)父級(jí)元素不一定轉(zhuǎn)化為了dom)

update函數(shù):在元素發(fā)生更新時(shí)就會(huì)調(diào)用,可以通過比較新舊的值來進(jìn)行邏輯處理

componentUpdated函數(shù):元素更新完成后觸發(fā)一次

unbind函數(shù):在元素所在的模板刪除的時(shí)候就觸發(fā)一次

鉤子函數(shù)對(duì)應(yīng)的參數(shù)el,binding,vnode,oldnode,具體參數(shù)講解如下:

a、el指令所綁定的元素 可以直接操組dom元素

b、binding一個(gè)對(duì)象,具體包括以下屬性:

1)name:定義的指令名稱 不包括v-

2)value:指令的綁定值,如果綁定的是一個(gè)計(jì)算式,value為對(duì)應(yīng)計(jì)算結(jié)果

3)oldvalue:指令綁定元素的前一個(gè)值,只對(duì)update和componentUpdated鉤子函數(shù)有值

4)expression:指令綁定的原始值 不對(duì)值進(jìn)行任何加工

5)arg:傳遞給指令的參數(shù)

6)modifiers:指令修飾符,如:v-focus.show.async 則接收的modifiers為{show:true,async:true}

c、vnode:vue編譯生成的虛擬dom

d、oldVnode:上一個(gè)vnode,只在update和componentUpdated鉤子函數(shù)中有效

??:如果不需要其他鉤子函數(shù),可以直接簡(jiǎn)寫為:directive(“focus”,function(el,binding){})

5、vue的實(shí)現(xiàn)原理

vue.js是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個(gè)屬性的setter,getter,在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽回調(diào)。

具體步驟
第一步:需要observe的數(shù)據(jù)對(duì)象進(jìn)行遞歸遍歷
包括子屬性對(duì)象的屬性,都加上setter和getter
這樣的話,給這個(gè)對(duì)象的某個(gè)值賦值,就會(huì)觸發(fā)setter,那么就能監(jiān)聽到了數(shù)據(jù)變化
第二步:compile解析模板指令
將模板中的變量替換成數(shù)據(jù),然后初始化渲染頁(yè)面視圖,并將每個(gè)指令對(duì)應(yīng)的節(jié)點(diǎn)綁定更新函數(shù),添加監(jiān)聽數(shù)據(jù)的訂閱者,一旦數(shù)據(jù)有變動(dòng),收到通知,更新視圖
第三步:Watcher訂閱者是Observer和Compile之前通信的橋梁
主要做的事情是:
(1)在自身實(shí)例化時(shí)往屬性訂閱器(dep)里面添加自己
(2)自身必須有一個(gè)update()方法
(3)待屬性變動(dòng)dep.notice()通知時(shí),能調(diào)用自身的update()方法,并觸發(fā)Compile中綁定的回調(diào),則功成身退。
第四步:MVVM作為數(shù)據(jù)綁定的入口,整合Observer、Compile和Watcher三者,通過Observer來監(jiān)聽自己的model數(shù)據(jù)變化。通過Compile之間的通信橋梁,達(dá)到數(shù)據(jù)變化->視圖更新;視圖交互變化(input)->數(shù)據(jù)mode變更的雙向綁定結(jié)果。

6、vue的diff算法理解

(1)diff算法的作用:用來修改dom的一小段,不會(huì)引起dom樹的重繪
(2)diff算法的實(shí)現(xiàn)原理:diff算法將wirtual dom(虛擬dom)的某個(gè)節(jié)點(diǎn)數(shù)據(jù)改變后生成的新的vnode與舊節(jié)點(diǎn)進(jìn)行比較,并替換為新的節(jié)點(diǎn),具體過程就是調(diào)用patch方法,比較新舊節(jié)點(diǎn),一邊比較一邊給真實(shí)的dom打補(bǔ)丁進(jìn)行替換
(3)diff算法是:(eno)
diff算法就是進(jìn)行虛擬節(jié)點(diǎn)對(duì)比,并返回一個(gè)patch對(duì)象,用來存儲(chǔ)兩個(gè)節(jié)點(diǎn)不同的地方,最后用patch記錄的消息去局部更新Dom。
(4)具體過程詳解

a、在采用diff算法進(jìn)行新舊節(jié)點(diǎn)進(jìn)行比較的時(shí)候,比較是按照在同級(jí)進(jìn)行比較的,不會(huì)進(jìn)行跨級(jí)比較:


image.png

b、當(dāng)數(shù)據(jù)發(fā)生改變的時(shí)候,set方法會(huì)調(diào)用dep.notify通知所有的訂閱者watcher,訂閱者會(huì)調(diào)用patch函數(shù)給響應(yīng)的dom進(jìn)行打補(bǔ)丁,從而更新真實(shí)的視圖

c、patch 函數(shù)接受兩個(gè)參數(shù),第一個(gè)是舊節(jié)點(diǎn),第二個(gè)是新節(jié)點(diǎn),首先判斷兩個(gè)節(jié)點(diǎn)是否值得比較,值得比較則執(zhí)行patchVnode函數(shù),不值得比較則將舊節(jié)點(diǎn)替換為新節(jié)點(diǎn)。如果兩個(gè)節(jié)點(diǎn)一樣就直接檢查對(duì)應(yīng)的子節(jié)點(diǎn),如果子節(jié)點(diǎn)不一樣就說明整個(gè)子節(jié)點(diǎn)全部改變不再往下對(duì)比直接進(jìn)行新舊節(jié)點(diǎn)的整體替換

d、patchCVnode函數(shù):找到真實(shí)的dom元素;判斷新舊節(jié)點(diǎn)是否指向同一個(gè)對(duì)象,如果是就直接返回;如果新舊節(jié)點(diǎn)都有文本節(jié)點(diǎn),那么直接將新的文本節(jié)點(diǎn)賦值給dom元素并且更新舊的節(jié)點(diǎn)為新的節(jié)點(diǎn)。如果舊節(jié)點(diǎn)有子節(jié)點(diǎn)再新節(jié)點(diǎn)沒有,則直接刪除dom元素中的子節(jié)點(diǎn);如果舊節(jié)點(diǎn)沒有子節(jié)點(diǎn),新節(jié)點(diǎn)有子節(jié)點(diǎn),那么直接將新節(jié)點(diǎn)中的子節(jié)點(diǎn)更新到dom中;如果兩者都有子節(jié)點(diǎn),那么繼續(xù)調(diào)用函數(shù)updateChildren

e、updateChildren函數(shù):抽離出新舊節(jié)點(diǎn)的所有子節(jié)點(diǎn),并且設(shè)置新舊節(jié)點(diǎn)的開始指針和結(jié)束指針,然后進(jìn)行兩輛比較,從而更新dom(調(diào)整順序或者插入新的內(nèi)容,結(jié)束后刪除多余的內(nèi)容)

7、vue的路由模式及區(qū)別、底層原理

vue-router有2種模式來實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)
1.hash模式
hash模式是通過利用url中的hash值來實(shí)現(xiàn)路由,而hash值的變化是不會(huì)刷新頁(yè)面。
hash底層原理:通過window.onhashchange事件監(jiān)聽url上的hash值變化,然后獲取hash值(window.location.hash),根據(jù)hash值分別把不同組件內(nèi)容渲染到router-link標(biāo)簽上,該方法必須在服務(wù)器環(huán)境下運(yùn)行。
注:onhashchange 事件在當(dāng)前 URL 的錨部分(以 '#' 號(hào)為開始) 發(fā)生改變時(shí)觸發(fā) 。

2、history模式
history模式根據(jù)html5新增的2個(gè)方法pushState和replaceState來實(shí)現(xiàn)路由,而且2種方法修改url時(shí)不會(huì)刷新頁(yè)面(路由沒有帶’#‘,需要后端支持)
history router底層原理
根據(jù)路由變化調(diào)用 pushState()和replaceState()方法修改url,通過window.onpopstate事件監(jiān)聽url的變化分別把不同組件的內(nèi)容渲染到router-link標(biāo)簽上。

hash模式在瀏覽器中符號(hào)”#“,#以及#后面的字符稱之為hash,用window.location.hash讀取。
特別:hash雖然在URL中,但不被包括在HTTP請(qǐng)求中;用來指導(dǎo)瀏覽器動(dòng)作,對(duì)服務(wù)端安全無(wú)用,hash不會(huì)重加載頁(yè)面。

history模式:history受用HTML5的新特性;
提供了兩個(gè)新方法:pushState(),replaceState() 可以對(duì)瀏覽器歷史記錄棧進(jìn)行修改,以及popState事件的監(jiān)聽到狀態(tài)變更。history模式下,前端的URL必須和實(shí)際向后端發(fā)起請(qǐng)求的URL一致,否則會(huì)報(bào)404錯(cuò)誤

8、組件通信

(1)子傳父
emit
(2)父?jìng)髯?br> props
(3)兄弟傳(有共同的父親)
(4)vuex 刷新數(shù)據(jù)會(huì)丟失
vuex 是 vue 的狀態(tài)管理器,存儲(chǔ)的數(shù)據(jù)是響應(yīng)式的。但是并不會(huì)保存起來,刷新之后就回到了初始狀態(tài),具體做法應(yīng)該在vuex里數(shù)據(jù)改變的時(shí)候把數(shù)據(jù)拷貝一份保存到localStorage里面,刷新之后,如果localStorage里有保存的數(shù)據(jù),取出來再替換store里的state。
(5)ref (6)slot (7)路由通信 (8)多級(jí)組件嵌套組件通信attrs/$listeners

image.png

9、vue的MVVM的理解

MVVM 是Model-View-ViewMode的縮寫
Mode:代表數(shù)據(jù)模型,主要用于定義數(shù)據(jù)和操作業(yè)務(wù)邏輯
View:代表頁(yè)面展示組件,視圖
ViewModel為mode和view的橋梁,監(jiān)聽模型數(shù)據(jù)改變和控制視圖行為,處理用戶交互。
通過雙向數(shù)據(jù)綁定把View和Model層連接起來,

在MVVM架構(gòu)中,View和Model之前并沒有直接的聯(lián)系,而是通過ViewModel進(jìn)行交互,Model和ViewModel之前的交互是雙向的,因此View數(shù)據(jù)的變化會(huì)同步到Model中,而Model數(shù)據(jù)的變化也會(huì)立即反應(yīng)到View上。

image.png

10、vue實(shí)現(xiàn)的原理

vue.js是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方法,通過Object.defineProperty()來劫持各個(gè)屬性的setter,getter,在數(shù)據(jù)變動(dòng)時(shí),發(fā)表信息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽回調(diào)。
具體步驟:
第一步:需要observe(觀察)的數(shù)據(jù)對(duì)象進(jìn)行遞歸遍歷,包括子屬性對(duì)象的屬性,都加上setter和getter
這樣的話,給這個(gè)對(duì)象的某個(gè)值賦值,就會(huì)觸發(fā)setter,那么就能監(jiān)聽到了數(shù)據(jù)變化

第二步:compile解析模塊指令,將模板中的變量替換成數(shù)據(jù),然后初始化渲染頁(yè)面視圖,并將每個(gè)指令對(duì)應(yīng)的節(jié)點(diǎn)綁定更新函數(shù),添加監(jiān)聽數(shù)據(jù)的訂閱者,一旦數(shù)據(jù)有變動(dòng),收到通知,更新視圖。

第三步:Watcher訂閱者是Observer和Compile之間通信的橋梁,主要做的事情是:
1.1在自身實(shí)例化時(shí)往屬性訂閱dep里面添加自己
2.2自身必須有一個(gè)update()方法
3.3待屬性變動(dòng)dep.notice()通知時(shí),能調(diào)用自身的update()方法,并觸發(fā)Compile中綁定的回調(diào),則功成身退。

第四步:MVVM作為數(shù)據(jù)綁定的入口,整合Observer、Compile和Watcher三者,通過Observer來監(jiān)聽自己的mode數(shù)據(jù)變化,通過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋梁,達(dá)到數(shù)據(jù)變化 -》視圖更新;視圖交互變化(input)-》數(shù)據(jù)model變更的雙向數(shù)據(jù)綁定效果。

11、vue與react、angular的比較?

Vue

輕量級(jí)框架:只關(guān)注視圖層,是一個(gè)構(gòu)建數(shù)據(jù)的視圖集合,大小只有幾十kb;
簡(jiǎn)單易學(xué):國(guó)人開發(fā),中文文檔,不存在語(yǔ)言障礙 ,易于理解和學(xué)習(xí);
雙向數(shù)據(jù)綁定:保留了angular的特點(diǎn),在數(shù)據(jù)操作方面更為簡(jiǎn)單;
組件化:保留了react的優(yōu)點(diǎn),實(shí)現(xiàn)了html的封裝和重用,在構(gòu)建單頁(yè)面應(yīng)用方面有著獨(dú)特的優(yōu)勢(shì);

視圖,數(shù)據(jù),結(jié)構(gòu)分離:使數(shù)據(jù)的更改更為簡(jiǎn)單,不需要進(jìn)行邏輯代碼的修改,只需要操作數(shù)據(jù)就能完成相關(guān)操作;
虛擬DOM:dom操作是非常耗費(fèi)性能的, 不再使用原生的dom操作節(jié)點(diǎn),極大解放dom操作,但具體操作的還是dom不過是換了另一種方式;
運(yùn)行速度更快:相比較與react而言,同樣是操作虛擬dom,就性能而言,vue存在很大的優(yōu)勢(shì)。

React

相同點(diǎn):
React采用特殊的JSX語(yǔ)法,Vue.js在組件開發(fā)中也推崇編寫.vue特殊文件格式,對(duì)文件內(nèi)容都有一些約定,兩者都需要編譯后使用;中心思想相同:一切都是組件,組件實(shí)例之間可以嵌套;都提供合理的鉤子函數(shù),可以讓開發(fā)者定制化地去處理需求;都不內(nèi)置列數(shù)AJAX,Route等功能到核心包,而是以插件的方式加載;在組件開發(fā)中都支持mixins的特性。

不同點(diǎn):
React采用的Virtual DOM會(huì)對(duì)渲染出來的結(jié)果做臟檢查;Vue.js在模板中提供了指令,過濾器等,可以非常方便,快捷地操作Virtual DOM。
(通俗,react沒有指令)
Angular

相同點(diǎn):
都支持指令:內(nèi)置指令和自定義指令;都支持過濾器:內(nèi)置過濾器和自定義過濾器;都支持雙向數(shù)據(jù)綁定;都不支持低端瀏覽器。

不同點(diǎn):
AngularJS的學(xué)習(xí)成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比較簡(jiǎn)單、直觀;在性能上,AngularJS依賴對(duì)數(shù)據(jù)做臟檢查,所以Watcher越多越慢;Vue.js使用基于依賴追蹤的觀察并且使用異步隊(duì)列更新,所有的數(shù)據(jù)都是獨(dú)立觸發(fā)的。

12、vue-roter的鉤子函數(shù)

vue路由鉤子大致可以分為三類

(1)全局鉤子
主要包括beforeEach和afterEach,
beforeEach函數(shù)有三個(gè)參數(shù):
to:router即將進(jìn)入的路由對(duì)象
from:當(dāng)前導(dǎo)航即將離開的路由
next:Function,進(jìn)行管道中的一個(gè)鉤子,如果執(zhí)行完了,則導(dǎo)航的狀態(tài)就是confirmed(確認(rèn)的);否則為false,終止導(dǎo)航。
afterEach函數(shù)不用傳next()函數(shù)這類鉤子主要作用于全局,一般用來判斷權(quán)限,以及頁(yè)面丟失時(shí)候需要執(zhí)行的操作,例如:


//使用鉤子函數(shù)對(duì)路由進(jìn)行權(quán)限跳轉(zhuǎn)
router.beforeEach((to, from, next) => {
    const role = localStorage.getItem('ms_username');
    if(!role && to.path !== '/login'){
        next('/login');
    }else if(to.meta.permission){
        // 如果是管理員權(quán)限則可進(jìn)入,這里只是簡(jiǎn)單的模擬管理員權(quán)限而已
        role === 'admin' ? next() : next('/403');
    }else{
        // 簡(jiǎn)單的判斷IE10及以下不進(jìn)入富文本編輯器,該組件不兼容
        if(navigator.userAgent.indexOf('MSIE') > -1 && to.path === '/editor'){
            Vue.prototype.$alert('vue-quill-editor組件不兼容IE10及以下瀏覽器,
            請(qǐng)使用更高版本的瀏覽器查看', '瀏覽器不兼容通知', {
                confirmButtonText: '確定'
            });
        }else{
            next();
        }
    }
})

(2)單個(gè)路由里面的鉤子
主要用于寫某個(gè)指定路由跳轉(zhuǎn)時(shí)需要執(zhí)行的邏輯

(3)組件路由
主要包括beforeRouteEnter和beforeRouteUpdate,beforeRouteLeave,這幾個(gè)鉤子都是寫在組件里面也可以傳三個(gè)參數(shù)(to,from,next),作用與前面類似

beforeRouteEnter(to, from, next) {
    next(vm => {
      if (
        vm.$route.meta.hasOwnProperty('auth_key') &&
        vm.$route.meta.auth_key != ''
      ) {
        if (!vm.hasPermission(vm.$route.meta.auth_key)) {
          vm.$router.replace('/admin/noPermission')
        }
      }
    })
  }

13、vuex的使用

(1)vuex是什么
Vuex 是Vue.js 的狀態(tài)管理模式,集中管理和存儲(chǔ)所有應(yīng)用組件的狀態(tài)。也是跨組件通信的一種方式,具體包括:

(2)vuex的屬性
1)state:
存放的數(shù)據(jù)狀態(tài),不可以直接修改里面的數(shù)據(jù)。
Vuex 使用單一狀態(tài)樹,即每個(gè)應(yīng)用將僅僅包含一個(gè)store 實(shí)例,但單一狀態(tài)樹和模塊化并不沖突。

2)getter:state的計(jì)算屬性,類似vue的計(jì)算屬性,主要用來過濾一些數(shù)據(jù)。

3)actions:actions可以理解為通過將mutations里面處理數(shù)據(jù)的方法變成可異步的處理數(shù)據(jù)的方法,簡(jiǎn)單的說就是異步操作數(shù)據(jù)。view 層通過 store.dispath 來分發(fā) action??梢援惒胶瘮?shù)調(diào)用

4)mutation:mutations定義的方法動(dòng)態(tài)修改Vuex 的 store 中的狀態(tài)或數(shù)據(jù)

5)modules:項(xiàng)目特別復(fù)雜的時(shí)候,可以讓每一個(gè)模塊擁有自己的state、mutation、action、getters,使得結(jié)構(gòu)非常清晰,方便管理。

(3)vuex解決了什么問題
1)多個(gè)組件依賴同一狀態(tài)時(shí),多層嵌套的組件非常繁瑣,并對(duì)兄弟組件間通信無(wú)能為力時(shí)。
2)不同組件的行為需要改變同一狀態(tài)。

(4)vuex的應(yīng)用場(chǎng)景
多個(gè)組件依賴同一狀態(tài)時(shí)
來自不同組件的行為需要變更同一狀態(tài)

(5)怎么引入vuex
1)先安裝依賴cnpm i vuex --save
2)在項(xiàng)目目錄src中建立store文件夾
3)在store文件夾下新建index.js文件,寫入

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
//不是在生產(chǎn)環(huán)境debug為true
const debug = process.env.NODE_ENV !== 'production';
//創(chuàng)建Vuex實(shí)例對(duì)象
const store = new Vuex.Store({
  strict:debug, //在不是生產(chǎn)環(huán)境下都開啟嚴(yán)格模式
  state:{},
  getters:{},
  mutations:{},
  actions:{}
})
export default store

然后再main.js文件中引入vuex,這么寫

import Vue from 'vue';
import App from './App.vue';
import store from './store';
const vm = new Vue({
    store:store,
    render: h => h(App)
}).$mount('#app')

4)vuex中狀態(tài)儲(chǔ)存在哪里,怎么改變它?
存儲(chǔ)在state中,改變vuex中的狀態(tài)唯一途徑就是提交mutation

5)vuex中狀態(tài)是對(duì)象時(shí),使用時(shí)要注意什么
因?yàn)閷?duì)象是引用類型,復(fù)制后改變屬性會(huì)影響原始數(shù)據(jù),這樣會(huì)改變state里面的狀態(tài),是不允許的,所以先用深度克隆復(fù)制對(duì)象,再修改。

6)vuex有個(gè)特點(diǎn) 刷新頁(yè)面 數(shù)據(jù)會(huì)丟失
再加個(gè)mapstate...

14、vue的filter的理解與用法

1)全局過濾器必須寫在vue實(shí)例創(chuàng)建之前

Vue.filter('testfilter', function (value,text) { // 返回處理后的值
   return value+text
   })

(2)局部寫法:在組件實(shí)例對(duì)象里掛載。

filters: {
        changemsg:(val,text)\=>{ return val + text
        }
    }

(3)使用方式:只能使用在{{}}和:v-bind中,定義時(shí)第一個(gè)參數(shù)固定為預(yù)處理的數(shù),后面的數(shù)為調(diào)用時(shí)傳入的參數(shù),調(diào)用時(shí)參數(shù)第一個(gè)對(duì)應(yīng)定義時(shí)第二個(gè)參數(shù),依次往后類推

<h3 :title="test|changemsg(1234)">{{test|changemsg(4567)}}</h3>  
//多個(gè)過濾器也可以串行使用  
<h2>{{name|filter1|filter2|filter3}}</h2>

(4)vue-cli項(xiàng)目中注冊(cè)多個(gè)全局過濾器寫法:


//1.創(chuàng)建一個(gè)單獨(dú)的文件定義并暴露函數(shù)對(duì)象
const filter1 = function (val) {
  return val + '--1'
}
const filter2 = function (val) {
  return val + '--2'
}
const filter3 = function (val) {
  return val + '--3'
}

export default {
  filter1,
  filter2,
  filter3
}

//2.導(dǎo)入main.js(在vue實(shí)例之前)
import filters from './filter/filter.js'

//3.循環(huán)注冊(cè)過濾器
Object.keys(filters).forEach(key=>{
  Vue.filter(key,filters[key])
})

15、vue的keep-alive的理解?

keep-alive 是Vue內(nèi)置的一個(gè)組件,可以使被包含的組件保留狀態(tài),或避免重新渲染。
頁(yè)面第一次進(jìn)入,鉤子的觸發(fā)順序:created-> mounted-> activated,退出時(shí)觸發(fā) deactivated ,
當(dāng)再次進(jìn)入(前進(jìn)或者后退)時(shí),只觸發(fā)activated事件掛載的方法等,
只執(zhí)行一次的放在 mounted 中;組件每次進(jìn)去執(zhí)行的方法放在 activated 中;
其有幾個(gè)屬性如下:

1)include - 字符串或正則表達(dá)式,只有名稱匹配的組件會(huì)被緩存
2)exclude - 字符串或正則表達(dá)式,任何名稱匹配的組件都不會(huì)被緩存
3)include 和 exclude 的屬性允許組件有條件地緩存。二者都可以用“,”分隔字符串、正則表達(dá)式、數(shù)組。當(dāng)使用正則或者是數(shù)組時(shí),要記得使用v-bind 。
注:匹配首先檢查組件自身的 name 選項(xiàng)
不會(huì)在函數(shù)式組件中正常工作,因?yàn)樗鼈儧]有緩存實(shí)例
當(dāng)組件在內(nèi)被切換,它的activated和deactivated這兩個(gè)生命周期鉤子函數(shù)將會(huì)被對(duì)應(yīng)執(zhí)行


<!-- 逗號(hào)分隔字符串,只有組件a與b被緩存。-->
<keep-alive include="a,b">
  <component></component>
</keep-alive>

<!-- 正則表達(dá)式 (需要使用 v-bind,符合匹配規(guī)則的都會(huì)被緩存) -->
<keep-alive :include="/a|b/">
  <component></component>
</keep-alive>

<!-- Array (需要使用 v-bind,被包含的都會(huì)被緩存) -->
<keep-alive :include="['a', 'b']">
  <component></component>
</keep-alive>

16、vue首屏白屏如何解決?
1)路由懶加載
2)vue-cli開啟打包壓縮 和后臺(tái)配合 gzip訪問
3)進(jìn)行cdn加速
4)開啟vue服務(wù)渲染模式
5)用webpack的externals屬性把不需要打包的庫(kù)文件分離出去,減少打包后文件的大小
6)在生產(chǎn)環(huán)境中刪除掉不必要的console.log

plugins: [
    new webpack.optimize.UglifyJsPlugin({ //添加-刪除console.log
      compress: {
        warnings: false,
        drop_debugger: true,
        drop_console: true
      },
      sourceMap: true
    }),

7)開啟nginx的gzip ,在nginx.conf配置文件中配置


http {  //在 http中配置如下代碼,
   gzip on;
   gzip_disable "msie6"; 
   gzip_vary on; 
   gzip_proxied any;
   gzip_comp_level 8; #壓縮級(jí)別
   gzip_buffers 16 8k;
   #gzip_http_version 1.1;
   gzip_min_length 100; #不壓縮臨界值
   gzip_types text/plain application/javascript application/x-javascript text/css
    application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
 }

8)添加loading效果,給用戶一種進(jìn)度感受

17、v-model的理解(原理)?

答:v-model用于表單數(shù)據(jù)的雙向綁定,其實(shí)它就是一個(gè)語(yǔ)法糖,這個(gè)背后就做了兩個(gè)操作:
1)v-bind綁定一個(gè)value屬性;
2)v-on指令給當(dāng)前元素綁定input事件

18、computed和watch的用法和區(qū)別?

computed
1)變量不在 data中定義,而是定義在computed中,寫法跟寫方法一樣,有返回值。函數(shù)名直接在頁(yè)面模板中渲染,不加小括號(hào) 。
2)根據(jù)傳入的變量的變化 進(jìn)行結(jié)果的更新。
3)計(jì)算屬性基于響應(yīng)式依賴進(jìn)行緩存。如其中的任意一個(gè)值未發(fā)生變化,它調(diào)用的就是上一次計(jì)算緩存的數(shù)據(jù),因此提高了程序的性能。而methods中每調(diào)用一次就會(huì)重新計(jì)算一次,為了進(jìn)行不必要的資源消耗,選擇用計(jì)算屬性。

watch

1)計(jì)算屬性的時(shí)候 初始化的時(shí)候就可以被監(jiān)聽到并且計(jì)算 但是watch是發(fā)生改變的時(shí)候才會(huì)觸發(fā)。
2)當(dāng)有一些數(shù)據(jù)需要隨著其它數(shù)據(jù)變動(dòng)而變動(dòng)時(shí),或者當(dāng)需要在數(shù)據(jù)變化時(shí)執(zhí)行異步或開銷較大的操作時(shí),使用 watch。

總結(jié):

1)計(jì)算屬性變量在computed中定義,屬性監(jiān)聽在data中定義。
2)計(jì)算屬性是聲明式的描述一個(gè)值依賴了其他值,依賴的值改變后重新計(jì)算結(jié)果更新DOM。屬性監(jiān)聽的是定義的變量,當(dāng)定義的值發(fā)生變化時(shí),執(zhí)行相對(duì)應(yīng)的函數(shù)。

18、$nextTick的使用?

答:在vue中理解修改數(shù)據(jù)后,對(duì)應(yīng)的dom需要一定的時(shí)間進(jìn)行更新,因此為了能夠準(zhǔn)確的后去更新后的dom,可以采用延遲回調(diào)的方法進(jìn)行更新dom的獲取,所以出現(xiàn)了$nextTick來進(jìn)行延遲回調(diào)。即:在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個(gè)方法,獲取更新后的 DOM。

19、data為什么是一個(gè)函數(shù)?

答:這是有JavaScript的特性所導(dǎo)致,在component中,data必須以函數(shù)的形式存在,不可以是對(duì)象。
組建中的data寫成一個(gè)函數(shù),數(shù)據(jù)以函數(shù)返回值的形式定義,這樣每次復(fù)用組件的時(shí)候,都會(huì)返回一份新的data,相當(dāng)于每個(gè)組件實(shí)例都有自己私有的數(shù)據(jù)空間,它們只負(fù)責(zé)各自維護(hù)的數(shù)據(jù),不會(huì)造成混亂。而單純的寫成對(duì)象形式,就是所有的組件實(shí)例共用了一個(gè)data,這樣改一個(gè)全都改了。

20、vue單頁(yè)面和傳統(tǒng)的多頁(yè)面區(qū)別?

單頁(yè)面應(yīng)用(SPA)

通俗一點(diǎn)說就是指只有一個(gè)主頁(yè)面的應(yīng)用,瀏覽器一開始要加載所有必須的 html, js, css。所有的頁(yè)面內(nèi)容都包含在這個(gè)所謂的主頁(yè)面中。但在寫的時(shí)候,還是會(huì)分開寫(頁(yè)面片段),然后在交互的時(shí)候由路由程序動(dòng)態(tài)載入,單頁(yè)面的頁(yè)面跳轉(zhuǎn),僅刷新局部資源。多應(yīng)用于pc端。

多頁(yè)面(MPA)

指一個(gè)應(yīng)用中有多個(gè)頁(yè)面,頁(yè)面跳轉(zhuǎn)時(shí)是整頁(yè)刷新

單頁(yè)面的優(yōu)點(diǎn):

用戶體驗(yàn)好,快,內(nèi)容的改變不需要重新加載整個(gè)頁(yè)面,基于這一點(diǎn)spa對(duì)服務(wù)器壓力較??;前后端分離;頁(yè)面效果會(huì)比較炫酷(比如切換頁(yè)面內(nèi)容時(shí)的專場(chǎng)動(dòng)畫)。

單頁(yè)面缺點(diǎn):

不利于seo;導(dǎo)航不可用,如果一定要導(dǎo)航需要自行實(shí)現(xiàn)前進(jìn)、后退。(由于是單頁(yè)面不能用瀏覽器的前進(jìn)后退功能,所以需要自己建立堆棧管理);初次加載時(shí)耗時(shí)多;頁(yè)面復(fù)雜度提高很多。

21、vue常用的修飾符?

.stop:等同于JavaScript中的event.stopPropagation(),防止事件冒泡;
.prevent:等同于JavaScript中的event.preventDefault(),防止執(zhí)行預(yù)設(shè)的行為(如果事件可取消,則取消該事件,而不停止事件的進(jìn)一步傳播);
.capture:與事件冒泡的方向相反,事件捕獲由外到內(nèi);
.self:只會(huì)觸發(fā)自己范圍內(nèi)的事件,不包含子元素;
.once:只會(huì)觸發(fā)一次。

22、vue開發(fā)遇到的問題?

1)樣式污染

答:在編寫樣式中,如果需要防止樣式的污染,可以使用兩種方式,一種是在組件的根元素上增加一個(gè)唯一的class或者id,然后在編寫組件的樣式時(shí)候在根元素對(duì)應(yīng)的class或者id下進(jìn)行編寫;另一種方式是在對(duì)應(yīng)的style上添加scoped關(guān)鍵字,不過該關(guān)鍵字對(duì)引用的框架UI無(wú)效

2)router-link在安卓上不起作用

答:不起作用的原因是因?yàn)檗D(zhuǎn)碼編譯的問題,可以使用babel來進(jìn)行處理,安裝babel polypill插件解決

3)初始化頁(yè)面出現(xiàn)閃屏亂碼的問題

答:這是因?yàn)関ue還沒有解析的情況下會(huì)容易出現(xiàn)花屏現(xiàn)象,看到類似于{{data}}的字樣,可以使用兩種方式來進(jìn)行處理,一種為:在設(shè)置index.html的根元素的元素的樣式為display:none,然后在mounted中的$nextTick函數(shù)中display:block展示;另一種方式是使用vue的內(nèi)置指令:v-cloak,并且在css中設(shè)置樣式

[v-cloak] {
display: none;
}
4)router-link上事件無(wú)效解決方法

答:使用@click.native來進(jìn)行調(diào)用原生的js事件。原因:router-link會(huì)阻止click事件,.native指直接監(jiān)聽一個(gè)原生事件。

23、vue的solt的用法?

在子組件內(nèi)使用特殊的<slot>元素就可以為這個(gè)子組件開啟一個(gè)slot(插槽),在父組件模板里,插入在子組件標(biāo)簽內(nèi)的所有內(nèi)容將替代子組件的<slot> 標(biāo)簽及它的內(nèi)容。

簡(jiǎn)單說來就是:在子組件內(nèi)部用 <slot></slot>標(biāo)簽占位,當(dāng)在父組件中使用子組件的時(shí)候,我們可以在子組件中插入內(nèi)容,而這些插入的內(nèi)容則會(huì)替換 <slot></slot>標(biāo)簽的位置。

當(dāng)然:?jiǎn)蝹€(gè)solt的時(shí)候可以不對(duì)solt進(jìn)行命名,如果存在多個(gè) 則一個(gè)可以不命名,其他必須命名,在調(diào)用的時(shí)候指定名稱的對(duì)應(yīng)替換slot,沒有指定的則直接默認(rèn)無(wú)名稱的solt

24、路由跳轉(zhuǎn)和location.href的區(qū)別?

使用location.href='/url'來跳轉(zhuǎn),簡(jiǎn)單方便,但是刷新了頁(yè)面;
使用路由方式跳轉(zhuǎn),無(wú)刷新頁(yè)面,靜態(tài)跳轉(zhuǎn);

25、為什么組件中data必須用函數(shù)返回一個(gè)對(duì)象()

對(duì)象為引用類型,當(dāng)重用組件時(shí),由于數(shù)據(jù)對(duì)象都指向同一個(gè)data對(duì)象,當(dāng)在一個(gè)組件中修改data時(shí),其他重用的組件的data會(huì)同時(shí)被修改;而使用返回對(duì)象的函數(shù),由于每次返回的都是一個(gè)新對(duì)象(Object的實(shí)例),引用地址不同,則不會(huì)出現(xiàn)這個(gè)問題。

26、組件中 data 為什么是一個(gè)函數(shù)

為什么組件中的 data 必須是一個(gè)函數(shù),然后 return 一個(gè)對(duì)象,而 new Vue 實(shí)例里,data 可以直接是一個(gè)對(duì)象?

因?yàn)榻M件是用來復(fù)用的,js里對(duì)象是引用類型,如果組件中data是一個(gè)對(duì)象,那種這樣作用域沒有隔離,子組件中的data屬性會(huì)相互影響,
如果組件中data選項(xiàng)是一個(gè)函數(shù),那么每個(gè)實(shí)例可以維護(hù)一份被返回對(duì)象的獨(dú)立的拷貝,組件實(shí)例之間的data屬性值不會(huì)互相影響;
而new Vue的實(shí)例,是不會(huì)被復(fù)用的,因此不存在引用對(duì)象問題。

27、說說你對(duì)組件插槽的理解

28、vue怎么定義全局方法

(1)掛載在Vue的prototype上

// base.js
const install = function (Vue, opts) {
    Vue.prototype.demo = function () {
        console.log('我已經(jīng)在Vue原型鏈上')
    }
}
export default {
    install
}

//main.js
//注冊(cè)全局函數(shù)
import base from 'service/base';
Vue.use(base);

(2)利用全局混入mixin
(3)用this.root.on綁定方法,用this.root.off解綁方法,用this.root.emit全局調(diào)用。

this.$root.$on('demo',function(){
    console.log('test');
})
this.$root.$emit('demo');
this.$root.$off('demo');

29、vue3.0與vue2.0對(duì)比

(1)聲明變更
(2)雙向綁定
(3)觀察屬性
(4)生命周期變更
(5)vue3.0實(shí)現(xiàn)了dom diff和vDOM的優(yōu)化
(6)響應(yīng)式原理改變
1、vue2.0使用的是defineProperty,有兩個(gè)難觸屏的問題
(1)只能做第一層屬性的響應(yīng),再往深處就無(wú)法實(shí)現(xiàn)了
(2)數(shù)組問題:defineProperty無(wú)法檢測(cè)數(shù)組的長(zhǎng)度變化,準(zhǔn)確來說,是無(wú)法檢測(cè)通過改變length的方法而增加的長(zhǎng)度無(wú)法檢測(cè)到
(3)vue3.0使用的是Proxy和Reflect,直接代碼整個(gè)對(duì)象
總結(jié):
1、Object.defineProperty只能劫持對(duì)象的屬性,而Proxy是直接代理對(duì)象,由于Object.defineProperty只能對(duì)屬性進(jìn)行劫持,需要遍歷對(duì)象的每個(gè)屬性。而Proxy可以直接代理對(duì)象。
2、Object.defineProperty對(duì)新增屬性需要手動(dòng)進(jìn)行Observe,由于defineProperty劫持的是對(duì)象的屬性,所以新增屬性時(shí),需要重新遍歷對(duì)象,對(duì)其新增屬性再使用。
Object.defineProperty進(jìn)行劫持,也是因?yàn)檫@個(gè)原因,使用vue給data中的數(shù)組或?qū)ο笮略鰧傩詴r(shí),需要使用vm.$set才能保證新增的屬性也是響應(yīng)式的。
3、Proxy支持13種攔截操作,這是defineProperty所不具有的新標(biāo)準(zhǔn)性能紅利


image.png

4、Proxy作為新標(biāo)準(zhǔn),長(zhǎng)遠(yuǎn)來看,js引擎會(huì)繼續(xù)優(yōu)化Proxy,但getter和setter基本不會(huì)再有針對(duì)性優(yōu)化。
5、Proxy兼容性差,目前并沒有一個(gè)完整支持Pxoxy所有攔截方法的Polyfill方案

30、vue中router和route的區(qū)別

1.$router是VueRouter的一個(gè)對(duì)象,通過Vue.use(VueRouter)和Vu構(gòu)造函數(shù)得到一個(gè)router的實(shí)例對(duì)象,
這個(gè)對(duì)象中是一個(gè)全局的對(duì)象,他包含了所有的路由,包含了許多關(guān)鍵的對(duì)象和屬性。

2.route是一個(gè)跳轉(zhuǎn)的路由對(duì)象,每一個(gè)路由都會(huì)有一個(gè)route對(duì)象,
是一個(gè)局部的對(duì)象,可以獲取對(duì)應(yīng)的name,path,params,query等

31、Vuex和localStorage區(qū)別

1、最重要的區(qū)別
(1)vuex存儲(chǔ)在內(nèi)存
(2)localstorage則以文件的方式存儲(chǔ)在本地
localstorage只能存儲(chǔ)字符串類型的數(shù)據(jù),存儲(chǔ)對(duì)象需要JSON的stringify和parse方法進(jìn)行處理。讀取內(nèi)存比讀取硬盤速度要快。
(3)vuex能做到數(shù)據(jù)響應(yīng)式,localstorage不能
(4)刷新頁(yè)面vuex存儲(chǔ)的值會(huì)丟失,localstorage不會(huì)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容