runtime-only 和 runtime-compiler
-
runtime-only:是運(yùn)行的時(shí)候代碼不能包含任意一個(gè)template標(biāo)簽
render(h)- 》 virtual Dom - 》UI真實(shí)dom
我們?cè)谑褂?Runtime Only 版本的 Vue.js 的時(shí)候掂骏,通常需要借助如 webpack 的 vue-loader 工具把 .vue 文件編譯成 JavaScript谬运,因?yàn)槭窃诰幾g階段做的京痢,所以它只包含運(yùn)行時(shí)的 Vue.js 代碼憨琳,因此代碼體積也會(huì)更輕量魔慷。 在將 .vue 文件編譯成 JavaScript的編譯過(guò)程中會(huì)將組件中的template模板編譯為render函數(shù),所以我們得到的是render函數(shù)的版本必怜。所以運(yùn)行的時(shí)候是不帶編譯的养涮,編譯是在離線的時(shí)候做的。
-
runtime-compiler:代碼中可以有template標(biāo)簽
-
template加載過(guò)程:
template - 》parse - 》ast 抽象語(yǔ)法樹(shù) - 》compiler - 》render(h)- 》 virtual Dom - 》UI真實(shí)dom
-
總結(jié)對(duì)比
最終渲染都是通過(guò) render 函數(shù)罐监,如果寫(xiě) template 屬性吴藻,則需要編譯成 render 函數(shù),那么這個(gè)編譯過(guò)程會(huì)發(fā)生運(yùn)行時(shí)弓柱,所以需要帶有編譯器的版本沟堡。
很顯然,這個(gè)編譯過(guò)程對(duì)性能會(huì)有一定損耗矢空,所以通常我們更推薦使用 Runtime-Only 的 Vue.js航罗。
runtime-only比runtime-compiler性能更高,代碼更少(少6kb)
計(jì)算屬性和監(jiān)聽(tīng)屬性和方法的區(qū)別
計(jì)算屬性
計(jì)算屬性是依賴的值改變會(huì)重新執(zhí)行函數(shù)妇多,當(dāng)數(shù)據(jù)沒(méi)有變化的時(shí)候伤哺,他會(huì)讀取緩存。計(jì)算屬性是取返回值作為最新結(jié)果者祖,所以里面不能異步的返回結(jié)果立莉。不能寫(xiě)異步邏輯。
頁(yè)面初次加載的時(shí)候七问,會(huì)運(yùn)行計(jì)算
計(jì)算屬性是對(duì)多個(gè)屬性進(jìn)行監(jiān)聽(tīng)蜓耻,進(jìn)一步整合,執(zhí)行判斷邏輯等械巡,返回結(jié)果作為一個(gè)新的屬性刹淌,可以綁定在頁(yè)面中
監(jiān)聽(tīng)屬性
偵聽(tīng)屬性是偵聽(tīng)的值改變會(huì)重新執(zhí)行函數(shù)饶氏,將一個(gè)值重新賦值作為最新結(jié)果,所以賦值的時(shí)候可以進(jìn)行一些異步操作有勾。
頁(yè)面初次加載的時(shí)候疹启,不會(huì)執(zhí)行操作
監(jiān)聽(tīng)屬性 是對(duì)單個(gè)已存在的data屬性進(jìn)行監(jiān)聽(tīng),獲取 oldValue newValue蔼卡,然后執(zhí)行一些判斷邏輯喊崖,比如修改其他值
總結(jié)對(duì)比
computed是屬性調(diào)用,而method是函數(shù)調(diào)用
數(shù)據(jù)變化時(shí)執(zhí)行異步或者開(kāi)銷比較大的操作的時(shí)候雇逞,這時(shí)候使用watch是合適的
computed一般是一個(gè)依賴值衍生新的值荤懂,值結(jié)果會(huì)被緩存,除非依賴值發(fā)生變化才會(huì)重新計(jì)算( eg:購(gòu)物車結(jié)算 )
watch一般監(jiān)聽(tīng)一個(gè)對(duì)象鍵值是需要觀察的變量或者表達(dá)式塘砸,鍵值對(duì)應(yīng)是回調(diào)函數(shù)节仿,主要是負(fù)責(zé)監(jiān)聽(tīng)某些特定數(shù)據(jù)的變化,從而進(jìn)行某些具體的業(yè)務(wù)邏輯
methods方法表示一個(gè)具體的操作掉蔬,負(fù)責(zé)書(shū)寫(xiě)主要業(yè)務(wù)邏輯
keep-alive
名詞解釋和作用
keep-alive是vue內(nèi)置的組件廊宪,自身不會(huì)渲染一個(gè)DOM元素,Vue在初始化生命周期的時(shí)候眉踱,為組件實(shí)例建立父子關(guān)系會(huì)根據(jù)abstract屬性決定是否忽略某個(gè)組件挤忙。在keep-alive中,設(shè)置了abstract:true谈喳,那Vue就會(huì)跳過(guò)該組件實(shí)例册烈。最后構(gòu)建的組件樹(shù)中就不會(huì)包含keep-alive組件,那么由組件樹(shù)渲染成的DOM樹(shù)自然也不會(huì)有keep-alive相關(guān)的節(jié)點(diǎn)了婿禽。
可以是被包含的組件保留狀態(tài)赏僧,緩存組件實(shí)例,不會(huì)銷毀扭倾,避免重新渲染淀零。
避免組件反復(fù)創(chuàng)建和渲染,有效提升系統(tǒng)性能膛壹〖葜校總的來(lái)說(shuō),keep-alive用于保存組件的渲染狀態(tài)模聋。
對(duì)應(yīng)的vue組件生命周期 activited和deactivited
屬性說(shuō)明
include:可以是字符串(組件名稱)或者正則表達(dá)式肩民,只有匹配的組件會(huì)被緩存
exclude:可以是字符串(組件名稱)或者正則表達(dá)式,任何匹配的組件都不會(huì)被緩存
max:定義緩存組件上限链方,超出上限使用LRU的策略置換緩存數(shù)據(jù)持痰。
內(nèi)存管理的一種頁(yè)面置換算法,對(duì)于在內(nèi)存中但又不用的數(shù)據(jù)塊(內(nèi)存塊)叫做LRU祟蚀,操作系統(tǒng)會(huì)根據(jù)哪些數(shù)據(jù)屬于LRU而將其移出內(nèi)存而騰出空間來(lái)加載另外的數(shù)據(jù)工窍。
兩個(gè)同時(shí)使用割卖,若某組件同時(shí)被兩個(gè)屬性都匹配, exclude 優(yōu)先級(jí)較高患雏,最終匹配的組件不會(huì)被緩存
路由傳參
路由傳參有4種方式
路由配置表中鹏溯,路徑后面串聯(lián)傳入的參數(shù)
強(qiáng)制刷新頁(yè)面,參數(shù)不會(huì)丟失 {path: '/a/:num', name: A, component: A}
方式1:通過(guò)router-link纵苛,to屬性 路由地址+傳遞參數(shù)
<router-link to = "/a/12">
方式2:通過(guò)path 串聯(lián)路由地址和傳遞的參數(shù)
this.$router.push({
path: `/d/${id}`
})
方式3:通過(guò)命名路由+params 匹配路由配置好的屬性名
this.$router.push({
name: 'A',
params: {
num: '12'
}
})
命名路由+params傳遞參數(shù)
路徑后面不需要加傳入的參數(shù)剿涮,再次刷新頁(yè)面后,參數(shù)會(huì)丟失 {path: '/b', name: 'B', component: B}
this.$router.push({
name: 'B',
params: {
sometext: '一只羊出沒(méi)'
}
})
獲取參數(shù): {{this.$route.params.sometext}}
通過(guò)query來(lái)傳遞參數(shù)
會(huì)顯示在地址攻人,以?開(kāi)頭串聯(lián)在地址末尾悬槽,傳遞多個(gè)參數(shù)怀吻,用“&”隔開(kāi),每個(gè)參數(shù)的名和值用“=”隔開(kāi)初婆,強(qiáng)制刷新頁(yè)面蓬坡,參數(shù)不會(huì)丟失
this.$router.push({
path: '/c',
query: {
sometext: '這是小羊同學(xué)'
}
獲取參數(shù):{{this.$route.query.sometext}}
傳參注意事項(xiàng)
1.當(dāng)使用path路徑匹配路由時(shí),不能和params不能同時(shí)使用磅叛,params傳遞的參數(shù)會(huì)丟失
2.當(dāng)使用命名路由時(shí)name屑咳,params和query可以同時(shí)使用傳遞參數(shù)
路由懶加載
為什么要懶加載
當(dāng)打包構(gòu)建應(yīng)用時(shí),JavaScript 包會(huì)變得非常大弊琴,影響頁(yè)面加載兆龙。
路由中會(huì)定義很多不同的頁(yè)面,默認(rèn)情況下這些頁(yè)面會(huì)被打包放在一個(gè)js文件中敲董,造成這個(gè)js文件非常大紫皇,請(qǐng)求耗時(shí)會(huì)比較久,有可能用戶的電腦還會(huì)出現(xiàn)短暫的空白腋寨,影響用戶的體驗(yàn)聪铺。
怎么實(shí)現(xiàn)懶加載
結(jié)合 Vue 的異步組件 (opens new window)和 Webpack 的代碼分割功能 (opens new window),輕松實(shí)現(xiàn)路由組件的懶加載
路由懶加載功能
主要作用就是將路由對(duì)應(yīng)的組件打包成一個(gè)個(gè)的js代碼塊萄窜,只有在這個(gè)路由被訪問(wèn)的時(shí)候铃剔,才加載對(duì)應(yīng)的組件
路由懶加載的三種方式
方式1 結(jié)合vue的異步組件和webpack的代碼分析,寫(xiě)法太復(fù)雜查刻,基本已經(jīng)棄用
const home = resolve => {require.ensure(['../views/Home.vue'],()=>{
resolve(require('../views/Home.vue'))
})}
方式2:AMD寫(xiě)法键兜,也基本被棄用了
const home = resolve =>require(['../vuews/Home.vue'],resolve);
方式3:在ES6中 有更加簡(jiǎn)單的寫(xiě)法來(lái)組織vue異步組件和webpack的代碼分割,強(qiáng)烈推薦
const home = ()=> import('../views/Home.vue')
路由守衛(wèi)
路由守衛(wèi)分為2兩種: 全局守衛(wèi)和局部守衛(wèi)
全局守衛(wèi) :前置守衛(wèi) beforeEatch 和后置鉤子 afterEatch
局部守衛(wèi)包括:路由守衛(wèi)和組件守衛(wèi)
路由守衛(wèi)是配置在路由映射表中,beforeEnter赖阻,參數(shù)和beforeEatch一直蝶押,優(yōu)先級(jí)高于全局守衛(wèi)
組件守衛(wèi)是定義在組件中的鉤子函數(shù) beforeRouterEnter , beforeRouterUpdate火欧, beforeRouterLevel
beforeRouterEnter 中不能使用this棋电,因?yàn)檫€沒(méi)有創(chuàng)建好組件茎截。
beforeRouterUpdate 是當(dāng)路由地址沒(méi)有改變,但是參數(shù)改變的時(shí)候赶盔,才會(huì)被調(diào)用企锌,比如 /a/1 => /a/2
beforeEatch((to,from,next)={
})
beforeEatch是一個(gè)函數(shù),里面的參數(shù)是一個(gè)箭頭函數(shù)于未,to和from 都是route對(duì)象實(shí)例撕攒,next和函數(shù),必須要調(diào)用烘浦,所以不會(huì)執(zhí)行路由不會(huì)跳轉(zhuǎn)
通常用全局的守衛(wèi)來(lái)監(jiān)聽(tīng)路由跳轉(zhuǎn)抖坪,執(zhí)行一些全局的操作,比如標(biāo)題闷叉。
路由導(dǎo)航
所有的組件都繼承自vue的原型擦俐,在vue原型vue.prototype 上定義的函數(shù)和屬性,子組件可以通過(guò)this. 直接調(diào)用,
比如**this.$router 和this.$route**
this.$router 指向的路由映射表握侧,VueRouter實(shí)例蚯瞧,可以導(dǎo)航到不同的url,
this.$router.push(),this.$router.replace,對(duì)應(yīng)的history中的pushState和replaceState
this.$route 指向的是路由映射表中的一個(gè)路由選項(xiàng)品擎,代表當(dāng)前跳轉(zhuǎn)的路由埋合,可以獲取當(dāng)前路由的name,path萄传,query甚颂,params等
Es6新特性
1.不一樣的變量聲明:const和let,ES6推薦使用let聲明局部變量
let表示聲明變量盲再,而const表示聲明常量西设,兩者都為塊級(jí)作用域;const 聲明的變量都會(huì)被認(rèn)為是常量答朋,意思就是它的值被設(shè)置完成后就不能再修改了
如果const的是一個(gè)對(duì)象贷揽,對(duì)象所包含的值是可以被修改的。抽象一點(diǎn)兒說(shuō)梦碗,就是對(duì)象所指向的地址沒(méi)有變就行
let 關(guān)鍵詞聲明的變量不具備變量提升(hoisting)特性禽绪,不能先使用,再聲明洪规。var具備變量提升
let 和 const 聲明只在最靠近的一個(gè)塊中(花括號(hào)內(nèi))有效
當(dāng)使用常量 const 聲明時(shí)印屁,請(qǐng)使用大寫(xiě)變量,如:CAPITAL_CASING
const 在聲明時(shí)必須被賦值
2.模板字符串
在ES6之前斩例,我們往往通過(guò)“\”和“+”來(lái)構(gòu)建模板
es6可以將表達(dá)式嵌入字符串中進(jìn)行拼接雄人。用${}來(lái)界定;
ES6反引號(hào)(``)直接搞定;
$("body").html(`This demonstrates the output of HTML content to the page, including student's ${name}, ${seatNumber}, ${sex} and so on.`);
3.箭頭函數(shù)(Arrow Functions)
ES6 中础钠,箭頭函數(shù)就是函數(shù)的一種簡(jiǎn)寫(xiě)形式恰力,使用括號(hào)包裹參數(shù),跟隨一個(gè) =>旗吁,緊接著是函數(shù)體踩萎;
箭頭函數(shù)最直觀的三個(gè)特點(diǎn)。
- 不需要 function 關(guān)鍵字來(lái)創(chuàng)建函數(shù)
- 省略 return 關(guān)鍵字
- 繼承當(dāng)前上下文的 this 關(guān)鍵字
- 當(dāng)你的函數(shù)有且僅有一個(gè)參數(shù)的時(shí)候很钓,是可以省略掉括號(hào)的香府。當(dāng)你函數(shù)返回有且僅有一個(gè)表達(dá)式的時(shí)候可以省略{} 和 return;
4.函數(shù)參數(shù)默認(rèn)值
// ES6之前码倦,當(dāng)未傳入?yún)?shù)時(shí)企孩,
text = 'default';
function printText(text) {
text = text || 'default';
console.log(text);
}
// ES6叹洲;
function printText(text = 'default') {
console.log(text);
}
printText('hello'); // helloprintText();// default
5.二進(jìn)制和八進(jìn)制字面量
ES6 支持二進(jìn)制和八進(jìn)制的字面量柠硕,通過(guò)在數(shù)字前面添加 0o 或者0O 即可將其轉(zhuǎn)換為八進(jìn)制值:
let oValue = 0o10;console.log(oValue); // 8 let bValue = 0b10; // 二進(jìn)制使用 `0b` 或者 `0B`console.log(bValue); // 2
6.模塊化 export 和 import
import 導(dǎo)入模塊、export 導(dǎo)出模塊
可以直接在任何變量或者函數(shù)前面加上一個(gè) export 關(guān)鍵字运提,就可以將它導(dǎo)出。
let var 和const區(qū)別
在javascript中有三種聲明變量的方式:var闻葵、let民泵、const。
JS中作用域有:全局作用域槽畔、函數(shù)作用域栈妆。沒(méi)有塊作用域的概念。ECMAScript 6(簡(jiǎn)稱ES6)中新增了塊級(jí)作用域厢钧。****塊作用域由 { } 包括鳞尔,if語(yǔ)句和for語(yǔ)句里面的{ }也屬于塊作用域。
var
var定義的變量可以修改早直,如果不初始化會(huì)輸出undefined寥假,不會(huì)報(bào)錯(cuò)。
var 聲明全局變量霞扬,換句話理解就是糕韧,聲明在for循環(huán)中的變量,跳出for循環(huán)同樣可以使用喻圃。
let
同一個(gè)變量萤彩,不可在聲明之前調(diào)用,必須先定義再使用斧拍,否則會(huì)報(bào)錯(cuò)雀扶,循環(huán)體中可以用let
let是塊級(jí)作用域,函數(shù)內(nèi)部使用let定義后肆汹,對(duì)函數(shù)外部無(wú)影響愚墓。并且let不能定義同名變量予权,否則會(huì)報(bào)錯(cuò)。
cosnt
const:用于聲明常量转绷,也具有塊級(jí)作用域 伟件,也可聲明塊級(jí)。const定義的變量不可以修改议经,而且必須初始化斧账。
如果const的是一個(gè)對(duì)象,對(duì)象所包含的值是可以被修改的煞肾。抽象一點(diǎn)兒說(shuō)咧织,就是對(duì)象所指向的地址沒(méi)有變就行
它和let一樣,也不能重復(fù)定義同一個(gè)變量籍救,const一旦定義习绢,無(wú)法修改.
let和const屬于局部變量,不會(huì)出現(xiàn)變量提升的情況蝙昙,
全局定義的let和const變量闪萄,不屬于頂層變量,不屬于window的屬性奇颠,
瀏覽器環(huán)境中頂層對(duì)象是window败去,Node中是global對(duì)象
es5中頂層變量的屬性等價(jià)于全局變量,定義的var變量是window屬性
到了es6中有所改變烈拒,es5的var ,function 聲明的全局變量 依舊是頂級(jí)對(duì)象的屬性 而es6聲明的全局變量不屬于頂級(jí)對(duì)象的屬性了
var age = 29;
let ages = 29;
alert(window.age) ==>29
alert(window.ages ) ==>undefined
axios配置
//安裝axios
npm install axios
Axios 是一個(gè)基于 promise 的 HTTP 庫(kù)圆裕,可以用在瀏覽器和 node.js 中【<福可以執(zhí)行g(shù)et請(qǐng)求吓妆,執(zhí)行post請(qǐng)求,執(zhí)行多個(gè)并發(fā)請(qǐng)求吨铸,支持promise 行拢,攔截請(qǐng)求和響應(yīng),轉(zhuǎn)換請(qǐng)求數(shù)據(jù)和響應(yīng)數(shù)據(jù)焊傅,取消請(qǐng)求 剂陡,自動(dòng)轉(zhuǎn)換json數(shù)據(jù)。
1.支持node端和瀏覽器端
同樣的API狐胎,node和瀏覽器全支持鸭栖,平臺(tái)切換無(wú)壓力
2.支持 Promise
使用Promise管理異步,告別傳統(tǒng)callback方式
3.豐富的配置項(xiàng)
支持?jǐn)r截器等高級(jí)配置
常用的請(qǐng)求配置
method:請(qǐng)求方法 post get delete put等
baseUrl:請(qǐng)求基本路徑地址握巢,將自動(dòng)加在 `url` 前面
url:請(qǐng)求地址
headers:自定義請(qǐng)求頭參數(shù)晕鹊,可以包含token,content-type等
timeout:配置請(qǐng)求超時(shí)
params: 是即將與請(qǐng)求一起發(fā)送的 URL 參數(shù)
添加攔截器
// 添加請(qǐng)求攔截器
axios.interceptors.request.use(
function (response) { // 對(duì)請(qǐng)求數(shù)據(jù)做點(diǎn)什么 return response; },
function (error) { // 對(duì)請(qǐng)求錯(cuò)誤做點(diǎn)什么 return Promise.reject(error); }
);
// 添加響應(yīng)攔截器
axios.interceptors.response.use(
function (response) { // 對(duì)響應(yīng)數(shù)據(jù)做點(diǎn)什么 return response; },
function (error) { // 對(duì)響應(yīng)錯(cuò)誤做點(diǎn)什么 return Promise.reject(error); }
);
創(chuàng)建axios實(shí)例
function createAxios(type){
let timeout = 20000; //統(tǒng)一的超時(shí)時(shí)間
var token = null;
if (userInfo.token()) {
token = userInfo.token();
}
let applicationHeaderPayload = {
'Content-Type': 'application/json; charset=utf-8',
'token':token,
'platform': "H5",
'Accept': '*/*'
}
let applicationHeader = {
'Content-Type': 'application/x-www-form-urlencoded',
'token':token,
'platform': "H5",
'Accept': '*/*'
};
let args = {}; //配置參數(shù)
let axiosInstance; //axios 實(shí)例
switch(type){
case "payload" :
args = {
timeout,
"headers": applicationHeaderPayload
};
break;
case "formData" :
args = {
timeout,
"headers" : applicationHeader
};
break;
default :
break;
}
axiosInstance = axios.create(args);
axiosInstance.interceptors.request.use (function (config) { //請(qǐng)求攔截器
var token = null;
if (userInfo.token()) {
token = userInfo.token();
}
config.url = baseUrl+config.url;
config.headers = {
'Content-Type': 'application/json; charset=utf-8',
'token':token,
'platform': "H5",
'Accept': '*/*'
}
if(config && config.data && ['formData'].indexOf(type) != -1){
config.data = qs.stringify(config.data);
config.headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'token':token,
'platform': "H5",
'Accept': '*/*'
}
}
return config;
}, function (error) {
return Promise.reject(error);
});
axiosInstance.interceptors.response.use(function (response) { //返回?cái)r截器
return handleSuccess(response);
}, function (data) {
return handleError(data);
});
return axiosInstance;
}
vue-router兩種加載模式
1. Hash (對(duì)應(yīng)HashHistory)
hash(“#”)符號(hào)的本來(lái)作用是加在URL中指示網(wǎng)頁(yè)中的位置:
http://www.example.com/index.html#print
符號(hào)本身以及它后面的字符稱之為hash(也就是我之前為什么地址欄都會(huì)有一個(gè)‘#’),可通過(guò)window.location.hash屬性讀取溅话。它具有如下特點(diǎn):
- hash雖然出現(xiàn)在URL中晓锻,但不會(huì)被包括在HTTP請(qǐng)求中。它是用來(lái)指導(dǎo)瀏覽器動(dòng)作的飞几,對(duì)服務(wù)器端完全無(wú)用砚哆,因此,改變hash不會(huì)重新加載頁(yè)面
2.可以為hash的改變添加監(jiān)聽(tīng)事件:
window.addEventListener("hashchange", funcRef, false)
- 每一次改變hash(window.location.hash)屑墨,都會(huì)在瀏覽器的訪問(wèn)歷史中增加一個(gè)記錄
利用hash的以上特點(diǎn)躁锁,就可以來(lái)實(shí)現(xiàn)前端路由“更新視圖但不重新請(qǐng)求頁(yè)面”的功能了。
2. History (對(duì)應(yīng)HTML5History)
History接口是瀏覽器歷史記錄棧提供的接口卵史,通過(guò)back(), forward(), go()等方法战转,我們可以讀取瀏覽器歷史記錄棧的信息,進(jìn)行各種跳轉(zhuǎn)操作以躯。
從HTML5開(kāi)始槐秧,History interface提供了兩個(gè)新的方法:pushState(), replaceState()使得我們可以對(duì)瀏覽器歷史記錄棧進(jìn)行修改:
window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
stateObject: 當(dāng)瀏覽器跳轉(zhuǎn)到新的狀態(tài)時(shí),將觸發(fā)popState事件忧设,該事件將攜帶這個(gè)stateObject參數(shù)的副本
title: 所添加記錄的標(biāo)題
URL: 所添加記錄的URL
這兩個(gè)方法有個(gè)共同的特點(diǎn):當(dāng)調(diào)用他們修改瀏覽器歷史記錄棧后刁标,雖然當(dāng)前URL改變了,但瀏覽器不會(huì)刷新頁(yè)面址晕,這就為單頁(yè)應(yīng)用前端路由“更新視圖但不重新請(qǐng)求頁(yè)面”提供了基礎(chǔ)命雀。
瀏覽器歷史記錄可以看作一個(gè)「棧」斩箫。棧是一種后進(jìn)先出的結(jié)構(gòu),可以把它想象成一摞盤(pán)子撵儿,用戶每點(diǎn)開(kāi)一個(gè)新網(wǎng)頁(yè)乘客,都會(huì)在上面加一個(gè)新盤(pán)子,叫「入椀硇」易核。
用戶每次點(diǎn)擊「后退」按鈕都會(huì)取走最上面的那個(gè)盤(pán)子,叫做「出椑四」牡直。而每次瀏覽器顯示的自然是最頂端的盤(pán)子的內(nèi)容。
vue-router 的作用
vue-router的作用就是通過(guò)改變URL纳决,在不重新請(qǐng)求頁(yè)面的情況下碰逸,更新頁(yè)面視圖。簡(jiǎn)單的說(shuō)就是阔加,雖然地址欄的地址改變了饵史,但是并不是一個(gè)全新的頁(yè)面,而是之前的頁(yè)面某些部分進(jìn)行了修改。
export default new Router({
mode: 'history', //后端支持可開(kāi)
routes: constantRouterMap})
這是Vue項(xiàng)目中常見(jiàn)的一段初始化vue-router的代碼胳喷,mode屬性用來(lái)指定vue-router使用哪一種模式湃番。在沒(méi)有指定mode的值,則使用hash模式吭露。
vue-router路由模式有幾種吠撮?請(qǐng)談?wù)勀銓?duì)它們的理解?
常用的路由模式有hash和history讲竿;
最直觀的區(qū)別是hash模式url上會(huì)攜帶有一個(gè)#泥兰,而history不攜帶;
hash:
即地址欄URL中的#符號(hào)戴卜,它的特點(diǎn)在于hash值雖然出現(xiàn)在URL中逾条,但不會(huì)被包括在HTTP請(qǐng)求中,對(duì)服務(wù)端完全沒(méi)影響投剥,因此改變hash值不會(huì)重新加載頁(yè)面师脂。
history:
利用了HTML5 History interface 中新增的pushState() 和 replaceState()方法。
這兩個(gè)方法應(yīng)用于瀏覽器歷史記錄棧江锨,提供了修改歷史記錄的功能吃警,執(zhí)行修改時(shí)雖然改變了URL但是不會(huì)立即的向服務(wù)端發(fā)起請(qǐng)求。
hash和history模式都屬于瀏覽器自身的特性啄育,vue-router只是利用了這兩個(gè)特性來(lái)實(shí)現(xiàn)前端路由
但是在history模式下會(huì)出現(xiàn)刷新404的問(wèn)題酌心,對(duì)于這個(gè)問(wèn)題,我們只需要在服務(wù)器配置nginx如果URL匹配不到任何靜態(tài)資源挑豌,就跳轉(zhuǎn)到默認(rèn)的index.html
history.pushState()相比于直接修改hash主要有以下優(yōu)勢(shì):
- pushState設(shè)置的新URL可以是與當(dāng)前URL同源的任意URL安券;而hash只可修改#后面的部分,故只可設(shè)置與當(dāng)前同文檔的URL
- pushState設(shè)置的新URL可以與當(dāng)前URL一模一樣氓英,這樣也會(huì)把記錄添加到棧中侯勉;而hash設(shè)置的新值必須與原來(lái)不一樣才會(huì)觸發(fā)記錄添加到棧中
- pushState通過(guò)stateObject可以添加任意類型的數(shù)據(jù)到記錄中;而hash只可添加短字符串
- pushState可額外設(shè)置title屬性供后續(xù)使用
v-if 和 show的區(qū)別
相同點(diǎn):v-if與v-show都可以動(dòng)態(tài)控制dom元素顯示隱藏
不同點(diǎn):v-if顯示隱藏是將dom元素整個(gè)添加或刪除铝阐,而v-show隱藏則是為該元素添加css--display:none址貌,dom元素還在。
組件通信的方法
父子組件通信
1.props 父組件向子組件傳遞數(shù)據(jù) 徘键,$emit 子組件觸發(fā)父組件事件響應(yīng)
2.$children 和 $refs 獲取子組件實(shí)例對(duì)象练对,$parent或者$root 獲取父組件或者根組件實(shí)例對(duì)象。拿到實(shí)例對(duì)象可以直接操作data數(shù)據(jù)或者調(diào)用函數(shù)吹害,但是一般不推薦螟凭,耦合度太高
$children 和 $refs 獲取子組件實(shí)例對(duì)象 這兩個(gè)的區(qū)別:
ref可以指定任意的dom元素節(jié)點(diǎn),包括原生HTML元素赠制,children 獲取的是包含自定義子組件實(shí)例列表赂摆,并且是無(wú)序的
3.通過(guò)vuex 或者localStorage 保存數(shù)據(jù)挟憔,進(jìn)行數(shù)據(jù)傳遞
4.多級(jí)組件嵌套需要傳遞數(shù)據(jù)時(shí), Vue2.4 版本提供了另一種方法----$attrs/$listeners
5. provide/inject,以允許一個(gè)祖先組件向其所有子孫后代注入一個(gè)依賴烟号,不論組件層次有多深绊谭,并在起上下游關(guān)系成立的時(shí)間里始終生效。
祖先組件中通過(guò) provider 來(lái)提供變量汪拥,然后在子孫組件中通過(guò) inject 來(lái)注入變量达传。
provide / inject API 主要解決了跨級(jí)組件間的通信問(wèn)題,不過(guò)它的使用場(chǎng)景迫筑,主要是子組件獲取上級(jí)組件的狀態(tài)宪赶,跨級(jí)組件間建立了一種主動(dòng)提供與依賴注入的關(guān)系。
需要注意的是:**provide 和 inject 綁定并不是可響應(yīng)的**脯燃。這是刻意為之的搂妻。然而,如果你傳入了一個(gè)可監(jiān)聽(tīng)的對(duì)象辕棚,那么其對(duì)象的屬性還是可響應(yīng)的----vue 官方文檔
所以欲主,上面 A.vue 的 name 如果改變了,B.vue 的 this.name 是不會(huì)改變的逝嚎,為了解決這種問(wèn)題扁瓢,可以把祖先組件的this實(shí)例傳遞provide過(guò)去,然后子組件通過(guò)this 獲取需要的參數(shù)补君。耦合度太高
組件通信常見(jiàn)使用場(chǎng)景可以分為三類:
**父子通信:**
父向子傳遞數(shù)據(jù)是通過(guò) props引几,子向父是通過(guò) events($emit);
通過(guò)父鏈 / 子鏈也可以通信($parent / $children)挽铁;ref 也可以訪問(wèn)組件實(shí)例伟桅;
provide / inject API;$attrs/$listeners
** 兄弟通信:**
Bus叽掘;Vuex贿讹;localStorage
**跨級(jí)通信:**
Bus;Vuex够掠;localStorage;provide / inject API茄菊;$attrs/$listeners
vue 自定義指令
自定義指令
Vue 內(nèi)置了一些非常有用的指令(比如v-html 和 v-once等)疯潭,每個(gè)指令都有自身的用途
Vue 也允許注冊(cè)自定義指令。它的作用價(jià)值在于當(dāng)開(kāi)發(fā)人員在某些場(chǎng)景下需要對(duì)普通 DOM 元素進(jìn)行操作面殖。
Vue 自定義指令有全局注冊(cè)和局部注冊(cè)兩種方式竖哩。先來(lái)看看注冊(cè)全局指令的方式,
通過(guò) Vue.directive( id, [definition] ) 方式注冊(cè)全局指令脊僚。然后在入口文件中進(jìn)行 Vue.use() 調(diào)用相叁。
當(dāng)頁(yè)面加載時(shí)遵绰,該元素將獲得焦點(diǎn) (注意:autofocus 在移動(dòng)版 Safari 上不工作)。事實(shí)上,只要你在打開(kāi)這個(gè)頁(yè)面后還沒(méi)點(diǎn)擊過(guò)任何內(nèi)容,這個(gè)輸入框就應(yīng)當(dāng)還是處于聚焦?fàn)顟B(tài)∠ü睿現(xiàn)在讓我們用指令來(lái)實(shí)現(xiàn)這個(gè)功能:
注冊(cè)一個(gè)全局自定義指令 v-focus
Vue.directive('focus', {
// 當(dāng)被綁定的元素插入到 DOM 中時(shí)……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
如果想注冊(cè)局部指令吭从,組件中也接受一個(gè) directives 的選項(xiàng):
directives: {
focus: {
// 指令的定義
inserted: function (el) {
el.focus()
}
}
}
然后你可以在模板中任何元素上使用新的 v-focus property,如下:<input v-focus>
vue常用內(nèi)置指令
v-model
v-for
v-text
v-html
v-on
v-bind
v-if/v-else
v-show
1.vuex是什么憋肖?怎么使用?哪種功能場(chǎng)景使用它
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài)哭当,并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。簡(jiǎn)單來(lái)說(shuō)就是:應(yīng)用遇到多個(gè)組件共享狀態(tài)時(shí)冗澈,使用vuex钦勘。
場(chǎng)景:多個(gè)組件共享數(shù)據(jù)或者是跨組件傳遞數(shù)據(jù)時(shí)
vuex的流程
頁(yè)面通過(guò)mapAction異步提交事件到action。action通過(guò)commit把對(duì)應(yīng)參數(shù)同步提交到mutation亚亲,mutation會(huì)修改state中對(duì)應(yīng)的值彻采。最后通過(guò)getter把對(duì)應(yīng)值跑出去,在頁(yè)面的計(jì)算屬性中朵栖,通過(guò)颊亮,mapGetter來(lái)動(dòng)態(tài)獲取state中的值
在vue組件中可以直接通過(guò)this.$store 來(lái)操作
vuex有哪幾種屬性
有五種,分別是State , Getter , Mutation , Action , Module (就是mapAction)
- state:vuex的基本數(shù)據(jù),用來(lái)存儲(chǔ)變量
- geeter:從基本數(shù)據(jù)(state)派生的數(shù)據(jù)陨溅,相當(dāng)于state的計(jì)算屬性,對(duì)state數(shù)據(jù)進(jìn)行封裝轉(zhuǎn)換之后再輸出
- mutation:提交更新數(shù)據(jù)的方法终惑,必須是同步的(如果需要異步使用action)。每個(gè)mutation 都有一個(gè)字符串的 事件類型 (type) 和 一個(gè) 回調(diào)函數(shù) (handler)门扇”⒂校回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方,并且它會(huì)接受 state 作為第一個(gè)參數(shù)臼寄,提交載荷作為第二個(gè)參數(shù)霸奕。
- action:和mutation的功能大致相同,不同之處在于 ==》1. Action 提交的是 mutation吉拳,而不是直接變更狀態(tài)质帅。 2. Action 可以包含任意異步操作。
- modules:模塊化vuex留攒,可以讓每一個(gè)模塊擁有自己的state煤惩、mutation、action炼邀、getters,使得結(jié)構(gòu)非常清晰魄揉,方便管理。
- actions與mutations作用類似拭宁,都是可以對(duì)狀態(tài)進(jìn)行修改洛退。不同的是actions是異步操作的瓣俯。actions是可以調(diào)用Mutations里的方法的。
dispatch:異步操作兵怯,寫(xiě)法: this.store.commit('mutations方法名',值)
Vuex中actions和mutations的區(qū)別
Mutation 更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation
Vuex 中的 mutation 非常類似于事件:每個(gè) mutation 都有一個(gè)字符串的 事件類型 (type) 和 一個(gè) 回調(diào)函數(shù) (handler)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方摇零,并且它會(huì)接受 state 作為第一個(gè)參數(shù)
Action Action 類似于 mutation推掸,不同在于:
- Action 提交的是 mutation,而不是直接變更狀態(tài)驻仅。
- Action 可以包含任意異步操作谅畅。 .
什么是mvvm模式,談?wù)勀愕睦斫猓?/h3>
MVVM - Model View ViewModel噪服,數(shù)據(jù)毡泻,視圖,視圖模型
view 可以通過(guò) 事件綁定 的方式影響 model
model 可以通過(guò) 數(shù)據(jù)綁定 的形式影響到view粘优,
viewModel是把 model 和 view 連起來(lái)的橋梁仇味,這樣就實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定。
請(qǐng)談?wù)勀銓?duì)vue.js 生命周期的理解雹顺?
MVVM - Model View ViewModel噪服,數(shù)據(jù)毡泻,視圖,視圖模型
view 可以通過(guò) 事件綁定 的方式影響 model
model 可以通過(guò) 數(shù)據(jù)綁定 的形式影響到view粘优,
viewModel是把 model 和 view 連起來(lái)的橋梁仇味,這樣就實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定。
1.什么是vue.js的生命周期:Vue 實(shí)例有一個(gè)完整的生命周期丹墨,也就是從開(kāi)始創(chuàng)建、初始化數(shù)據(jù)嬉愧、編譯模版贩挣、掛載 Dom -> 渲染、更新 -> 渲染没酣、卸載等一系列過(guò)程王财,我們稱這是 Vue 的生命周期。
2.各個(gè)生命周期的作用
為什么vue中組件里面的data是一個(gè)函數(shù)而不是一個(gè)對(duì)象呢裕便?
因?yàn)榻M件可能被用來(lái)創(chuàng)建多個(gè)實(shí)例绒净,如果data仍然是一個(gè)純粹的對(duì)象,則所有的實(shí)例將共享引用一個(gè)數(shù)據(jù)對(duì)象偿衰,通過(guò)提供data函數(shù)挂疆,每次創(chuàng)建一個(gè)新的實(shí)例之后,我們能夠調(diào)用data函數(shù)從而返回一個(gè)全新的副本數(shù)據(jù)對(duì)象下翎,這樣每一個(gè)實(shí)例都有自己私有的數(shù)據(jù)空間不會(huì)互相影響
vue事件修飾符以及各個(gè)的作用囱嫩?
.stop:阻止事件冒泡
.native:綁定原生事件
.once:事件只執(zhí)行一次
.self 將事件綁定在自身身上,相當(dāng)于阻止事件冒泡
.prevent:阻止默認(rèn)事件
.passive: 2.3.0 新增,滾動(dòng)事件的默認(rèn)行為 (即滾動(dòng)行為) 將會(huì)立即觸發(fā),不能和.prevent 一起使用
vue如何優(yōu)化頁(yè)面加載漏设?
1.UI組件庫(kù)盡量使用cdn的方式引入,或者下載本地通過(guò)js文件引入;
2.配置路由懶加載的方式今妄;
3.增加loading圖,提升用戶體驗(yàn)
父組件和子組件生命周期執(zhí)行的順序郑口?
1.加載渲染過(guò)程:
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate
-> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
2.子組件更新過(guò)程:
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
3.父組件更新過(guò)程:
父 beforeUpdate -> 父 updated
4.銷毀過(guò)程:
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
獲取dom節(jié)點(diǎn)的方式
案例解析
DOM 是一個(gè)樹(shù)形結(jié)構(gòu)鸳碧,操作一個(gè)DOM節(jié)點(diǎn),實(shí)際上就是這幾個(gè)操作:更新犬性、刪除瞻离、添加、遍歷
在操作DOM節(jié)點(diǎn)之前乒裆,需要通過(guò)各種方式先拿到這個(gè)DOM節(jié)點(diǎn)套利,常用的方法有:
一、通過(guò)元素類型的方法來(lái)操作:
- document.getElementById();//id名鹤耍,在實(shí)際開(kāi)發(fā)中較少使用肉迫,選擇器中多用class id一般只用在頂級(jí)層存在 不能太過(guò)依賴id
- document.getElementsByTagName();//標(biāo)簽名
- document.getElementsByClassName();//類名
- document.getElementsByName();//name屬性值,一般不用
- document.querySelector();//css選擇符模式稿黄,返回與該模式匹配的第一個(gè)元素喊衫,結(jié)果為一個(gè)元素;如果沒(méi)找到匹配的元素杆怕,則返回null
- document.querySelectorAll()//css選擇符模式族购,返回與該模式匹配的所有元素,結(jié)果為一個(gè)類數(shù)組
二陵珍、根據(jù)關(guān)系樹(shù)來(lái)選擇(遍歷節(jié)點(diǎn)樹(shù)):
【先簡(jiǎn)單介紹一下節(jié)點(diǎn):
DOM(文檔對(duì)象模型)可以將任何HTML寝杖、XML文檔描繪成一個(gè)多層次的節(jié)點(diǎn)樹(shù)。所有的頁(yè)面都表現(xiàn)為以一個(gè)特定節(jié)點(diǎn)為根節(jié)點(diǎn)的樹(shù)形結(jié)構(gòu)互纯。html文檔中根節(jié)點(diǎn)為document節(jié)點(diǎn)瑟幕。
所有節(jié)點(diǎn)都有nodeType屬性,代表節(jié)點(diǎn)的不同類型伟姐,通過(guò)nodeType屬性可以來(lái)判斷節(jié)點(diǎn)的類型收苏。經(jīng)常使用的節(jié)點(diǎn)主要有以下幾種類型:
Element類型(元素節(jié)點(diǎn)):nodeType值為 1
Text類型(文本節(jié)點(diǎn)):nodeType值為 3
Comment類型(注釋節(jié)點(diǎn)):nodeType值為 8
Document類型(document節(jié)點(diǎn)):nodeType值為 9;其規(guī)定的一些常用的屬性有
document.body document.head 分別為HTML中的 <body><head>
document.documentElement為<html>標(biāo)簽
所有的節(jié)點(diǎn)都有 hasChildNodes()方法 判斷有無(wú)子節(jié)點(diǎn) 有一個(gè)或多個(gè)子節(jié)點(diǎn)時(shí)返回true】
通過(guò)一些屬性可以來(lái)遍歷節(jié)點(diǎn)樹(shù):
parentNode//獲取所選節(jié)點(diǎn)的父節(jié)點(diǎn)愤兵,最頂層的節(jié)點(diǎn)為#document
childNodes //獲取所選節(jié)點(diǎn)的子節(jié)點(diǎn)們
firstChild //獲取所選節(jié)點(diǎn)的第一個(gè)子節(jié)點(diǎn)
lastChild //獲取所選節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn)
nextSibling //獲取所選節(jié)點(diǎn)的后一個(gè)兄弟節(jié)點(diǎn) 列表中最后一個(gè)節(jié)點(diǎn)的nextSibling屬性值為null
previousSibling //獲取所選節(jié)點(diǎn)的前一兄弟節(jié)點(diǎn) 列表中第一個(gè)節(jié)點(diǎn)的previousSibling屬性值為null
由于文檔中的節(jié)點(diǎn)類型較多鹿霸,遍歷子節(jié)點(diǎn)的結(jié)果很多時(shí)候并不能得到我們想要的結(jié)果,使用遍歷元素節(jié)點(diǎn)則很方便
三秆乳、基于元素節(jié)點(diǎn)樹(shù)的遍歷(遍歷元素節(jié)點(diǎn)樹(shù)):
parentElement //返回當(dāng)前元素的父元素節(jié)點(diǎn)(IE9以下不兼容)
children // 返回當(dāng)前元素的元素子節(jié)點(diǎn)
firstElementChild //返回的是第一個(gè)元素子節(jié)點(diǎn)(IE9以下不兼容)
lastElementChild //返回的是最后一個(gè)元素子節(jié)點(diǎn)(IE9以下不兼容)
nextElementSibling //返回的是后一個(gè)兄弟元素節(jié)點(diǎn)(IE9以下不兼容)
previousElementSibling //返回的是前一個(gè)兄弟元素節(jié)點(diǎn)(IE9以下不兼容)
vue獲取dom節(jié)點(diǎn)
在vue項(xiàng)目中懦鼠,獲取dom節(jié)點(diǎn)可以用ref屬性,這個(gè)屬性就是來(lái)獲取dom對(duì)象的屹堰。
<template>
<div class="contaier" ref="box" style="width: 100px;height: 100px;">
這里用來(lái)測(cè)試元素的ref屬性
</div>
<button type="button" @click="showData()">點(diǎn)擊</button>
</template>
<script>
export default {
methods: {
showData() {
console.log(this.$refs.box);
console.log(this.$refs.box.style);
}
}
}
</script>