日常知識(shí)點(diǎn)總結(jié)(vue篇):
1古程、vue的生命周期:
Vue實(shí)例從開(kāi)始創(chuàng)建,初始化數(shù)據(jù)喊崖,編譯模板挣磨,掛載Dom->渲染雇逞,更新->渲染,卸載等一系列過(guò)程茁裙,我們稱(chēng)這是Vue的生命周期塘砸。
作用:生命周期中有多個(gè)事件鉤子,讓我們?cè)诳刂普麄€(gè)Vue實(shí)例的過(guò)程時(shí)更容易形成好的邏輯晤锥。
1)beforeCreate( ) ;
實(shí)例創(chuàng)建前,這個(gè)階段實(shí)例的data,method是讀不到的
2)created( );
實(shí)例創(chuàng)建后,這個(gè)階段已經(jīng)完成了數(shù)據(jù)觀測(cè)(data? observer)谣蠢,屬性和方法的運(yùn)算,watch/event事件回調(diào).mount掛載階段還沒(méi)開(kāi)始,$el屬性目前不可見(jiàn),數(shù)據(jù)并沒(méi)有在Dom元素上進(jìn)行渲染.
3)beforeMount( );
在掛載開(kāi)始之前被調(diào)用,相關(guān)的render函數(shù)首次被調(diào)用.
4)mounted( );
el選項(xiàng)的Dom節(jié)點(diǎn)被新創(chuàng)建的vm.$el替換,并掛載到實(shí)例上去之后調(diào)用此生命周期函數(shù).此時(shí)實(shí)例的數(shù)據(jù)在Dom節(jié)點(diǎn)上進(jìn)行渲染.
5)beforeUpdate( );
數(shù)據(jù)更新時(shí)調(diào)用,但不進(jìn)行Dom重新渲染,在數(shù)據(jù)更新時(shí)Dom沒(méi)渲染前可以在這個(gè)生命函數(shù)里進(jìn)行狀態(tài)處理
6)updated( );
這個(gè)狀態(tài)下數(shù)據(jù)更新并且Dom重新渲染,當(dāng)這個(gè)生命周期函數(shù)被調(diào)用時(shí),組件Dom已經(jīng)更新,所以你現(xiàn)在可以執(zhí)行依賴(lài)于Dom的操作.當(dāng)實(shí)例每次進(jìn)行數(shù)據(jù)更新時(shí)updated都會(huì)執(zhí)行.
7)beforeDestory( );
銷(xiāo)毀前執(zhí)行(實(shí)例仍然完全可用)查近∶减猓可以做一個(gè)確認(rèn)停止事件的確認(rèn)框。
8)destoryed( );
Vue實(shí)例銷(xiāo)毀后調(diào)用.調(diào)用后,vue實(shí)例指示的所有東西都會(huì)解綁定,所有的事件監(jiān)聽(tīng)器會(huì)被移除,所有的子實(shí)例也會(huì)被銷(xiāo)毀.
Vue每個(gè)生命周期階段可以做的事:
created:實(shí)例已經(jīng)創(chuàng)建完成霜威,因?yàn)樗亲钤缬|發(fā)的原因可以進(jìn)行一些數(shù)據(jù)谈喳,資源的請(qǐng)求。
mounted:實(shí)例已經(jīng)掛載完成戈泼,可以進(jìn)行一些Dom操作婿禽。
beforeUpdate:可以在這個(gè)鉤子中進(jìn)一步的更改狀態(tài),這不會(huì)觸發(fā)附加的重渲染過(guò)程大猛。
updated:可以執(zhí)行依賴(lài)于Dom的操作扭倾。然而在大多數(shù)情況下,你應(yīng)該避免在此期間更改狀態(tài)挽绩,因?yàn)檫@可能會(huì)導(dǎo)致更新無(wú)線(xiàn)循環(huán)膛壹。該鉤子在服務(wù)端渲染期間不被調(diào)用。
beforeDestory:可以執(zhí)行一些優(yōu)化操作唉堪,清空定時(shí)器模聋,解除綁定事件。
nextTick:針對(duì)單一事件更新數(shù)據(jù)后立即操作dom
watch: 監(jiān)聽(tīng)具體數(shù)據(jù)變化,并做相應(yīng)的處理
2唠亚、vue響應(yīng)式原理:
當(dāng)一個(gè)vue實(shí)例創(chuàng)建時(shí)链方,vue會(huì)遍歷data選項(xiàng)的屬性,用Object.defineProperty將它們轉(zhuǎn)為getter/setter并且在內(nèi)部追蹤相關(guān)依賴(lài)灶搜,在屬性被訪(fǎng)問(wèn)和修改時(shí)通知變化祟蚀。每個(gè)組件實(shí)例內(nèi)部都有相應(yīng)的watcher程序?qū)嵗鼤?huì)在組件渲染的過(guò)程中把屬性記錄為依賴(lài)割卖,之后當(dāng)依賴(lài)項(xiàng)的setter被調(diào)用時(shí)前酿,會(huì)通知watcher重新計(jì)算,從而致使它關(guān)聯(lián)的組件得以更新究珊。
3薪者、vue雙向數(shù)據(jù)綁定原理:
vue.js是采用數(shù)據(jù)劫持結(jié)合“發(fā)布者---訂閱者”模式的方式,通過(guò)Object.defineProperty( )來(lái)劫持各個(gè)屬性的setter剿涮、getter言津,在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者攻人,觸發(fā)相應(yīng)的監(jiān)聽(tīng)回調(diào)。
具體步驟:
1)需要observe的數(shù)據(jù)對(duì)象進(jìn)行遞歸遍歷悬槽,包括子屬性對(duì)象的屬性怀吻,都加上setter和getter這樣的話(huà),給這個(gè)對(duì)象的某個(gè)值賦值初婆,就會(huì)觸發(fā)setter蓬坡,那么就能監(jiān)聽(tīng)到數(shù)據(jù)變化。
2)compile解析模板指令磅叛,將模板中的變量替換成數(shù)據(jù)屑咳,然后初始化 渲染頁(yè)面視圖,并將每個(gè)指令對(duì)應(yīng)的節(jié)點(diǎn)綁定更新函數(shù)弊琴,添加監(jiān)聽(tīng)數(shù)據(jù)的訂閱者兆龙,一旦數(shù)據(jù)有變動(dòng),收到通知敲董,更新視圖紫皇。
3)Watcher訂閱者是Observer和Compile之間通信的橋梁,主要做的事情是:在自身實(shí)例化時(shí)往屬性訂閱器(dep)里面添加自己腋寨,自身必須有一個(gè)update( )方法聪铺,待屬性變動(dòng)dep.notice( )通知時(shí),能調(diào)用自身的update( )方法萄窜,并觸發(fā)Compile中綁定的回調(diào)铃剔,則功成身退。
4)MVVM作為數(shù)據(jù)綁定的入口脂倦,整合Observe番宁,Compile和Watcher三者,通過(guò)Observe來(lái)監(jiān)聽(tīng)自己的model數(shù)據(jù)變化赖阻,通過(guò)Compile來(lái)解析編譯模板指令,最終利用Watcher搭起Observe和Compile之間的通信橋梁踱蠢,達(dá)到數(shù)據(jù)變化-->視圖更新火欧;視圖交互變化(input)-->數(shù)據(jù)model變更的雙向綁定效果。
4茎截、vue的組件通信:
1)父子間通信苇侵,父 -> 子通過(guò)props,子 -> 父$on企锌,$emit(發(fā)布-訂閱)
2)獲取父子組件實(shí)例的方式$parent榆浓,$children
3)在父組件中提供數(shù)據(jù)子組件進(jìn)行消費(fèi) Provide,inject(寫(xiě)插件用較多)
provide( ) { someval:'來(lái)自低級(jí)組件的數(shù)據(jù)'}
inject:['somaval']
4)Ref獲取實(shí)例的方式調(diào)用組件的屬性或者方法
5)Event? Bus? 實(shí)現(xiàn)跨組件通信
非父子組件/兄弟組件之間的數(shù)據(jù)傳遞:
/*新建一個(gè)Vue實(shí)例作為中央事件*/
let event = new Vue();
/*監(jiān)聽(tīng)事件 */
event.$on('eventName',(val) => {
? //.......do? something
})
/*觸發(fā)事件 */
event.$emit('eventName','這是一條消息撕攒。')
6)vuex:狀態(tài)管理實(shí)現(xiàn)通信陡鹃。服務(wù)器設(shè)置session服務(wù)器返回給客戶(hù)端的信息在響應(yīng)頭中帶著set-cookie='connect.sid'客戶(hù)端會(huì)把信息種植到本地的cookie中httponly客戶(hù)端再次向服務(wù)器發(fā)送請(qǐng)求的時(shí)候烘浦,會(huì)默認(rèn)在請(qǐng)求頭中cookie把connect.sid傳遞發(fā)給服務(wù)器
5、Vuex是什么:
定義:Vuex是專(zhuān)門(mén)為vue.js應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式萍鲸。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài)闷叉。
狀態(tài)自管理應(yīng)用包含以下幾個(gè)部分:
State,是 Vuex 這一狀態(tài)管理工具的唯一的數(shù)據(jù)源脊阴,所有的數(shù)據(jù)都儲(chǔ)存在里面握侧。
Getter,對(duì)數(shù)據(jù)獲取之前的再次編譯嘿期,可以理解為state的計(jì)算屬性品擎,
在組件中使用$store.getters.fun( )。
Mutation 备徐,是同步更新數(shù)據(jù)(內(nèi)部會(huì)進(jìn)行是否為異步方式更新數(shù)據(jù)的檢測(cè))孽查。$watch嚴(yán)格模式下會(huì)報(bào)錯(cuò)
在組件中使用$store.commit(" ",params)。
Action坦喘,異步操作盲再,可以獲取數(shù)據(jù)后調(diào)用mutation提交最終數(shù)據(jù)
在組件中使用$store.dispath(" ")。
Module瓣铣,當(dāng)應(yīng)用非常復(fù)雜時(shí)答朋,可以把整個(gè)store拆分成幾個(gè)模塊(module),每個(gè)module中都可以含有各自的state,getter棠笑,mutation梦碗,action
vuex的使用:
1)在src目錄下創(chuàng)建vuex文件夾,并在文件夾下創(chuàng)建一個(gè)store.js文件蓖救。
2)下載洪规,并引入vuex。
3)在store.js文件中循捺,引入vuex并且使用vuex斩例。
4)在main.js中引入store并Vue.use(Vuex)。
使用場(chǎng)景:?jiǎn)雾?yè)應(yīng)用中从橘,組件之間的狀態(tài)磁餐。音樂(lè)播放休傍,登錄管理,加入購(gòu)物車(chē)。
6嗤谚、vue-loader是什么舆床,什么用途:
vue-loader是基于webpack的一個(gè)loader(加載器)缕粹,解析和轉(zhuǎn)換.vue文件登夫,提取出其中的邏輯代碼script,樣式代碼style,以及HTML模板template董栽,再分別把它們交給對(duì)應(yīng)的loader去處理码倦,核心的作用,就是提取裆泳,劃重點(diǎn)叹洲。
webpack的loader,其實(shí)就是用來(lái)打包工禾,轉(zhuǎn)譯js或者css文件运提,簡(jiǎn)單的說(shuō)就是把寫(xiě)的代碼轉(zhuǎn)換成瀏覽器能識(shí)別的,還有一些打包闻葵,壓縮的功能等民泵。
vue-loader的作用:
1)允許為Vue組件的每個(gè)部分使用其它的webpack loader,例如在<style>的部分使用Sass和在<template>的部分使用Pug
2)允許在一個(gè).vue文件中使用自定義塊槽畔,并對(duì)其運(yùn)用系定義的loader鏈
3)使用webpack loader將<style><template>中引入的資源當(dāng)作模塊依賴(lài)來(lái)處理
4)為每個(gè)組件模擬出scoped CSS
5)在開(kāi)發(fā)過(guò)程中使用熱重載來(lái)保持狀態(tài)
7栈妆、vue-router的路由模式:
vue-router中默認(rèn)使用的時(shí)hash模式,也就是URL中帶有#號(hào)厢钧,使用mode:"history"修改為history模式鳞尔。
實(shí)際上存在三種模式:
Hash: 使用URL的hash值來(lái)作為路由。支持所有瀏覽器早直。
History: 以來(lái)HTML5 History API 和服務(wù)器配置寥假。參考官網(wǎng)中HTML5 History模式
Abstract: 支持所有javascript運(yùn)行模式。如果發(fā)現(xiàn)沒(méi)有瀏覽器的API霞扬,路由會(huì)自動(dòng)強(qiáng)制進(jìn)入這個(gè)模式糕韧。
hash模式:
背后的原理時(shí)onhashchange事件。因?yàn)閔ash發(fā)生變化的url都會(huì)被瀏覽器記錄下來(lái)喻圃,因此瀏覽器的前進(jìn)后退都可以用的萤彩。盡管瀏覽器沒(méi)有請(qǐng)求服務(wù)器,但是頁(yè)面狀態(tài)和url----關(guān)聯(lián)起來(lái)斧拍,被稱(chēng)為前端路由雀扶。
history路由:
historyAPI分為兩大部分:切換(history.go()? /history.back()? /history.forward() ),
修改歷史狀態(tài)(pushState( stateObj,title,url) / replaceState(stateObj,title,url))
8、$router與$route的區(qū)別
$router饮焦,是路由實(shí)例對(duì)象怕吴。為VueRouter實(shí)例,想要跳轉(zhuǎn)導(dǎo)航到不同URL县踢,則使用$router.push( )方法,傳入?yún)?shù)為字符串/對(duì)象伟件。
$route硼啤,是路由信息對(duì)象。為當(dāng)前router跳轉(zhuǎn)對(duì)象里面可以獲取name, path, query, params等斧账。
params 和query 的傳參及使用:
1) 使用query傳參的時(shí)候,name,path都可以引入,但使用params傳參的時(shí)候只能使用name進(jìn)行引入.
2) 接收參數(shù)的時(shí)候使用this.$route.params.name或者this.$route.query.name
3) 進(jìn)行路由跳轉(zhuǎn)的時(shí)候,我們使用this.$router.push('路徑')
4) 如果index.js配置路由時(shí),我們能看到,params的參數(shù)是URL不可或缺的一部分,但是query的參數(shù)是拼起來(lái)的,沒(méi)有也不影響.
9谴返、用vue-cli初始化一個(gè)vue項(xiàng)目里的各個(gè)文件都是什么作用(從上到下依次說(shuō)明):
node_modules:項(xiàng)目依賴(lài)的第三方node包
public:
src:放的是整個(gè)項(xiàng)目的源代碼
1)main.js:是整個(gè)項(xiàng)目的入口文件
2)APP.vue:項(xiàng)目最開(kāi)始的根組件
3)router:項(xiàng)目所有路由都放在router下的index.js文件里
4)store:
5)views:
6)components:放的是項(xiàng)目中用到的小組件
7)assets:項(xiàng)目里要用到的圖片資源
8)config:項(xiàng)目里的配置文件煞肾,基礎(chǔ)配置在index.js里,開(kāi)發(fā)環(huán)境的配置在dev.env.js
9)build.js:項(xiàng)目打包的webpack配置內(nèi)容
editorconfig:配置編輯器里的語(yǔ)法嗓袱,里面可以自定義內(nèi)容籍救,可統(tǒng)一編輯器自動(dòng)格式化代碼。
eslintrc.js:代碼的規(guī)范渠抹,看代碼是否標(biāo)準(zhǔn)
gitignore:使用git希望把代碼放到線(xiàn)上蝙昙,但是一些特殊的文件并不想或者不需要傳到線(xiàn)上,就可以把它配置到gitgnore文件里梧却,當(dāng)提交到git倉(cāng)庫(kù)文件時(shí)奇颠,這里的文件就不會(huì)被提交到git線(xiàn)上倉(cāng)庫(kù);
babel.config.js:語(yǔ)法解析器
package-lock.json:package的鎖文件放航,確定安裝的第三方包版本烈拒,為了統(tǒng)一團(tuán)隊(duì)的編碼;
package.json:這是一個(gè)依賴(lài)包广鳍,也就是第三方模塊依賴(lài)存放處荆几;
README.md:項(xiàng)目說(shuō)明文件
10、v-show和v-if指令的共同點(diǎn)和不同點(diǎn):
v-show指令是通過(guò)修改元素的display的CSS屬性讓其顯示或者隱藏
v-if 指令是直接銷(xiāo)毀和重建DOM達(dá)到讓元素顯示和隱藏的效果
使用v-show會(huì)更加節(jié)省性能上的開(kāi)銷(xiāo)赊时;當(dāng)只需要一次顯示或隱藏時(shí)吨铸,使用v-if更加合理。
v-for與v-if不同在同一層級(jí)蛋叼,在使用時(shí)焊傅,v-for的優(yōu)先級(jí)比v-if高,會(huì)先循環(huán)狈涮,然后給每一個(gè)循環(huán)后的節(jié)點(diǎn)狐胎,添加v-if。
11歌馍、NextTick是做什么的
$nextTick是在下次DOM更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)握巢,在修改數(shù)據(jù)之后使用$nextTick,則可以在回調(diào)中獲取更新后的DOM松却。
12暴浦、對(duì)比jQuery, Vue有什么不同
jQuery專(zhuān)注視圖層晓锻,通過(guò)操作DOM去實(shí)現(xiàn)頁(yè)面的一些邏輯渲染歌焦;
Vue專(zhuān)注于數(shù)據(jù)層,通過(guò)數(shù)據(jù)的雙向綁定砚哆,最終表現(xiàn)在DOM層面独撇,減少DOM操作;
Vue使用了組件化思想,使得項(xiàng)目子集職責(zé)清晰纷铣,提高了開(kāi)發(fā)效率卵史,方便重復(fù)利用,便于協(xié)同開(kāi)發(fā)搜立。
12以躯、Vue中computed和watch的區(qū)別:
computed(計(jì)算屬性):
1)不支持異步,當(dāng)computed內(nèi)有異步操作時(shí)無(wú)效啄踊,無(wú)法監(jiān)聽(tīng)數(shù)據(jù)的變化忧设。
2)簡(jiǎn)化template里面{{ }}計(jì)算和處理props或$emit的傳值。
3)具有緩存性社痛,頁(yè)面重新渲染值不變化见转,計(jì)算屬性會(huì)立即返回之前的計(jì)算結(jié)果,而不必再次執(zhí)行函數(shù)蒜哀。
watch(偵聽(tīng)屬性):
1)watch支持異步斩箫,監(jiān)聽(tīng)props, $emit或本組件的值執(zhí)行異步操作。
2)監(jiān)聽(tīng)數(shù)據(jù)必須是data中聲明過(guò)或者父組件傳遞過(guò)來(lái)的props中的數(shù)據(jù)撵儿,當(dāng)數(shù)據(jù)變化時(shí)乘客,觸發(fā)其他操作。監(jiān)聽(tīng)的函數(shù)接收兩個(gè)參數(shù)淀歇,第一個(gè)參數(shù)是最新的值易核,第二個(gè)參數(shù)是輸入之前的值。
3)不支持緩存浪默,數(shù)據(jù)變牡直,直接會(huì)觸發(fā)相應(yīng)的操作。
13纳决、 計(jì)算屬性 computed 和事件 methods 有什么區(qū)別
將同一函數(shù)定義為一個(gè) method 或者一個(gè)計(jì)算屬性碰逸。對(duì)于最終的結(jié)果,兩種方式是相同的阔加。
不同點(diǎn):
computed:計(jì)算屬性是基于它們的依賴(lài)進(jìn)行緩存的饵史,只有在它的相關(guān)依賴(lài)發(fā)生改變時(shí)才會(huì)重新求值。
method:只要發(fā)生重新渲染胜榔, method 調(diào)用總會(huì)執(zhí)行該函數(shù)胳喷。
14、多頁(yè)面應(yīng)用與單頁(yè)面應(yīng)用的區(qū)別:
1)頁(yè)面的組成
多頁(yè)面夭织,由多個(gè)完整頁(yè)面吭露,例如:page1.html, page2.html
單頁(yè)面,由一個(gè)初始頁(yè)面和多個(gè)頁(yè)面模塊組成尊惰,例如:index.html和page1.html.js, page2.html.js
2)公共文件加載
多頁(yè)面奴饮,跳轉(zhuǎn)頁(yè)面前后纬向,js/css/img等公用文件重新加載
單頁(yè)面择浊,js/css/img等公用文件只在加載初始頁(yè)面時(shí)加載戴卜,更換頁(yè)面內(nèi)容前后無(wú)需重新加載
3)頁(yè)面跳轉(zhuǎn)/內(nèi)容更新
多頁(yè)面,頁(yè)面通過(guò)window.location.href = './index.html'跳轉(zhuǎn)
單頁(yè)面琢岩,通過(guò)使用js方法投剥,append/remove或者show/hide等方式來(lái)進(jìn)行頁(yè)面內(nèi)容的更換
4)頁(yè)面跳轉(zhuǎn)/內(nèi)容更新所需要數(shù)據(jù)的傳遞
多頁(yè)面,可以使用路徑攜帶數(shù)據(jù)傳遞的方式担孔,或者localstorage江锨,cookie等存儲(chǔ)方式
單頁(yè)面,直接通過(guò)參數(shù)傳遞糕篇,或者全局變量的方式進(jìn)行啄育,因?yàn)槎际窃谝粋€(gè)頁(yè)面的腳本環(huán)境下
5)用戶(hù)體驗(yàn)
多頁(yè)面,如果單個(gè)頁(yè)面加載的文件相對(duì)較大(多)拌消,頁(yè)面切換加載會(huì)很慢
單頁(yè)面挑豌,頁(yè)面片段切換較快,用戶(hù)體驗(yàn)較好墩崩,因?yàn)槌醮我呀?jīng)加載好相關(guān)文件氓英。但是初次加載頁(yè)面時(shí)需要調(diào)整優(yōu)化,因?yàn)榧虞d文件較多鹦筹。
6)使用場(chǎng)景
多頁(yè)面铝阐,適用于高度追求支持搜索引擎的應(yīng)用
單頁(yè)面,高要求的體驗(yàn)度铐拐,追求界面流暢的應(yīng)用
7)專(zhuān)場(chǎng)動(dòng)畫(huà)
多頁(yè)面徘键,不容易實(shí)現(xiàn)
單頁(yè)面,容易實(shí)現(xiàn)
總結(jié):?jiǎn)雾?yè)面模式相較有優(yōu)勢(shì)遍蟋,無(wú)論在用戶(hù)體驗(yàn)還是頁(yè)面切換的數(shù)據(jù)傳遞吹害,頁(yè)面切換動(dòng)畫(huà),都可以有比較答的操作空間匿值。
15赠制、Vue父子組件生命周期調(diào)用順序:
1)加載渲染過(guò)程:
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
2)子組件更新過(guò)程:
父fubeforeUpdate -> 子beforeUpdate -> 子updated -> 父updated
3)父組件更新過(guò)程:
父beforeUpdated -> 父updated
4)銷(xiāo)毀過(guò)程:
父beforeDestory -> 子beforeDestory -> 子destoryed -> 父destoryed
理解:
組件的調(diào)用順序都是先父后子,渲染完成的順序肯定是先子后父
組件的銷(xiāo)毀操作是先父后子挟憔,銷(xiāo)毀完成的順序是先子后父
16钟些、 Vue 組件 data 為什么必須是函數(shù)
因?yàn)?JS 本身的特性帶來(lái)的,如果 data 是一個(gè)對(duì)象绊谭,那么由于對(duì)象本身屬于引用類(lèi)型政恍,當(dāng)我們修改其中的一個(gè)屬性時(shí),會(huì)影響到所有 Vue 實(shí)例的數(shù)據(jù)达传。如果將 data 作為一個(gè)函數(shù)返回一個(gè)對(duì)象篙耗,那么每一個(gè)實(shí)例的 data 屬性都是獨(dú)立的迫筑,不會(huì)相互影響了。
17宗弯、Vue自定義過(guò)濾器
可以用全局方法Vue.filter(? )注冊(cè)一個(gè)自定義過(guò)濾器脯燃,它接收兩個(gè)參數(shù):過(guò)濾器ID和過(guò)濾器函數(shù)。過(guò)濾器函數(shù)以值為參數(shù)蒙保,返回轉(zhuǎn)換后的值辕棚。
js:Vue.filter('reverse',function(value){
? ? return value.split('').reverse().join('');
? ? })
html:<span v-text='message | reverse'></span>
18、Vue中自定義指令
全局定義指令:在vue對(duì)象的directive方法里面有兩個(gè)參數(shù)邓厕,一個(gè)是指令名稱(chēng)逝嚎,另一個(gè)是函數(shù)。
組件內(nèi)定義指令:directives
鉤子函數(shù):bind(綁定事件出發(fā))/ inserted(節(jié)點(diǎn)插入時(shí)候觸發(fā))/ update(組件內(nèi)相關(guān)更新)
鉤子函數(shù)參數(shù):el, binding
//注冊(cè)全局自定義指令详恼,v-focus
? Vue.directive('focus',{
? ? ? ? //當(dāng)被綁定的元素插入到DOM中時(shí)
? ? ? inserted: function(el){
? ? ? ? ? //聚焦元素
? ? ? ? ? el.focus()
? ? ? }
? })
//局部注冊(cè)
? ? directive:{
? ? ? focus:{
? ? ? ? ? ? //指令的定義
? ? ? ? ? ? inserted:function(el){
? ? ? ? ? ? ? ? el.focus();
? ? ? ? ? ? }
? ? ? ? }
? }
vuejs里的指令/組件/插件:
? ? ? ? 組件與指令的區(qū)別:
組件补君,通常都有對(duì)應(yīng)的html代碼,表示一塊具有特定樣式昧互,邏輯和功能的實(shí)體挽铁。
指令,通常用于給已存在DOM添加相應(yīng)的行為硅堆,例如v-if, v-for等屿储,定義指令的時(shí)候一般不需要特定的視圖。
? ? ? ? 組件與插件的區(qū)別:
組件渐逃,是用來(lái)構(gòu)成你的APP的業(yè)務(wù)模塊够掠,它的目標(biāo)是App.vue。
插件茄菊,是用來(lái)增強(qiáng)你的技術(shù)棧的功能模塊疯潭,它的目標(biāo)是Vue本身。
19面殖、Vue中常見(jiàn)性能優(yōu)化
1)編碼優(yōu)化:
不要將所有的數(shù)據(jù)都放在data中竖哩,data中的數(shù)據(jù)都會(huì)增加getter和setter,會(huì)收集對(duì)應(yīng)的watcher
vue在v-for時(shí)給每項(xiàng)元素綁定事件需要用事件代理
SPA頁(yè)面采用keep-alive緩存組件
拆分組件(提高復(fù)用性脊僚,增加代碼的可維護(hù)性相叁,減少不必要的渲染)
v-if當(dāng)值為false時(shí)內(nèi)部指令不會(huì)執(zhí)行,具有阻斷功能辽幌,很多情況下使用v-if替代v-show
key保證唯一性(默認(rèn)vue會(huì)采用就地復(fù)用策略)
Object.freeze凍結(jié)數(shù)據(jù)
合理使用路由懶加載增淹,異步組件
盡量采用runtime運(yùn)行時(shí)版本
數(shù)據(jù)持久化的問(wèn)題(防抖,節(jié)流)
2)vue加載性能優(yōu)化
第三方模塊按需導(dǎo)入(babel-plugin-component)
滾動(dòng)到可視區(qū)域動(dòng)態(tài)加載(https://tangbc.github.io/vue-virtual-scroll-list)
圖片懶加載(https://github.com/hilongjw/vue-lazyload)
3)用戶(hù)體驗(yàn)
app-skeleton骨架屏乌企,loading虑润,在加載過(guò)程中,可以提供loading圖標(biāo)
app-shell app殼 加酵,先加載頭和底部拳喻,給用戶(hù)正在加載哭当,不過(guò)加載較慢的錯(cuò)覺(jué)
pwa,serviceWorker
better-click防止iPhone點(diǎn)擊延遲冗澈,在開(kāi)發(fā)移動(dòng)端vuejs項(xiàng)目時(shí)钦勘,手指觸摸時(shí)會(huì)出現(xiàn)300ms的延遲效果,可以采用better-click對(duì)ipone系列的兼容體驗(yàn)優(yōu)化渗柿。
4)SEO優(yōu)化
預(yù)渲染插件prerender-spa-plugin
服務(wù)端渲染ssr
5)打包優(yōu)化
使用cdn的方式加載第三方模塊
多線(xiàn)程打包happypack
splitChunks抽離公共文件
sourceMap 生成个盆,屏蔽sourceMap,在index.js的通用配置文件分別對(duì)開(kāi)發(fā)環(huán)境和上線(xiàn)環(huán)境做了打包配置分類(lèi)朵栖,在build對(duì)象中的配置信息中,productionSourceMap修改成false柴梆。
6)緩存陨溅,壓縮
客戶(hù)端緩存,服務(wù)端緩存
服務(wù)端gzip壓縮绍在,對(duì)于項(xiàng)目代碼中的JS/CSS/等文件進(jìn)行g(shù)zip壓縮门扇,index.js的通用配置,productionGzip設(shè)置為true
20偿渡、為什么使用key:
當(dāng)有相同標(biāo)簽名的元素切換時(shí)臼寄,需要通過(guò)key特性設(shè)置唯一的值來(lái)標(biāo)記,讓Vue區(qū)分它們溜宽,否則Vue為了效率只會(huì)替換相同標(biāo)簽內(nèi)部的內(nèi)容吉拳。
21、自定義組件的雙向綁定(v-model):綁定value值适揉,監(jiān)聽(tīng)input事件留攒。
22、Vue組件化的理解:
定義:組件是可復(fù)用的Vue實(shí)例嫉嘀,準(zhǔn)確講它們是VueComponent的實(shí)例炼邀,繼承自Vue。
優(yōu)點(diǎn):組件化可以增加代碼的復(fù)用性剪侮,可維護(hù)性和可測(cè)試性拭宁。
使用場(chǎng)景:
通用組件,實(shí)現(xiàn)最基本的功能瓣俯,具有通用性杰标,復(fù)用性,例如按鈕組件降铸,輸入框在旱,布局組件
業(yè)務(wù)組件,完成具體業(yè)務(wù)推掸,具有一定的復(fù)用性桶蝎,例如登錄組件驻仅,輪播圖組件
頁(yè)面組件,組織應(yīng)用各部分獨(dú)立內(nèi)容登渣,需要時(shí)在不同頁(yè)面組件間切換噪服,例如列表頁(yè),詳情頁(yè)組件
如何使用組件:
定義胜茧,Vue.component()粘优,components選項(xiàng),sfc(單文件組件)
分類(lèi)呻顽,有狀態(tài)組件雹顺,fucntional(無(wú)狀態(tài),函數(shù)組件)廊遍,abstract(抽象組件嬉愧,沒(méi)有具體視圖)
通信,props喉前,$emit()/$on()没酣,provide/inject,$children/$parent/$root/$attrs/$listeners
內(nèi)容分發(fā)卵迂,<slot>裕便,<template>,v-slot (v-slot :后邊是插槽名稱(chēng)见咒,=后邊是組件內(nèi)部綁定作用域值的映射偿衰。)
使用及優(yōu)化,is论颅,keep-alive哎垦,異步組件
組件的本質(zhì):
vue中的組件經(jīng)歷如下過(guò)程:組件配置=》VueComponent實(shí)例=》render()=》virtual DOM=》DOM
所以組件的本質(zhì)是產(chǎn)生虛擬DOM
23、動(dòng)態(tài)路由
24恃疯、導(dǎo)航守衛(wèi):
全局守衛(wèi)漏设,每次路由跳轉(zhuǎn)都會(huì)被觸發(fā)
router.beforeEach((to,from,next)=>{ //全局前置守衛(wèi) });
router.beforeResolve((to,from,next)=>{ //全局解析守衛(wèi)})今妄;
router.afterEach((to,from)=>{ //全局后置鉤子})郑口;
路由獨(dú)享的守衛(wèi),寫(xiě)在配置里盾鳞,
beforeEnter(to,from,next)=>{? }
組件內(nèi)的守衛(wèi)犬性,可以在路由組件內(nèi)直接定義路由導(dǎo)航守衛(wèi)
beforeRouteEnter((to,from,next)=>{? })
beforeRouteUpdate((to,from,next)=>{? })
beforeRouteLeave((to,from,next)=>{? ? })
完整的導(dǎo)航解析流程(runQueue):
1)導(dǎo)航被觸發(fā)
2)在失活的組件里調(diào)用離開(kāi)守衛(wèi)
3)調(diào)用全局的beforeEach守衛(wèi)
4)在重用的組件里調(diào)用beforeRouterUpdate守衛(wèi)
5)在路由配置里調(diào)用beforeEnter
6)解析異步路由組件
7)在被激活的組件里調(diào)用beforeRouterEnter
8)調(diào)用全局的beforeResolve守衛(wèi)
9)導(dǎo)航被確認(rèn)
10)調(diào)用全局的afterEach鉤子
11)觸發(fā)DOM更新
12)用創(chuàng)建好的實(shí)例調(diào)用beforeRouteEnter守衛(wèi)中傳給next的回調(diào)函數(shù)
25、vue.js實(shí)現(xiàn)點(diǎn)擊按鈕腾仅,全頁(yè)面切換中英文乒裆?
1)所有組件配置當(dāng)前頁(yè)面所有json數(shù)據(jù),使用$bus.on和$bus.emit通知所有組件
2)配置在一個(gè)大的json中推励,放到app.Vue中鹤耍,讀取不同字段肉迫,通過(guò)props層層傳遞
3)使用Vue-i18n組件
26、vue數(shù)組/對(duì)象來(lái)渲染一個(gè)列表稿黄,修改數(shù)組的某個(gè)值喊衫,視圖是否會(huì)更新?為什么杆怕?
Vue.set(vm.items, indexOfItem, newValue)
Vue.items.splice(indexOfItem, 1, newvalue)
只有在data里初始化的數(shù)據(jù)才是響應(yīng)式的族购,Vue不能檢測(cè)到對(duì)象屬性的添加或刪除,沒(méi)有在data里聲明的屬性不是響應(yīng)式的陵珍。
27寝杖、router-link點(diǎn)擊事件失效,怎么解決的撑教?
在vue中綁定事件的方法:v-on:click=‘函數(shù)名稱(chēng)’;@click = ‘函數(shù)名稱(chēng)’;
在使用了 vue-router 路由時(shí)會(huì)使用 標(biāo)簽來(lái)代替 a 標(biāo)簽跳轉(zhuǎn)朝墩。
解決辦法:加 .native 修飾符
解釋?zhuān)?/p>
1: 因?yàn)樗亲远x標(biāo)簽,根本就沒(méi)有事件和方法伟姐,所以不觸發(fā),加個(gè)native 就是告訴vue 這個(gè)標(biāo)簽現(xiàn)在有主了 它是H5標(biāo)簽 可以加事件了亿卤。
2:父組件要想在子組件監(jiān)聽(tīng)自己的click事件就得加native愤兵,router-link 其實(shí)就是一個(gè)封裝好的 .vue 組件,所以需要 加.native修飾符才能綁定事件
28排吴、Vue常用的修飾符
表單修飾符:
? v-model.lazy,失去焦點(diǎn)秆乳,同步。
? ? v-model.number,讀輸入的值判斷是否可以轉(zhuǎn)換為number
? v-model.trim,輸入內(nèi)容钻哩,首位空格去除
事件修飾符:
? ? v-on:click.prevent--阻止默認(rèn)事件
? ? v-on:click.stop--阻止冒泡
? ? v-on:click.self要求click事件只有在e.target == e.currentTaget的時(shí)候才會(huì)執(zhí)行
? ? v-on:click.once只綁定一次click事件
? ? v-on:click.capture遵循事件捕獲順序屹堰,不是冒泡順序
v-on:scroll.passive = "onScroll" 在移動(dòng)端,觸發(fā)onscroll事件會(huì)讓網(wǎng)頁(yè)變卡街氢,使用這個(gè)修飾符扯键,相對(duì)于給onscroll事件整一個(gè).lazy修飾符。
v-on:click.native 該修飾符把一個(gè)vue組件轉(zhuǎn)化為一個(gè)普通的HTML標(biāo)簽珊肃。
按鍵修飾符:
? v-on:keyDown.enter,按鍵修飾符荣刑,只有enter鍵才執(zhí)行相對(duì)應(yīng)事件;tab,esc等按鍵
? ? v-on:keyDown.ctrl,alt,shift伦乔,meta系統(tǒng)修飾符,要按住相對(duì)應(yīng)的按鍵才能執(zhí)行事件
? v-on:click.right,middle,left鼠標(biāo)按鍵修飾符
29厉亏、axios的相關(guān)問(wèn)題:
axios是一個(gè)基于promise的HTTP庫(kù),可以用在瀏覽器和node.js中烈和。前端最流行的ajax請(qǐng)求庫(kù)爱只。
axios特點(diǎn):
1)基于promise的異步ajax請(qǐng)求庫(kù),支持promise所有的API
2)瀏覽器端/node端都可以使用招刹,瀏覽器中創(chuàng)建XMLHttpRequests
3)支持請(qǐng)求/響應(yīng)攔截器
4)支持請(qǐng)求取消
5)可以轉(zhuǎn)換請(qǐng)求數(shù)據(jù)和響應(yīng)數(shù)據(jù)恬试,并對(duì)響應(yīng)回來(lái)的內(nèi)容自動(dòng)轉(zhuǎn)換成JSON類(lèi)型的數(shù)據(jù)
6)批量發(fā)送多個(gè)請(qǐng)求
7)安全性更高窝趣,客戶(hù)端支持防御XSRF,就是讓你的每個(gè)請(qǐng)求都帶一個(gè)從cookie中拿到的key,根據(jù)瀏覽器同源策略忘渔,假冒的網(wǎng)站是拿不到你cookie中的key,這樣高帖,后臺(tái)就可以輕松辨別出這個(gè)請(qǐng)求是否是用戶(hù)在假冒網(wǎng)站上的誤導(dǎo)輸入,從而采取正確的策略畦粮。
axios常用語(yǔ)法
axios.get(url[, config]) //get請(qǐng)求用于列表和信息查詢(xún)
axios.delete(url[, config]) //刪除
axios.post(url[, data[, config]]) //post請(qǐng)求用于信息的添加
axios.put(url[, data[, config]]) //更新操作
axios.defaults.xxx //請(qǐng)求的默認(rèn)全局配置
axios.interceptors.request.use() //添加請(qǐng)求攔截器
axios.interceptors.response.use() //添加響應(yīng)攔截器
axios.Cancel() //用于創(chuàng)建取消請(qǐng)求的錯(cuò)誤對(duì)象
axios.CancelToken() //用于創(chuàng)建取消請(qǐng)求的token對(duì)象
axios.isCancel() //是否是一個(gè)取消請(qǐng)求的錯(cuò)誤
axios.all(promise) //用于批量執(zhí)行多個(gè)異步請(qǐng)求
axios.spread() //用來(lái)指定接收所有成功數(shù)據(jù)的回調(diào)函數(shù)的方法
axios為什么既能在瀏覽器環(huán)境運(yùn)行又能在服務(wù)器(node)環(huán)境運(yùn)行散址?
axios在瀏覽器端使用XMLHttpRequest對(duì)象發(fā)送ajax請(qǐng)求;在node環(huán)境使用http對(duì)象發(fā)送ajax請(qǐng)求宣赔。
var defaults.adapter = getDefaultAdapter();
function getDefaultAdapter () {
var adapter;
? if (typeof XMLHttpRequest !== 'undefined') {
? ? // 瀏覽器環(huán)境
? ? ? ? adapter = require('./adapter/xhr');
? ? } else if (typeof process !== 'undefined') {
? ? // node環(huán)境
? ? ? ? adapter = require('./adapter/http');
? }
? return adapter;
}
上述代碼预麸,可以看出XMLHttpRequest是一個(gè)API,它為客戶(hù)端提供了在客戶(hù)端和服務(wù)器之間傳輸數(shù)據(jù)的功能儒将;process對(duì)象是一個(gè)global(全局變量)吏祸,提供有關(guān)信息,控制當(dāng)前Node.js進(jìn)程钩蚊。
axios相關(guān)配置屬性:
‘url’是用于請(qǐng)求的服務(wù)器URL
‘method’是創(chuàng)建請(qǐng)求時(shí)使用的方法贡翘,默認(rèn)時(shí)get
‘baseURL’將自動(dòng)加在‘url’前面,除非‘url’是一個(gè)絕對(duì)URL砰逻。它可以通過(guò)設(shè)置一個(gè)‘baseURL’便于為axios實(shí)例的方法傳遞相對(duì)URL
‘transformRequset’允許在向服務(wù)器發(fā)送前鸣驱,修改請(qǐng)求數(shù)據(jù),只能用在‘PUT’蝠咆,‘POST’和‘PATCH’這幾個(gè)請(qǐng)求方法
‘headers’是即將被發(fā)送的自定義請(qǐng)求頭
‘params’是即將與請(qǐng)求一起發(fā)送的URL參數(shù)踊东,必須是一個(gè)無(wú)格式對(duì)象(plainobject)或URLSearchParams對(duì)象
‘a(chǎn)uth’表示應(yīng)該使用HTTP基礎(chǔ)驗(yàn)證,并提供憑據(jù)刚操,username, password
‘proxy’定義代理服務(wù)器的主機(jī)名稱(chēng)和端口
axios相比原生ajax的優(yōu)點(diǎn)(ajax的缺點(diǎn))
ajax是針對(duì)MVC的編程闸翅,不符合現(xiàn)在前端MVVM的浪潮
基于原生的XHR開(kāi)發(fā),XHR本身的架構(gòu)不清晰
30菊霜、懶加載(按需加載路由):
webpack中提供了require.ensure( )來(lái)實(shí)現(xiàn)按需加載坚冀。以前引入路由是通過(guò)import這樣的方式引入,改為const定義的方式進(jìn)行引入占卧。
不進(jìn)行頁(yè)面按需加載引入方式:import? home? from? '../../common/home.vue'
進(jìn)行頁(yè)面按需加載的引入方式:const? home=r=>require.ensure([ ],( )=>r(require('../../comon/home.vue')))
31遗菠、Vue-cli3.0和2.0的區(qū)別:
1)默認(rèn)進(jìn)行懶觀察(lazy observation)
在2.x版本里,不管數(shù)據(jù)多大华蜒,都會(huì)在一開(kāi)始就為其創(chuàng)建觀察者辙纬。當(dāng)數(shù)據(jù)很大時(shí),會(huì)在頁(yè)面載入時(shí)造成明顯的性能壓力叭喜。3.x版本贺拣,只會(huì)對(duì)‘被用于渲染初始可見(jiàn)部分的數(shù)據(jù)’創(chuàng)建觀察者。因此,3.x的觀察者更高效譬涡。
2)更精準(zhǔn)的變更通知
2.x版本中闪幽,使用Vue.set來(lái)給對(duì)象新增一個(gè)屬性時(shí),這個(gè)對(duì)象的所有watcher都會(huì)重新運(yùn)行涡匀;3.x版本中盯腌,只有依賴(lài)那個(gè)屬性的watcher才會(huì)重新運(yùn)行。
3)3.0新加了TypeScript以及PWA的支持陨瘩。
4)部分命令發(fā)生了變化
下載安裝npm? install? -g? vue@cli
刪除了vue list
創(chuàng)建項(xiàng)目vue create
啟動(dòng)項(xiàng)目 npm? run? serve
5)默認(rèn)項(xiàng)目目錄結(jié)構(gòu)也發(fā)生了變化
移除了配置文件目錄腕够,config和build文件夾
移除了static文件夾,新增public文件夾舌劳,并且index.html移動(dòng)到public中
在src文件夾中新增了views文件夾帚湘,用于分類(lèi)視圖組件和公共組件
32、Vue3.0新特性:
1)setup 是新的組件選項(xiàng)甚淡。充當(dāng)在組件內(nèi)部使用入口點(diǎn)大诸。
調(diào)用時(shí)間,創(chuàng)建組件實(shí)例時(shí)贯卦,在初始組件解析后立即調(diào)用资柔。在生命周期方面,它在beforeCreate之后撵割,created之前被調(diào)用建邓。
2)Proxy
3.0表示已經(jīng)放棄使用了Object.defineProperty,而選擇了使用更快的原生Proxy睁枕。消除了之前Vue2.0中基于Object.defineProperty的實(shí)現(xiàn)所存在的很多限制:無(wú)法監(jiān)聽(tīng)屬性的添加和刪除,數(shù)組索引和長(zhǎng)度的變更沸手,并可以支持Map外遇,Set,Weak Map契吉,Weak Set跳仿。
Proxy對(duì)象用于定義基本操作的自定義行為(如,屬性查找捐晶,賦值菲语,枚舉,函數(shù)調(diào)用等)惑灵。通俗講山上,就是在對(duì)目標(biāo)對(duì)象的操作之前提供了攔截,可以對(duì)外界的操作進(jìn)行過(guò)濾和改寫(xiě)英支,修改某些操作的默認(rèn)行為佩憾,這樣可以不直接操作對(duì)象本身,而是通過(guò)操作對(duì)象的代理對(duì)象來(lái)間接來(lái)操作對(duì)象,達(dá)到預(yù)期的目的妄帘。
語(yǔ)法:let? proxy = new Proxy(target楞黄,handler);
參數(shù)target是用Proxy包裝的目標(biāo)對(duì)象(可以是任何類(lèi)型的對(duì)象,包括原生數(shù)組抡驼,函數(shù)鬼廓,甚至另一個(gè)代理)。
參數(shù)handler也是一個(gè)對(duì)象致盟,其屬性是當(dāng)執(zhí)行一個(gè)操作時(shí)定義代理的行為的函數(shù)碎税,也就是子當(dāng)以的行為。
handler可以是空對(duì)象{ }勾邦,則并表示對(duì)proxy操作就是對(duì)目標(biāo)對(duì)象target操作蚣录;但不能設(shè)置為null,會(huì)拋出一個(gè)錯(cuò)誤---Cannot create proxy with a non-object? as? target or handler!
語(yǔ)法層:
new Proxy(target眷篇,handler);
target萎河,表示被代理的對(duì)象
handler,對(duì)代理的對(duì)象做了什么操作
handler {
set( ){ },? // 設(shè)置的時(shí)候干的事情
get( ){ },? // 獲取干的事情
deleteProperty( ){ },? // 刪除
has( ){ },? // 有沒(méi)有這個(gè)東西 ‘xxx’in? obj
apply( ){ },? // 調(diào)用函數(shù)處理
........
}
33蕉饼、vuex刷新數(shù)據(jù)消失:
監(jiān)聽(tīng)頁(yè)面是否刷新虐杯,如果頁(yè)面刷新了,將state對(duì)象存入到sessionStorage/localStorage中昧港。頁(yè)面打開(kāi)之后擎椰,判斷sessionStorage/localStorage中是否存在state對(duì)象,如果存在创肥,則說(shuō)明頁(yè)面是被刷新過(guò)的达舒,將sessionStorage/localStorage中存的數(shù)據(jù)取出來(lái)給vuex中的state賦值。如果不存在叹侄,說(shuō)明是第一次打開(kāi)巩搏,則取vuex中定義的state初始值。
//在頁(yè)面加載時(shí)讀取sessionStorage里的狀態(tài)信息
if (sessionStorage.getItem("store") ) {
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("store"))))
}
//在頁(yè)面刷新時(shí)將vuex里的信息保存到sessionStorage里
window.addEventListener("beforeunload",()=>{
sessionStorage.setItem("store",JSON.stringify(this.$store.state))
})
34趾代、vue怎樣監(jiān)聽(tīng)數(shù)組
vue通過(guò)重寫(xiě)數(shù)組的某些方法來(lái)監(jiān)聽(tīng)數(shù)組變化贯底,重寫(xiě)后的方法中會(huì)手動(dòng)觸發(fā)通知該數(shù)組的所有依賴(lài)進(jìn)行更新(ob.dep.notify( ))。
35撒强、vue手機(jī)端白屏:
手機(jī)白屏主要是因?yàn)轫?yè)面渲染阻塞導(dǎo)致的禽捆,導(dǎo)致的原因有:
1)css文件加載需要一定的時(shí)間,在加載的過(guò)程中頁(yè)面是空白的
解決:將css代碼前置或者內(nèi)聯(lián)html即使用<style>
2)可能是等待異步加載數(shù)據(jù)在渲染頁(yè)面導(dǎo)致白屏飘哨,數(shù)據(jù)量大加載慢胚想,導(dǎo)致數(shù)據(jù)沒(méi)請(qǐng)求到,阻塞頁(yè)面渲染
解決:在手機(jī)顯示的首屏?xí)r同步渲染頁(yè)面杖玲,后續(xù)的數(shù)據(jù)在也頁(yè)面滾動(dòng)(滑屏)時(shí)顿仇,再采取異步請(qǐng)求渲染頁(yè)面
3)手機(jī)頁(yè)面的首屏JS的執(zhí)行會(huì)阻塞頁(yè)面的渲染
解決:盡量不要在首屏html代碼中放置內(nèi)聯(lián)腳本淘正。即:不要使用<script></script>
首頁(yè)白屏優(yōu)化實(shí)踐:
1)SSR,服務(wù)端渲染臼闻。在服務(wù)端將渲染邏輯處理好鸿吆,然后將處理好的HTML直接返回給前端顯示。也可以解決SEO的問(wèn)題述呐,因?yàn)椴恍枰獎(jiǎng)討B(tài)獲取數(shù)據(jù)了惩淳。
2)預(yù)渲染,用prerender-spa-plugin做預(yù)渲染乓搬。下面是常用prerender-spa-plugin的配置思犁,staticDir預(yù)渲染輸出的文件地址,routes要做預(yù)渲染的路由进肯,minify壓縮相關(guān)的配置激蹲,render渲染引擎相關(guān)的配置,可以傳入自自定義的渲染引擎或者直接使用默認(rèn)的PuppeteerRenderer, renderAfterDocumentEvent是渲染引擎配置中的一個(gè)屬性江掩,指當(dāng)某個(gè)事件觸發(fā)時(shí)才執(zhí)行預(yù)渲染学辱。
const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
module.exports = {
? configureWebpack: config => {
? ? let plugins = []
? plugins.push(new PrerenderSPAPlugin({
? ? ? staticDir: path.resolve(__dirname, 'dist'),
? ? ? routes: ['/', '/about'],
? ? ? minify: {
? ? ? collapseBooleanAttributes: true,
? ? ? ? collapseWhitespace: true,
? ? ? ? decodeEntities: true,
? ? ? ? keepClosingSlash: true,
? ? ? ? sortAttributes: true
? ? },
? ? ? renderer: new Renderer({
? ? ? ? renderAfterDocumentEvent: 'custom-render-trigger'
? ? ? })
? }))
? ? config.plugins = [
? ? ? ...config.plugins,
? ? ...plugins
? ]
? }
}
3)骨架屏,loading
36环形、Vue監(jiān)聽(tīng)路由的變化:
1)通過(guò)watch
// 監(jiān)聽(tīng),當(dāng)路由發(fā)生變化的時(shí)候執(zhí)行
watch:{
? $route(to,from){
? ? console.log(to.path);
? }
},
或者
// 監(jiān)聽(tīng),當(dāng)路由發(fā)生變化的時(shí)候執(zhí)行
watch: {
? $route: {
? ? handler: function(val, oldVal){
? ? ? console.log(val);
? ? },
? ? // 深度觀察監(jiān)聽(tīng)
? ? deep: true
}
},
或者
// 監(jiān)聽(tīng),當(dāng)路由發(fā)生變化的時(shí)候執(zhí)行
watch: {
? '$route':'getPath'
},
methods: {
? getPath(){
? ? console.log(this.$route.path);
? }
}
2)通過(guò)vue-router的鉤子函數(shù)beforeRouterEnter / beforeRouteUpdate / beforeRouteLeave
// 監(jiān)聽(tīng)策泣,當(dāng)路由發(fā)生變化的時(shí)候執(zhí)行
beforeRouteEnter(to, from, next){
// 在渲染該組件的對(duì)應(yīng)路由被confirm前調(diào)用
// 不能獲取組件實(shí)例 'this'
// 因?yàn)楫?dāng)鉤子執(zhí)行前,組件實(shí)例還沒(méi)被創(chuàng)建
}抬吟,
beforeRouterUpdate( to, from, next){
// 在當(dāng)前路由改變萨咕,但是該組件被復(fù)用時(shí)調(diào)用
// 舉例來(lái)說(shuō),對(duì)于一個(gè)帶有動(dòng)態(tài)參數(shù)的路徑 /foo/:id火本,在/foo/1 和 /foo/2 之間調(diào)轉(zhuǎn)的時(shí)候
// 由于會(huì)渲染同樣的Foo組件危队,因此組件實(shí)例會(huì)被復(fù)用。而這個(gè)鉤子就會(huì)在這個(gè)情況下被調(diào)用钙畔。
// 可以訪(fǎng)問(wèn)組件實(shí)例 'this'
},
deforeRouteLeave( to, from, next){
// 導(dǎo)航離開(kāi)該組件的對(duì)應(yīng)路由時(shí)調(diào)用
// 可以訪(fǎng)問(wèn)組件實(shí)例 'this'
}
37交掏、vue的路由跳轉(zhuǎn):
1)router-link
不帶參數(shù):<router-link :to="{name:'home'}">
帶參數(shù):
<router-link :to="{name:'home', params: {id:1}}">
// 路由配置 path: "/home/:id" 或者 path: "/home:id"
// 不配置path ,第一次可請(qǐng)求,刷新頁(yè)面id會(huì)消失
// 配置path,刷新頁(yè)面id會(huì)保留
// html 取參 $route.params.id
// script 取參 this.$route.params.id
<router-link :to="{name:'home', query: {id:1}}">
// query傳參數(shù) (類(lèi)似get,url后面會(huì)顯示參數(shù))
// 路由可不配置
// html 取參 $route.query.id
// script 取參 this.$route.query.id
2)this.$router.push( )---函數(shù)里面調(diào)用
不帶參數(shù)
this.$router.push('/home')
this.$router.push({name:'home'})
this.$router.push({path:'/home'})
query傳參
this.$router.push({name:'home',query: {id:'1'}})
this.$router.push({path:'/home',query: {id:'1'}})
// html 取參 $route.query.id
// script 取參 this.$route.query.id
params傳參
this.$router.push({name:'home',params: {id:'1'}}) // 只能用 name
// 路由配置 path: "/home/:id" 或者 path: "/home:id" ,
// 不配置path ,第一次可請(qǐng)求,刷新頁(yè)面id會(huì)消失
// 配置path,刷新頁(yè)面id會(huì)保留
// html 取參 $route.params.id
// script 取參 this.$route.params.id
query和params區(qū)別:query類(lèi)似 get, 跳轉(zhuǎn)之后頁(yè)面 url后面會(huì)拼接參數(shù),類(lèi)似?id=1, 非重要性的可以這樣傳( 密碼之類(lèi)還是用params),刷新頁(yè)面id還在。params類(lèi)似 post, 跳轉(zhuǎn)之后頁(yè)面 url后面不會(huì)拼接參數(shù) , 但是刷新頁(yè)面id 會(huì)消失
3)this.$router.replace() (用法同上,push)
4)this.$router.go(n) ( )---向前或者向后跳轉(zhuǎn)n個(gè)頁(yè)面刃鳄,n可為正整數(shù)或負(fù)整數(shù)
區(qū)別:
this.$router.push----跳轉(zhuǎn)到指定url路徑,并向history棧中添加一個(gè)記錄钱骂,點(diǎn)擊后退會(huì)返回到上一個(gè)頁(yè)面
this.$router.replace----跳轉(zhuǎn)到指定的url路徑叔锐,但是history棧中不會(huì)有記錄,點(diǎn)擊返回跳轉(zhuǎn)到上上個(gè)頁(yè)面
this.$router.go(n)-----向前或者向后跳轉(zhuǎn)n個(gè)頁(yè)面见秽,n可為正整數(shù)或負(fù)整數(shù)