1、組件間怎么傳值,具體說說代碼怎樣實現(xiàn)
子傳父:子向父是通過 events(
$emit
);通過父鏈 / 子鏈也可以通信($parent
/$children
);ref 也可以訪問組件實例;provide / inject API;$attrs/$listeners
父傳子:父向子傳遞數(shù)據(jù)是通過 props,
兄弟組件傳值:bus,vuex
跨級父子通信:Bus;Vuex;provide / inject API、
$attrs/$listeners
2、Vue雙向綁定原理
采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在數(shù)據(jù)變動時發(fā)布消息給訂閱者,觸發(fā)相應的監(jiān)聽回調(diào)。
1、實現(xiàn)一個數(shù)據(jù)監(jiān)聽器Observer,能夠?qū)?shù)據(jù)對象的所有屬性進行監(jiān)聽,如有變動可拿到最新值并通知訂閱者
2、實現(xiàn)一個指令解析器Compile,對每個元素節(jié)點的指令進行掃描和解析,根據(jù)指令模板替換數(shù)據(jù),以及綁定相應的更新函數(shù)
3、實現(xiàn)一個Watcher,作為連接Observer和Compile的橋梁,能夠訂閱并收到每個屬性變動的通知,執(zhí)行指令綁定的相應回調(diào)函數(shù),從而更新視圖
3、Vue的生命周期和鉤子函數(shù)
[圖片上傳失敗...(image-87e971-1566982812354)]
beforecreate
: 舉個栗子:可以在這加個loading事件
created
:在這結(jié)束loading,還做一些初始化,實現(xiàn)函數(shù)自執(zhí)行
mounted
: 在這發(fā)起后端請求,拿回數(shù)據(jù),配合路由鉤子做一些事情
beforeDestroy
: 你確認刪除XX嗎? destroyed :當前組件已被刪除,清空相關內(nèi)容
4、應該在vue的生命周期的什么階段發(fā)出ajax請求,為什么
看實際情況,一般在 created
里面就可以,如果涉及到需要頁面加載完成之后的話就用 mounted
5、vuex是什么?怎么使用?哪種功能場景使用它?
只用來讀取的狀態(tài)集中放在store中; 改變狀態(tài)的方式是提交mutations,這是個同步的事務; 異步邏輯應該封裝在action中。
在main.js引入store,注入。新建了一個目錄store,….. export 。
場景有:單頁應用中,組件之間的狀態(tài)同步、音樂播放、登錄狀態(tài)、加入購物車
[圖片上傳失敗...(image-8e3ed4-1566982812354)]
state
Vuex 使用單一狀態(tài)樹,即每個應用將僅僅包含一個store 實例,但單一狀態(tài)樹和模塊化并不沖突。存放的數(shù)據(jù)狀態(tài),不可以直接修改里面的數(shù)據(jù)。
mutations
mutations定義的方法動態(tài)修改Vuex 的 store 中的狀態(tài)或數(shù)據(jù)。
getters
類似vue的計算屬性,主要用來過濾一些數(shù)據(jù)。
action
actions可以理解為通過將mutations里面處里數(shù)據(jù)的方法變成可異步的處理數(shù)據(jù)的方法,簡單的說就是異步操作數(shù)據(jù)。view 層通過 store.dispath 來分發(fā) action。
const store = new Vuex.Store({ //store實例
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
modules
項目特別復雜的時候,可以讓每一個模塊擁有自己的state、mutation、action、getters,使得結(jié)構(gòu)非常清晰,方便管理。
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
})
6、Vue路由守衛(wèi)
路由跳轉(zhuǎn)前做一些驗證,比如登錄驗證,是網(wǎng)站中的普遍需求。對此,vue-route 提供的 beforeRouteUpdate 可以方便地實現(xiàn)導航守衛(wèi)。
全局守衛(wèi)
你可以使用 router.beforeEach
注冊一個全局前置守衛(wèi):
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
每個守衛(wèi)方法接收三個參數(shù):
-
to: Route
: 即將要進入的目標 路由對象 -
from: Route
: 當前導航正要離開的路由 -
next: Function
: 一定要調(diào)用該方法來 resolve 這個鉤子。執(zhí)行效果依賴next
方法的調(diào)用參數(shù),確保要調(diào)用next
方法,否則鉤子就不會被 resolved
舉一個例子:
- 列舉需要判斷登錄狀態(tài)的“路由集合”,當跳轉(zhuǎn)至集合中的路由時,如果“未登錄狀態(tài)”,則跳轉(zhuǎn)到登錄頁面LoginPage;
- 當直接進入登錄頁面LoginPage時,如果“已登錄狀態(tài)”,則跳轉(zhuǎn)到首頁HomePage;
7、常用的vue指令,Vue的自定義指令怎么做
常用的vue指令有v-if、v-show,v-for,v-model等等
- 創(chuàng)建局部指令
var app = new Vue({
el: '#app',
data: {
},
// 創(chuàng)建指令(可以多個)
directives: {
// 指令名稱
drag: {
inserted(el) {
// 指令中第一個參數(shù)是當前使用指令的DOM
console.log(el);
console.log(arguments);
// 對DOM進行操作
el.style.width = '200px';
el.style.height = '200px';
el.style.background = '#000';
}
}
}
})
- 全局指令
Vue.directive('dir2', {
inserted(el) {
console.log(el);
}
})
- 指令的使用
<div id="app">
<div v-dir1></div>
<div v-dir2></div>
</div>
8、Vue登錄流程?需要做什么驗證
在前后端完全分離的情況下,Vue項目中實現(xiàn)token驗證大致思路如下:
第一次登錄的時候,前端調(diào)后端的登陸接口,發(fā)送用戶名和密碼
后端收到請求,驗證用戶名和密碼,驗證成功,就給前端返回一個token
前端拿到token,將token存儲到localStorage和vuex中,并跳轉(zhuǎn)路由頁面
前端每次跳轉(zhuǎn)路由,就判斷 localStroage 中有無 token ,沒有就跳轉(zhuǎn)到登錄頁面,有則跳轉(zhuǎn)到對應路由頁面
每次調(diào)后端接口,都要在請求頭中加token,我們常用axios的請求庫中,添加全局攔截器,將token設置在請求頭中。
后端判斷請求頭中有無token,有token,就拿到token并驗證token,驗證成功就返回數(shù)據(jù),驗證失敗(例如:token過期)就返回401,請求頭中沒有token也返回401
如果前端拿到狀態(tài)碼為401,就清除token信息并跳轉(zhuǎn)到登錄頁面
// http request 攔截器
axios.interceptors.request.use(
config => {
if (store.state.token) { // 判斷是否存在token,如果存在的話,則每個http header都加上token
config.headers.Authorization = `token ${store.state.token}`;
}
return config;
},
err => {
return Promise.reject(err);
});
// http response 攔截器
axios.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
// 返回 401 清除token信息并跳轉(zhuǎn)到登錄頁面
store.commit(types.LOGOUT);
router.replace({
path: 'login',
query: {redirect: router.currentRoute.fullPath}
})
}
}
return Promise.reject(error.response.data) // 返回接口返回的錯誤信息
});
9、講一下MVVM中的vm工作流程
MVVM 是 Model-View-ViewModel 的縮寫。
Model代表數(shù)據(jù)模型,也可以在Model中定義數(shù)據(jù)修改和操作的業(yè)務邏輯。
View 代表UI 組件,它負責將數(shù)據(jù)模型轉(zhuǎn)化成UI 展現(xiàn)出來。
ViewModel 監(jiān)聽模型數(shù)據(jù)的改變和控制視圖行為、處理用戶交互,簡單理解就是一個同步View 和 Model的對象,連接Model和View。
在MVVM架構(gòu)下,View 和 Model 之間并沒有直接的聯(lián)系,而是通過ViewModel進行交互,Model 和 ViewModel 之間的交互是雙向的, 因此View 數(shù)據(jù)的變化會同步到Model中,而Model 數(shù)據(jù)的變化也會立即反應到View 上。
ViewModel 通過雙向數(shù)據(jù)綁定把 View 層和 Model 層連接了起來,而View 和 Model 之間的同步工作完全是自動的,無需人為干涉,因此開發(fā)者只需關注業(yè)務邏輯,不需要手動操作DOM, 不需要關注數(shù)據(jù)狀態(tài)的同步問題,復雜的數(shù)據(jù)狀態(tài)維護完全由 MVVM 來統(tǒng)一管理。
10、Vue和react的區(qū)別?
react和vue都是做組件化的,整體的功能都類似,但是他們的設計思路是有很多不同的。使用react和vue,主要是理解他們的設計思路的不同
react整體是函數(shù)式的思想,把組件設計成純組件,狀態(tài)和邏輯通過參數(shù)傳入,所以在react中,是單向數(shù)據(jù)流,
而vue的思想是響應式的,也就是基于是數(shù)據(jù)可變的,通過對每一個屬性建立Watcher來監(jiān)聽,當屬性變化的時候,響應式的更新對應的虛擬dom
react的性能優(yōu)化需要手動去做,而vue的性能優(yōu)化是自動的,但是vue的響應式機制也有問題,就是當state特別多的時候,Watcher也會很多,會導致卡頓
react是類式的寫法,api很少,而vue是聲明式的寫法,通過傳入各種options,api和參數(shù)都很多
react可以通過高階組件(Higher Order Components--HOC)來擴展,而vue需要通過mixins來擴展
總結(jié):react整體的思路就是函數(shù)式,所以推崇純組件,數(shù)據(jù)不可變,單向數(shù)據(jù)流,當然需要雙向的地方也可以做到,比如結(jié)合redux-form,而vue是基于可變數(shù)據(jù)的,支持雙向綁定。react組件的擴展一般是通過高階組件,而vue組件會使用mixin。vue內(nèi)置了很多功能,而react做的很少,很多都是由社區(qū)來完成的,vue追求的是開發(fā)的簡單,而react更在乎方式是否正確。
11、Vue里面的插槽
<slot>
是組件的一塊HTML模板,父組件決定這塊模板顯不顯示以及怎么顯示。
位置由子組件自身決定(slot現(xiàn)在組件template的什么位置,父組件傳過來的模板將來就顯示在什么位置)
匿名插槽:只能有一個,可以放在組件的任何位置
<v-xx><h1></h1></v-xx>
12、Vue-cli2.0和Vue-cli3.0的區(qū)別
用vue-cli3.0版本創(chuàng)建的項目與2.0版本相比較,我們會發(fā)現(xiàn),文件目錄少了很多 eg:build、config,那么如何像vue-cli 2.* 之前關于端口號的配置、打包之后的路徑的配置、圖片的配置等,到哪里配置呢??vue-cli 3.0 可以在項目的根目錄下新建一個 vue.config.js 文件,之前繁瑣的配置都可以在這里直接配置
3.0能直接運行單個組件
3.0有一個UI管理界面
安裝了2.0版本,要先卸載
13、Vue的路由實現(xiàn) || vue-router的原理
hash模式:在瀏覽器中符號“#”,#以及#后面的字符稱之為hash,用window.location.hash讀取;
特點:hash雖然在URL中,但不被包括在HTTP請求中;用來指導瀏覽器動作,對服務端安全無用,hash不會重加載頁面。
hash 模式下,僅 hash 符號之前的內(nèi)容會被包含在請求中,如 http://www.xxx.com,因此對于后端來說,即使沒有做到對路由的全覆蓋,也不會返回 404 錯誤。
history模式:history采用HTML5的新特性;且提供了兩個新方法:pushState(),replaceState()可以對瀏覽器歷史記錄棧進行修改,以及popState事件的監(jiān)聽到狀態(tài)變更。
history 模式下,前端的 URL 必須和實際向后端發(fā)起請求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少對 /items/id 的路由處理,將返回 404 錯誤。Vue-Router 官網(wǎng)里如此描述:“不過這種模式要玩好,還需要后臺配置支持……所以呢,你要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。”
14、vue路由的鉤子函數(shù)
首頁可以控制導航跳轉(zhuǎn),beforeEach,afterEach等,一般用于頁面title的修改。一些需要登錄才能調(diào)整頁面的重定向功能。
beforeEach主要有3個參數(shù)to,from,next:
to:route即將進入的目標路由對象,
from:route當前導航正要離開的路由
next:function一定要調(diào)用該方法resolve這個鉤子。執(zhí)行效果依賴next方法的調(diào)用參數(shù)。可以控制網(wǎng)頁的跳轉(zhuǎn)。
15、對keep-alive 的了解
<keep-alive>
是Vue的內(nèi)置組件,能在組件切換過程中將狀態(tài)保留在內(nèi)存中,防止重復渲染DOM。
<keep-alive>
包裹動態(tài)組件時,會緩存不活動的組件實例,而不是銷毀它們。
<keep-alive>
與 <transition>
相似,只是一個抽象組件,它不會在DOM樹中渲染(真實或者虛擬都不會),也不在父組件鏈中存在,比如:你永遠在 this.$parent
中找不到 keep-alive
。
keep-alive生命周期鉤子函數(shù):activated、deactivated
使用<keep-alive>
會將數(shù)據(jù)保留在內(nèi)存中,如果要在每次進入頁面的時候獲取最新的數(shù)據(jù),需要在activated
階段獲取數(shù)據(jù),承擔原來created鉤子中獲取數(shù)據(jù)的任務。
被包含在 <keep-alive>
中創(chuàng)建的組件,會多出兩個生命周期的鉤子: activated
與 deactivated
activated:在組件被激活時調(diào)用,在組件第一次渲染時也會被調(diào)用,之后每次keep-alive激活時被調(diào)用。
deactivated:在組件被停用時調(diào)用。
注意:只有組件被 keep-alive
包裹時,這兩個生命周期才會被調(diào)用,如果作為正常組件使用,是不會被調(diào)用,以及在 2.1.0
版本之后,使用 exclude
排除之后,就算被包裹在 keep-alive
中,這兩個鉤子依然不會被調(diào)用!另外在服務端渲染時此鉤子也不會被調(diào)用的。
什么時候獲取數(shù)據(jù)?
當引入keep-alive
的時候,頁面第一次進入,鉤子的觸發(fā)順序created-> mounted-> activated,退出時觸發(fā)deactivated。當再次進入(前進或者后退)時,只觸發(fā)activated。
16、DOM 和虛擬DOM的區(qū)別 以及你對于他們了解
DOM的本質(zhì):DOM是瀏覽器概念,瀏覽器從服務器端讀取html頁面,瀏覽器將html解析成一棵元素嵌套關系的dom樹,用對象來表示頁面上的元素,并提供操作dom對象的api。
虛擬DOM:框架概念,程序員用js對象來模擬頁面上dom元素的嵌套關系( 本質(zhì) ),為了實現(xiàn)頁面元素的高效更新( 目的 )
虛擬DOM是真實DOM結(jié)構(gòu)的映射,即一個數(shù)據(jù)集合
// 對于這個Html 文件
<div class="">
<p>
<span>
Hello, the world!
</span>
<span>
Hello, the code!
</span>
</p>
</div>
// 它對應的虛擬DOM就是
let nodesData = {
tag: 'div',
attr: []
children: [
{
tag: 'p',
children: [
{
tag: 'span',
children: [
{
tag: '#text',
text: 'Hello, the world!'
}
]
}
]
},
{
tag: 'span',
children: [
{
tag: '#text',
text: 'Hello, the code!'
}
]
}
]
}
// 或這種寫法
let vNodes = v('div', [
v('p', [
v('span', [ v('#text', 'Hello, the world!') ] )
]
),
v('span', [
v('#text', 'Hello, the code!')
])
]
)
虛擬DOM的核心就是一個diff算法:使用一個render()方法就可以將上面vNodes還原成真實的Html頁面
17、vue指令的生命周期
自定義指令有五個生命周期(也叫鉤子函數(shù)),分別是 bind,inserted,update,componentUpdated,unbind
- bind:只調(diào)用一次,指令第一次綁定到元素時調(diào)用,用這個鉤子函數(shù)可以定義一個綁定時執(zhí)行一次的初始化動作。
- inserted:被綁定元素插入父節(jié)點時調(diào)用(父節(jié)點存在即可調(diào)用,不必存在于document中)。
- update:被綁定于元素所在的模板更新時調(diào)用,而無論綁定值是否變化。通過比較更新前后的綁定值,可以忽略不必要的模板更新。
- componentUpdated:被綁定元素所在模板完成一次更新周期時調(diào)用。
- unbind:只調(diào)用一次,指令與元素解綁時調(diào)用。
18、vue封裝公共組件(通用組件)需要考慮到什么
開發(fā)通用組件是很基礎且重要的工作,通用組件必須具備高性能、低耦合的特性
一、數(shù)據(jù)從父組件傳入
為了解耦,子組件本身就不能生成數(shù)據(jù)。即使生成了,也只能在組件內(nèi)部運作,不能傳遞出去。
父對子傳參,就需要用到 props,但是通用組件的的應用場景比較復雜,對 props 傳遞的參數(shù)應該添加一些驗證規(guī)則
二、在父組件處理事件
在通用組件中,通常會需要有各種事件,
比如復選框的 change 事件,或者組件中某個按鈕的 click 事件
這些事件的處理方法應當盡量放到父組件中,通用組件本身只作為一個中轉(zhuǎn)
三、記得留一個 slot
一個通用組件,往往不能夠完美的適應所有應用場景
所以在封裝組件的時候,只需要完成組件 80% 的功能,剩下的 20% 讓父組件通過 solt 解決
四、不要依賴 Vuex
父子組件之間是通過 props 和 自定義事件 來傳參,非父子組件通常會采用 Vuex 傳參
但是 Vuex 的設計初衷是用來管理組件狀態(tài),雖然可以用來傳參,但并不推薦
因為 Vuex 類似于一個全局變量,會一直占用內(nèi)存
在寫入數(shù)據(jù)龐大的 state 的時候,就會產(chǎn)生內(nèi)存泄露
五、合理運用 scoped 編寫 CSS
在編寫組件的時候,可以在 <style> 標簽中添加 scoped,讓標簽中的樣式只對當前組件生效
但是一味的使用 scoped,肯定會產(chǎn)生大量的重復代碼
所以在開發(fā)的時候,應該避免在組件中寫樣式
當全局樣式寫好之后,再針對每個組件,通過 scoped 屬性添加組件樣式
19、父組件怎么調(diào)用子組件里的方法
在父組件中:首先要引入子組件 import Child from './child';
<child ref="mychild"></child>是在父組件中為子組件添加一個占位,ref="mychild"是子組件在父組件中的名字
父組件中 components: { 是聲明子組件在父組件中的名字}
在父組件的方法中調(diào)用子組件的方法,很重要 this.$refs.mychild.parentHandleclick("嘿嘿嘿"); parentHandleclick是子組件中的方法
20、css只在當前組件起作用
答:在style標簽中寫入scoped即可 例如:<style scoped></style>
21、v-if 和 v-show 區(qū)別
答:v-if按照條件是否渲染,v-show是display的block或none;
22、
router的區(qū)別
答:router是“路由實例”對象包括了路由的跳轉(zhuǎn)方法,鉤子函數(shù)等。
23、vue.js的兩個核心是什么?
答:數(shù)據(jù)驅(qū)動、組件系統(tǒng)
24、vue常用的修飾符?
答:.prevent: 提交事件不再重載頁面;.stop: 阻止單擊事件冒泡;.self: 當事件發(fā)生在該元素本身而不是子元素的時候會觸發(fā);.capture: 事件偵聽,事件發(fā)生的時候會調(diào)用
25、v-on 可以綁定多個方法嗎?
答:可以
26、vue中 key 值的作用?
答:當 Vue.js 用 v-for 正在更新已渲染過的元素列表時,它默認用“就地復用”策略。如果數(shù)據(jù)項的順序被改變,Vue 將不會移動 DOM 元素來匹配數(shù)據(jù)項的順序, 而是簡單復用此處每個元素,并且確保它在特定索引下顯示已被渲染過的每個元素。key的作用主要是為了高效的更新虛擬DOM。
27、什么是vue的計算屬性?
答:在模板中放入太多的邏輯會讓模板過重且難以維護,在需要對數(shù)據(jù)進行復雜處理,且可能多次使用的情況下,盡量采取計算屬性的方式。好處:①使得數(shù)據(jù)處理結(jié)構(gòu)清晰;②依賴于數(shù)據(jù),數(shù)據(jù)更新,處理結(jié)果自動更新;③計算屬性內(nèi)部this指向vm實例;④在template調(diào)用時,直接寫計算屬性名即可;⑤常用的是getter方法,獲取數(shù)據(jù),也可以使用set方法改變數(shù)據(jù);⑥相較于methods,不管依賴的數(shù)據(jù)變不變,methods都會重新計算,但是依賴數(shù)據(jù)不變的時候computed從緩存中獲取,不會重新計算。
計算屬性就是當其依賴屬性的值發(fā)生變化時,這個屬性的值會自動更新。
<body>
<div id="app">
<input type="text" v-model="msg">
<p>原始字符:{{msg}}</p>
<p>計算屬性翻轉(zhuǎn)字符:{{reverseMsg}}</p>
</div>
<script>
new Vue({
el:'#app',
data:{
msg:'Hello'
},
//vue的計算屬性
computed:{
reverseMsg(){
//返回翻轉(zhuǎn)后的字符串,當msg變化后reverseMsg會跟著變化
return this.msg.split('').reverse().join('')
}
}
})
</script>
</body>
28、vue等單頁面應用及其優(yōu)缺點
答:優(yōu)點:Vue 的目標是通過盡可能簡單的 API 實現(xiàn)響應的數(shù)據(jù)綁定和組合的視圖組件,核心是一個響應的數(shù)據(jù)綁定系統(tǒng)。MVVM、數(shù)據(jù)驅(qū)動、組件化、輕量、簡潔、高效、快速、模塊友好。
缺點:不支持低版本的瀏覽器,最低只支持到IE9;不利于SEO的優(yōu)化(如果要支持SEO,建議通過服務端來進行渲染組件);第一次加載首頁耗時相對長一些;不可以使用瀏覽器的導航按鈕需要自行實現(xiàn)前進、后退。
29、路由之間跳轉(zhuǎn)
聲明式(標簽跳轉(zhuǎn)) 編程式( js跳轉(zhuǎn))
通過router-link實現(xiàn)跳轉(zhuǎn)
通過js的編程的方式
30、Vue中怎么實現(xiàn)跨域
使用http-proxy-middleware 代理解決(項目使用vue-cli腳手架搭建)
例如請求的url:“http://aa.com/demo.json“
1、打開config/index.js,在proxyTable中添寫如下代碼:
proxyTable: {
'/api': { //使用"/api"來代替"http://aa.com"
target: 'http://aa.com', //源地址
changeOrigin: true, //改變源
secure:false // 是否使用https
pathRewrite: {
'^/api': '/api' //路徑重寫
}
}
}
2、使用axios請求數(shù)據(jù)時直接使用“/api”
getData () {
axios.get('/api/demo.json', function (res) {
console.log(res)
})
以上配置只是在開發(fā)環(huán)境(dev)中解決跨域。要解決生產(chǎn)環(huán)境的跨域問題,則在config/dev.env.js
和config/prod.env.js
里也就是開發(fā)/生產(chǎn)環(huán)境下分別配置一下請求的地址API_HOST
,開發(fā)環(huán)境中我們用上面配置的代理地址api,生產(chǎn)環(huán)境下用正常的接口地址
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
API_HOST:"/api/"
})
'use strict'
module.exports = {
NODE_ENV: '"production"',
API_HOST:"http://aa.com"
}
31、Vue首屏加載過慢的解決方法有哪些
vue首屏加載過慢的原因
- 網(wǎng)速慢肯定會導致首屏加載過慢,但是在這里我們不做討論
- vue項目作為一個單頁面應用,如果不對路由進行處理,在加載首頁的時候,就會將所有組件全部加載,并向服務器請求數(shù)據(jù),這必將拖慢加載速度;
- 通過查看Network,發(fā)現(xiàn)整個網(wǎng)站加載試講長達10幾秒,加載時間最長的就是js、css文件和媒體文件及圖片
解決方案
vue-router 路由懶加載
在項目開發(fā)中,我們會用到很多第三方庫,如果可以按需引入,我們可以只引入自己需要的組件,來減少所占空間,但也會有一些不能按需引入,我們可以采用CDN外部加載,在index.html中從CDN引入組件,去掉其他頁面的組件import,
關閉sourcemap,sourcemap是為了方便線上調(diào)試用的,因為線上代碼都是壓縮過的,導致調(diào)試極為不便,而有了sourcemap,就等于加了個索引字典,出了問題可以定位到源代碼的位置。
但是,這個玩意是每個js都帶一個sourcemap,有時sourcemap會很大,拖累了整個項目加載速度,為了節(jié)省加載時間,我們將其關閉掉開啟gzip壓縮,這個優(yōu)化是兩方面的,前端將文件打包成.gz文件,然后通過nginx的配置,讓瀏覽器直接解析.gz文件。
加個loading效果:首頁加個好看的loading阻塞一下,讓用戶別等的那么心焦。
如果首頁真的有瓶頸,可以考慮用node單獨做服務端渲染,而下面的子頁面仍用spa單頁的方式交互。
32、vue如何實現(xiàn)按需加載組件
https://www.cnblogs.com/-roc/p/9983177.html
33、 請說下封裝 vue 插件封裝過程
https://www.jb51.net/article/157120.htm
34、vue項目的多語言處理
Vue已經(jīng)有了這個多語種的插件,vue-i18n
35、vue中的watch介紹和場景
監(jiān)聽并處理data屬性的更新,對data屬性的監(jiān)聽,說明屬性是在data中聲明過的
屬性更新時調(diào)用監(jiān)聽函數(shù),可選參數(shù)分別為新值和舊值,對屬性重新設置值,只要跟原來的值相等就不會觸發(fā)函數(shù)調(diào)用,這一點跟計算屬性是相似的,
// 基礎用法
watch: {
activeTab(newValue, oldValue) {
console.log(newValue, oldValue);
this.getList();
}
}
// 函數(shù)體調(diào)用Vue實例的方法可簡寫
watch: {
activeTab: 'getList'
}
屬性初始化的值默認不會觸發(fā)監(jiān)聽,解決辦法添加說明immediate:true,表示監(jiān)聽初始值,此時使用handler寫法
watch: {
activeTab: {
handler(newValue, oldValue) {
console.log(newValue, oldValue);
this.getList();
},
// 立即執(zhí)行handler函數(shù)
immediate: true
}
}
當被監(jiān)聽的屬性為對象時,默認不會監(jiān)聽對象內(nèi)部屬性的變化,而是只監(jiān)聽屬性被賦值時的變化,解決辦法添加說明deep:true(默認為false),此時監(jiān)聽器會深度遍歷給對象的每一個屬性都帶上監(jiān)聽器,更新寫法
// 監(jiān)聽對象的所有屬性
watch: {
activeTab: {
handler(newValue, oldValue) {
console.log(newValue, oldValue);
this.getList();
},
// 深度監(jiān)聽
deep: true
}
}
// 監(jiān)聽對象的某些屬性
watch: {
'activeTab.index': {
handler(newValue, oldValue) {
console.log(newValue, oldValue);
this.getList();
}
}
}
另外組件中的監(jiān)聽器會隨組建的注銷而注銷,不會造成內(nèi)存溢出,但如果使用命令式的( vm.$watch)全局的監(jiān)聽器需要手動注銷才行