前面,咱們已經針對前端的基礎知識和常見的一些進階知識都作了總體的梳理,而且也對緩存進行了單獨的具體講解,有須要的朋友可自行查看相關的文章,文章以下:前端常見面試-css篇、前端常見面試-js篇、前端常見面試-進階篇、前端常見面試-存儲/緩存篇
對於前端來講,儘管css、html、js是主要的基礎知識,可是隨着技術的不斷髮展,出現了不少優秀的mv*框架以及小程序框架。所以,對於前端開發者而言,須要對一些前端框架進行熟練掌握。這篇文章咱們一塊兒來聊一聊VUE及全家桶的常見面試問題。javascript
MVVM 是 Model-View-ViewModel的縮寫,即將數據模型與數據表現層經過數據驅動進行分離,從而只須要關係數據模型的開發,而不須要考慮頁面的表現,具體說來以下:
Model表明數據模型:主要用於定義數據和操做的業務邏輯。
View表明頁面展現組件(即dom展示形式):負責將數據模型轉化成UI 展示出來。
ViewModel爲model和view之間的橋樑:監聽模型數據的改變和控制視圖行爲、處理用戶交互。經過雙向數據綁定把 View 層和 Model 層鏈接了起來,而View 和 Model 之間的同步工做徹底是自動的,無需人爲干涉
在MVVM架構下,View 和 Model 之間並無直接的聯繫,而是經過ViewModel進行交互,Model 和 ViewModel 之間的交互是雙向的, 所以View 數據的變化會同步到Model中,而Model 數據的變化也會當即反應到View 上。php
答:總共分爲8個階段,具體爲:建立前/後,載入前/後,更新前/後,銷燬前/後。
建立前/後: 在beforeCreated階段:ue實例的掛載元素\$el和數據對象data都爲undefined,還未初始化;在created階段,vue實例的數據對象data有了,$el尚未。
載入前/後:在beforeMount階段,vue實例的$el和data都初始化了,但仍是掛載以前爲虛擬的dom節點,data.message還未替換;在mounted階段,vue實例掛載完成,data.message成功渲染。
更新前/後:當data變化時,會觸發beforeUpdate和updated方法。
銷燬前/後:在執行destroy方法後,對data的改變不會再觸發周期函數,說明此時vue實例已經解除了事件監聽以及和dom的綁定,可是dom結構依然存在。css
beforeCreate:在new一個vue實例後,只有一些默認的生命週期鉤子和默認事件,其餘的東西都還沒建立,data和methods中的數據都尚未初始化。不能在這個階段使用data中的數據和methods中的方法
create:data 和 methods都已經被初始化好了,若是要調用 methods 中的方法,或者操做 data 中的數據,最先能夠在這個階段中操做
beforeMount:執行到這個鉤子的時候,在內存中已經編譯好了模板了,可是尚未掛載到頁面中,此時,頁面仍是舊的,不能直接操做頁面的dom和獲取dom對象
mounted:執行到這個鉤子的時候,就表示Vue實例已經初始化完成了。此時組件脫離了建立階段,進入到了運行階段。 若是咱們想要經過插件操做頁面上的DOM節點,最先能夠在和這個階段中進行
beforeUpdate: 當執行這個鉤子時,頁面中的顯示的數據仍是舊的,data中的數據是更新後的,頁面尚未和最新的數據保持同步
updated:頁面顯示的數據和data中的數據已經保持同步了,都是最新的
beforeDestory:Vue實例從運行階段進入到了銷燬階段,這個時候上全部的data和 methods、指令、過濾器 ……都是處於可用狀態。尚未真正被銷燬
destroyed: 這個時候上全部的data和methods、指令、過濾器 ……都是處於不可用狀態。組件已經被銷燬了。html
共同點:都能控制元素的顯示和隱藏;
不一樣點:實現本質方法不一樣,v-show本質就是經過控制css中的display設置爲none,控制隱藏,只會編譯一次;v-if是動態的向DOM樹內添加或者刪除DOM元素,若初始值爲false,就不會編譯了。並且v-if不停的銷燬和建立比較消耗性能。
若是要頻繁切換某節點,使用v-show(切換開銷比較小,初始開銷較大)。若是不須要頻繁切換某節點使用v-if(初始渲染開銷較小,切換開銷比較大)。前端
當v-if與v-for一塊兒使用時,v-for具備比v-if更高的優先級,這意味着v-if將分別重複運行於每一個v-for循環中。
因此,不推薦v-if和v-for同時使用。若是v-if和v-for一塊兒用的話,vue中的的會自動提示v-if應該放到外層去vue
須要使用key來給每一個節點作一個惟一標識,Diff算法就能夠正確的識別此節點。主要是爲了高效的更新虛擬DOM。java
1)定義transition時須要設置對應的name,具體語法爲:<transition name=「fade」>須要動畫的內容或者組件或者頁面</transition>
2)過渡動畫主要包含6個class,分別爲:
v-enter:定義元素進入過渡的初始狀態,在元素插入前生效,插入後一幀刪除,
v-enter-active:在元素插入前生效,在動畫完成後刪除,
v-enter-to:在元素插入後一幀生效,在動畫完成後刪除,
v-leave:離開過渡的初始狀態,在元素離開時生效,下一幀刪除
v-leave-active:在離開過渡時生效,在動畫完成後刪除
v-leave-to:離開過渡結束狀態,在離開過渡下一幀生效,在動畫完成後刪除
⚠️:v會轉化爲對應的transition的name值
3)固然咱們也能夠自定義這六個class 能夠直接在transition中設置對應的屬性爲對應的class名稱,屬性有:enter-class,enter-active-class,enter-to-class,leave-class,leave-active-class,leave-to-class
4)在同時使用過渡和css動畫的時候 能夠設置type屬性來制定vue內部機制監聽transitioned或者animationed事件來完成過渡仍是動畫的監聽
5)若是須要設置對應的過渡時間,能夠直接設置屬性duration,能夠直接接收一個數字(單位爲毫秒),也能夠接收一個對象{enter:1000,leave:300}
6)也能夠設置過渡的鉤子函數,具體有:before-enter,enter,after-enter,enter-cancelled,before-leave,leave,after-leave,leave-cancellednode
自定義指令分爲全局指令和組件指令,其中全局指令須要使用directive來進行定義,組件指令須要使用directives來進行定義,具體定義方法同過濾器filter或者其餘生命週期,具體使用方法以下:
全局自定義指令 directive(name,{}),其中name表示定義的指令名稱(定義指令的時候不須要帶v-,可是在調用的時候須要哦帶v-),第二個參數是一個對象,對象中包括五個自定義組件的鉤子函數,具體包括:react
鉤子函數對應的參數el,binding,vnode,oldnode,具體參數講解以下:
a、el指令所綁定的元素 能夠直接操組dom元素
b、binding一個對象,具體包括如下屬性:
1)name:定義的指令名稱 不包括v-
2)value:指令的綁定值,若是綁定的是一個計算式,value爲對應計算結果
3)oldvalue:指令綁定元素的前一個值,只對update和componentUpdated鉤子函數有值
4)expression:指令綁定的原始值 不對值進行任何加工
5)arg:傳遞給指令的參數
6)modifiers:指令修飾符,如:v-focus.show.async 則接收的modifiers爲{show:true,async:true}
c、vnode:vue編譯生成的虛擬dom
d、oldVnode:上一個vnode,只在update和componentUpdated鉤子函數中有效webpack
⚠️:若是不須要其餘鉤子函數,能夠直接簡寫爲:directive(「focus」,function(el,binding){})
vue.js 是採用數據劫持結合發佈者-訂閱者模式的方式,經過Object.defineProperty()來劫持各個屬性的setter,getter,在數據變更時發佈消息給訂閱者,觸發相應的監聽回調。
具體步驟:
第一步:須要observe的數據對象進行遞歸遍歷,包括子屬性對象的屬性,都加上 setter和getter
這樣的話,給這個對象的某個值賦值,就會觸發setter,那麼就能監聽到了數據變化
第二步:compile解析模板指令,將模板中的變量替換成數據,而後初始化渲染頁面視圖,並將每一個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦數據有變更,收到通知,更新視圖
第三步:Watcher訂閱者是Observer和Compile之間通訊的橋樑,主要作的事情是:
一、在自身實例化時往屬性訂閱器(dep)裏面添加本身
二、自身必須有一個update()方法
三、待屬性變更dep.notice()通知時,能調用自身的update()方法,並觸發Compile中綁定的回調,則功成身退。
第四步:MVVM做爲數據綁定的入口,整合Observer、Compile和Watcher三者,經過Observer來監聽本身的model數據變化,經過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通訊橋樑,達到數據變化 -> 視圖更新;視圖交互變化(input) -> 數據model變動的雙向綁定效果。
1)diff算法的做用:用來修改dom的一小段,不會引發dom樹的重繪
2)diff算法的實現原理:diff算法將virtual dom的某個節點數據改變後生成的新的vnode與舊節點進行比較,並替換爲新的節點,具體過程就是調用patch方法,比較新舊節點,一邊比較一邊給真實的dom打補丁進行替換
3)具體過程詳解:
a、在採用diff算法進行新舊節點進行比較的時候,比較是按照在同級進行比較的,不會進行跨級比較:

b、當數據發生改變的時候,set方法會調用dep.notify通知全部的訂閱者watcher,訂閱者會調用patch函數給響應的dom進行打補丁,從而更新真實的視圖
c、patch函數接受兩個參數,第一個是舊節點,第二個是新節點,首先判斷兩個節點是否值得比較,值得比較則執行patchVnode函數,不值得比較則直接將舊節點替換爲新節點。若是兩個節點同樣就直接檢查對應的子節點,若是子節點不同就說明整個子節點所有改變再也不往下對比直接進行新舊節點的總體替換
d、patchVnode函數:找到真實的dom元素;判斷新舊節點是否指向同一個對象,若是是就直接返回;若是新舊節點都有文本節點,那麼直接將新的文本節點賦值給dom元素而且更新舊的節點爲新的節點;若是舊節點有子節點而新節點沒有,則直接刪除dom元素中的子節點;若是舊節點沒有子節點,新節點有子節點,那麼直接將新節點中的子節點更新到dom中;若是二者都有子節點,那麼繼續調用函數updateChildren
e、updateChildren函數:抽離出新舊節點的全部子節點,而且設置新舊節點的開始指針和結束指針,而後進行兩輛比較,從而更新dom(調整順序或者插入新的內容 結束後刪掉多餘的內容)
傳遞參數可使用props,傳遞函數能夠直接在調用子組件的時候傳遞自定義事件,並使用$emit來調用,例如:
//父組件 <div classs="parent"> <child @getinfo="myname" :userinfo="usermessage"></child> <div> export default { data(){ return { usermessage:'我是父親' } }, methods:{ myname(name){ console.log('個人名字叫'+name) } } } //子組件 <div classs="child"> 來源:{{userinfo}} <button @click="getname">顯示個人名字</button> <div> export default { props:['userinfo'], methods:{ getname(){ this.$emit('getinfo','bilibili') } } }
首先創建一個vue實例空白頁(js文件)
import Vue from 'vue' export default new Vue()
組件a(數據發送方)經過使用 $emit 自定義事件把數據帶過去
<template> <div> <span>A組件->{{msg}}</span> <input type="button" value="把a組件數據傳給b" @click ="send"> </div> </template> <script> import vmson from "../../../util/emptyVue" export default { data(){ return { msg:{ a:'111', b:'222' } } }, methods:{ send:function(){ vmson.$emit("aevent",this.msg) } } } </script>
組件b(數據接收方)使用而經過 $on監聽自定義事件的callback接收數據
<template> <div> <span>b組件,a傳的的數據爲->{{msg}}</span> </div> </template> <script> import vmson from "../../../util/emptyVue" export default { data(){ return { msg:"" } }, mounted(){ vmson.$on("aevent",(val)=>{//監聽事件aevent,回調函數要使用箭頭函數; console.log(val);//打印結果:我是a組件的數據 this.msg = val; }) } } </script>
特色:hash雖然在URL中,但不被包括在HTTP請求中;用來指導瀏覽器動做,對服務端安全無用,hash不會重加載頁面。
提供了兩個新方法:pushState(),replaceState()能夠對瀏覽器歷史記錄棧進行修改,以及popState事件的監聽到狀態變動。history 模式下,前端的 URL必須和實際向後端發起請求的URL一致,不然會報404錯誤
輕量級框架:只關注視圖層,是一個構建數據的視圖集合,大小隻有幾十kb;
簡單易學:國人開發,中文文檔,不存在語言障礙 ,易於理解和學習;
雙向數據綁定:保留了angular的特色,在數據操做方面更爲簡單;
組件化:保留了react的優勢,實現了html的封裝和重用,在構建單頁面應用方面有着獨特的優點;
視圖,數據,結構分離:使數據的更改更爲簡單,不須要進行邏輯代碼的修改,只須要操做數據就能完成相關操做;
虛擬DOM:dom操做是很是耗費性能的, 再也不使用原生的dom操做節點,極大解放dom操做,但具體操做的仍是dom不過是換了另外一種方式;
運行速度更快:相比較與react而言,一樣是操做虛擬dom,就性能而言,vue存在很大的優點。
相同點:
React採用特殊的JSX語法,Vue.js在組件開發中也推崇編寫.vue特殊文件格式,對文件內容都有一些約定,二者都須要編譯後使用;中心思想相同:一切都是組件,組件實例之間能夠嵌套;都提供合理的鉤子函數,可讓開發者定製化地去處理需求;都不內置列數AJAX,Route等功能到核心包,而是以插件的方式加載;在組件開發中都支持mixins的特性。
不一樣點:
React採用的Virtual DOM會對渲染出來的結果作髒檢查;Vue.js在模板中提供了指令,過濾器等,能夠很是方便,快捷地操做Virtual DOM。
相同點:
都支持指令:內置指令和自定義指令;都支持過濾器:內置過濾器和自定義過濾器;都支持雙向數據綁定;都不支持低端瀏覽器。
不一樣點:
AngularJS的學習成本高,好比增長了Dependency Injection特性,而Vue.js自己提供的API都比較簡單、直觀;在性能上,AngularJS依賴對數據作髒檢查,因此Watcher越多越慢;Vue.js使用基於依賴追蹤的觀察而且使用異步隊列更新,全部的數據都是獨立觸發的。
vue路由鉤子大體能夠分爲三類:
主要包括beforeEach和aftrEach,beforeEach函數有三個參數:
to:router即將進入的路由對象
from:當前導航即將離開的路由
next:Function,進行管道中的一個鉤子,若是執行完了,則導航的狀態就是 confirmed (確認的);不然爲false,終止導航。
afterEach函數不用傳next()函數這類鉤子主要做用於全局,通常用來判斷權限,以及以及頁面丟失時候須要執行的操做,例如:
//使用鉤子函數對路由進行權限跳轉 router.beforeEach((to, from, next) => { const role = localStorage.getItem('ms_username'); if(!role && to.path !== '/login'){ next('/login'); }else if(to.meta.permission){ // 若是是管理員權限則可進入,這裏只是簡單的模擬管理員權限而已 role === 'admin' ? next() : next('/403'); }else{ // 簡單的判斷IE10及如下不進入富文本編輯器,該組件不兼容 if(navigator.userAgent.indexOf('MSIE') > -1 && to.path === '/editor'){ Vue.prototype.$alert('vue-quill-editor組件不兼容IE10及如下瀏覽器,請使用更高版本的瀏 覽器查看', '瀏覽器不兼容通知', { confirmButtonText: '肯定' }); }else{ next(); } } })
主要用於寫某個指定路由跳轉時須要執行的邏輯
主要包括 beforeRouteEnter和beforeRouteUpdate ,beforeRouteLeave,這幾個鉤子都是寫在組件裏面也能夠傳三個參數(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') } } }) }
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化,具體包括:
1)state:Vuex 使用單一狀態樹,即每一個應用將僅僅包含一個store 實例,但單一狀態樹和模塊化並不衝突。存放的數據狀態,不能夠直接修改裏面的數據。
2)getter:state的計算屬性,相似vue的計算屬性,主要用來過濾一些數據。
3)action:actions能夠理解爲經過將mutations裏面處裏數據的方法變成可異步的處理數據的方法,簡單的說就是異步操做數據。view 層經過 store.dispath 來分發 action。能夠異步函數調用
4)mutation:mutations定義的方法動態修改Vuex 的 store 中的狀態或數據
5)modules:項目特別複雜的時候,可讓每個模塊擁有本身的state、mutation、action、getters,使得結構很是清晰,方便管理。
1)全局過濾器必須寫在vue實例建立以前
Vue.filter('testfilter', function (value,text) { // 返回處理後的值 return value+text })
2)局部寫法:在組件實例對象裏掛載。
filters: { changemsg:(val,text)\=>{ return val + text } },
3)使用方式:只能使用在{{}}和:v-bind中,定義時第一個參數固定爲預處理的數,後面的數爲調用時傳入的參數,調用時參數第一個對應定義時第二個參數,依次日後類推
<h3 :title="test|changemsg(1234)">{{test|changemsg(4567)}}</h3> //多個過濾器也能夠串行使用 <h2>{{name|filter1|filter2|filter3}}</h2>
4)vue-cli項目中註冊多個全局過濾器寫法:
//1.建立一個單獨的文件定義並暴露函數對象 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.導入main.js(在vue實例以前) import filters from './filter/filter.js' //3.循環註冊過濾器 Object.keys(filters).forEach(key=>{ Vue.filter(key,filters[key]) })
keep-alive 是Vue內置的一個組件,可使被包含的組件保留狀態,或避免從新渲染,頁面第一次進入,鉤子的觸發順序:created-> mounted-> activated,退出時觸發 deactivated ,當再次進入(前進或者後退)時,只觸發activated事件掛載的方法等,只執行一次的放在 mounted 中;組件每次進去執行的方法放在 activated 中;其有幾個屬性以下:
1)include - 字符串或正則表達式,只有名稱匹配的組件會被緩存
2)exclude - 字符串或正則表達式,任何名稱匹配的組件都不會被緩存
3)include 和 exclude 的屬性容許組件有條件地緩存。兩者均可以用「,」分隔字符串、正則表達式、數組。當使用正則或者是數組時,要記得使用v-bind 。
<!-- 逗號分隔字符串,只有組件a與b被緩存。 --> <keep-alive include="a,b"> <component></component> </keep-alive> <!-- 正則表達式 (須要使用 v-bind,符合匹配規則的都會被緩存) --> <keep-alive :include="/a|b/"> <component></component> </keep-alive> <!-- Array (須要使用 v-bind,被包含的都會被緩存) --> <keep-alive :include="['a', 'b']"> <component></component> </keep-alive>
根據業務需求,創建組件的模板,先把架子搭起來,寫寫樣式,考慮好組件的基本邏輯。
準備好組件的數據輸入。即分析好邏輯,定好 props 裏面的數據、類型。
準備好組件的數據輸出。即根據組件邏輯,作好要暴露出來的方法。
封裝完畢了,直接調用便可
1)路由懶加載
2)vue-cli開啓打包壓縮 和後臺配合 gzip訪問
3)進行cdn加速
4)開啓vue服務渲染模式
5)用webpack的externals屬性把不須要打包的庫文件分離出去,減小打包後文件的大小
6)在生產環境中刪除掉沒必要要的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; #壓縮級別 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效果,給用戶一種進度感覺
使用 v-cloak 指令設置樣式,這些樣式會在 Vue 實例編譯結束時,從綁定的 HTML 元素上被移除。
通常用於解決網頁閃屏的問題,在對一個的標籤中使用v-cloak,而後在樣式中設置[v-cloak]樣式, [v-cloak]
需寫在 link 引入的css中,或者寫一個內聯css樣式,寫在import
引入的css中不起做用。
答:就是先轉化成AST樹,再獲得的render函數返回VNode(Vue的虛擬DOM節點),具體爲:
首先,經過compile編譯器把template編譯成AST語法樹(abstract syntax tree 即 源代碼的抽象語法結構的樹狀表現形式),compile是createCompiler的返回值,createCompiler是用以建立編譯器的。另外compile還負責合併option。
而後,AST會通過generate(將AST語法樹轉化成render funtion字符串的過程)獲得render函數,render的返回值是VNode,VNode是Vue的虛擬DOM節點,裏面有(標籤名、子節點、文本等等)
答:v-model用於表單數據的雙向綁定,其實它就是一個語法糖,這個背後就作了兩個操做:
1)v-bind綁定一個value屬性;
2)v-on指令給當前元素綁定input事件
1)變量不在 data中定義,而是定義在computed中,寫法跟寫方法同樣,有返回值。函數名直接在頁面模板中渲染,不加小括號 。
2)根據傳入的變量的變化 進行結果的更新。
3)計算屬性基於響應式依賴進行緩存。如其中的任意一個值未發生變化,它調用的就是上一次計算緩存的數據,所以提升了程序的性能。而methods中每調用一次就會從新計算一次,爲了進行沒必要要的資源消耗,選擇用計算屬性。
1)計算屬性的時候 初始化的時候就能夠被監聽到而且計算 可是watch是發生改變的時候纔會觸發。
2)當有一些數據須要隨着其它數據變更而變更時,或者當須要在數據變化時執行異步或開銷較大的操做時,使用 watch。
1)計算屬性變量在computed中定義,屬性監聽在data中定義。
2)計算屬性是聲明式的描述一個值依賴了其餘值,依賴的值改變後從新計算結果更新DOM。屬性監聽的是定義的變量,當定義的值發生變化時,執行相對應的函數。
答:在vue中理解修改數據後,對應的dom須要必定的時間進行更新,所以爲了可以準確的後去更新後的dom,能夠採用延遲迴調的方法進行更新dom的獲取,因此出現了$nextTick來進行延遲迴調。即:在下次 DOM 更新循環結束以後執行延遲迴調。在修改數據以後當即使用這個方法,獲取更新後的 DOM。
答:這是有JavaScript的特性所致使,在component中,data必須以函數的形式存在,不能夠是對象。
組建中的data寫成一個函數,數據以函數返回值的形式定義,這樣每次複用組件的時候,都會返回一份新的data,至關於每一個組件實例都有本身私有的數據空間,它們只負責各自維護的數據,不會形成混亂。而單純的寫成對象形式,就是全部的組件實例共用了一個data,這樣改一個全都改了。
通俗一點說就是指只有一個主頁面的應用,瀏覽器一開始要加載全部必須的 html, js, css。全部的頁面內容都包含在這個所謂的主頁面中。但在寫的時候,仍是會分開寫(頁面片斷),而後在交互的時候由路由程序動態載入,單頁面的頁面跳轉,僅刷新局部資源。多應用於pc端。
指一個應用中有多個頁面,頁面跳轉時是整頁刷新
用戶體驗好,快,內容的改變不須要從新加載整個頁面,基於這一點spa對服務器壓力較小;先後端分離;頁面效果會比較炫酷(好比切換頁面內容時的專場動畫)。
不利於seo;導航不可用,若是必定要導航須要自行實現前進、後退。(因爲是單頁面不能用瀏覽器的前進後退功能,因此須要本身創建堆棧管理);初次加載時耗時多;頁面複雜度提升不少。
.stop:等同於JavaScript中的event.stopPropagation(),防止事件冒泡;
.prevent:等同於JavaScript中的event.preventDefault(),防止執行預設的行爲(若是事件可取消,則取消該事件,而不中止事件的進一步傳播);
.capture:與事件冒泡的方向相反,事件捕獲由外到內;
.self:只會觸發本身範圍內的事件,不包含子元素;
.once:只會觸發一次。
答:push();pop();shift();unshift();splice(); sort();reverse()
router是VueRouter的一個對象,經過Vue.use(VueRouter)和VueRouter構造函數獲得一個router的實例對象,這個對象中是一個全局的對象,他包含了全部的路由包含了許多關鍵的對象和屬性,常見的有:
1)push:向 history 棧添加一個新的記錄,當咱們點擊瀏覽器的返回按鈕時能夠看到以前的頁面
// 字符串 this.$router.push('home') // 對象 this.$router.push({ path: 'home' }) // 命名的路由 this.$router.push({ name: 'user', params: { userId: 123 }}) // 帶查詢參數,變成 /register?plan=123 this.$router.push({ path: 'register', query: { plan: '123' }})
2)go:頁面路由跳轉 前進或者後退
// 頁面路由跳轉 前進或者後退 this.$router.go(-1) // 後退
3)replace:push方法會向 history 棧添加一個新的記錄,而replace方法是替換當前的頁面,不會向 history 棧添加一個新的記錄
$route對象表示當前的路由信息,包含了當前URL解析獲得的信息。包含當前的路徑、參數、query對象等。
1)$route.path:字符串,對應當前路由的路徑,老是解析爲絕對路徑,如 "/foo/bar"。
2)$route.params:一個 key/value 對象,包含了 動態片斷 和 全匹配片斷,若是沒有路由參數,就是一個空對象。
3)$route.query:一個 key/value 對象,表示 URL 查詢參數。例如,對於路徑 /foo?user=1,則有 $route.query.user == 1,若是沒有查詢參數,則是個空對象。
4)$route.hash:當前路由的 hash 值 (不帶#) ,若是沒有 hash 值,則爲空字符串。
5.$route.fullPath:完成解析後的 URL,包含查詢參數和 hash 的完整路徑。
6$route.matched:數組,包含當前匹配的路徑中所包含的全部片斷所對應的配置參數對象。
7.$route.name:當前路徑名字
8.$route.meta:路由元信息
vue異步組件技術 ==== 異步加載
vue-router配置路由 , 使用vue的異步組件技術 , 能夠實現按需加載 。可是,這種狀況下一個組件生成一個js文件
/* vue異步組件技術 */ { path: '/home', name: 'home', component: resolve => require(['@/components/home'],resolve) },{ path: '/index', name: 'Index', component: resolve => require(['@/components/index'],resolve) },{ path: '/about', name: 'about', component: resolve => require(['@/components/about'],resolve) }
路由懶加載(使用import)
// 下面2行代碼,沒有指定webpackChunkName,每一個組件打包成一個js文件。 /* const Home = () => import('@/components/home') const Index = () => import('@/components/index') const About = () => import('@/components/about') */ // 下面2行代碼,指定了相同的webpackChunkName,會合並打包成一個js文件。 把組件按組分塊 const Home = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/home') const Index = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/index') const About = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/about')
{ path: '/about', component: About }, { path: '/index', component: Index }, { path: '/home', component: Home }
vue-router配置路由,使用webpack的require.ensure技術,也能夠實現按需加載。這種狀況下,多個路由指定相同的chunkName,會合並打包成一個js文件。
/* 組件懶加載方案三: webpack提供的require.ensure() */ { path: '/home', name: 'home', component: r => require.ensure([], () => r(require('@/components/home')), 'demo') }, { path: '/index', name: 'Index', component: r => require.ensure([], () => r(require('@/components/index')), 'demo') }, { path: '/about', name: 'about', component: r => require.ensure([], () => r(require('@/components/about')), 'demo-01') }
答:delete只是被刪除的元素變成了 empty/undefined 其餘的元素的鍵值仍是不變。Vue.delete 直接刪除了數組 改變了數組的鍵值。
使用location.href='/url'來跳轉,簡單方便,可是刷新了頁面;
使用路由方式跳轉,無刷新頁面,靜態跳轉;
在子組件內使用特殊的<slot>元素就能夠爲這個子組件開啓一個slot(插槽),在父組件模板裏,插入在子組件標籤內的全部內容將替代子組件的<slot> 標籤及它的內容。
簡單說來就是:在子組件內部用 <slot></slot>標籤佔位,當在父組件中使用子組件的時候,咱們能夠在子組件中插入內容,而這些插入的內容則會替換 <slot></slot>標籤的位置
固然:單個solt的時候能夠不對solt進行命名,若是存在多個 則一個能夠不命名,其餘必須命名,在調用的時候指定名稱的對應替換slot,沒有指定的則直接默認無名稱的solt
觸發當前實例上的自定義事件(並將附加參數都傳給監聽器回調)
監聽實例上自定義事件並調用回調函數,監聽emit觸發的事件
監聽一個自定義事件,可是隻觸發一次,在第一次觸發以後移除監聽器。
用來移除自定義事件監聽器。若是沒有提供參數,則移除全部的事件監聽器;若是隻提供了事件,則移除該事件全部的監聽器;若是同時提供了事件與回調,則只移除這個回調的監聽器。
這四個方法的實現原理是:經過對vue實例掛載,而後分別使用對象存儲數組對應的函數事件,其中emit經過循環查找存儲的數組中對應的函數進行調用,once只匹配一次就就結束,on是將對應的函數存儲到數組中,off是刪除數組中指定的元素或者全部的元素事件。具體能夠參考文章:VUE $on/$emit實現
能夠用來獲取vue的根實例,好比在簡單的項目中將公共數據放再vue根實例上(能夠理解爲一個全局 store ),所以能夠代替vuex實現狀態管理;
在子組件上使用ref特性後,this.$refs屬性能夠直接訪問該子組件。能夠代替事件$emit 和$on 的做用。使用方式是經過ref特性爲這個子組件賦予一個ID引用,再經過this.\$refs.testId獲取指定元素。注意:\$refs只會在組件渲染完成以後生效,而且它們不是響應式的。這僅做爲一個用於直接操做子組件的「逃生艙」——你應該避免在模板或計算屬性中訪問\$refs。
$parent 屬性能夠用來從一個子組件訪問父組件的實例,能夠替代將數據以 prop 的方式傳入子組件的方式;當變動父級組件的數據的時候,容易形成調試和理解難度增長;
答:在編寫樣式中,若是須要防止樣式的污染,可使用兩種方式,一種是在組件的根元素上增長一個惟一的class或者id,而後在編寫組件的樣式時候在根元素對應的class或者id下進行編寫;另外一種方式是在對應的style上添加scoped關鍵字,不過該關鍵字對引用的框架UI無效
答:不起做用的緣由是由於轉碼編譯的問題,可使用babel來進行處理,安裝babel polypill插件解決
答:這是由於vue尚未解析的狀況下會容易出現花屏現象,看到相似於{{data}}的字樣,可使用兩種方式來進行處理,一種爲:在設置index.html的根元素的元素的樣式爲display:none,而後在mounted中的$nextTick函數中display:block展現;另外一種方式是使用vue的內置指令:v-cloak,而且在css中設置樣式
[v-cloak] { display: none; }
答:使用@click.native來進行調用原生的js事件。緣由:router-link會阻止click事件,.native指直接監聽一個原生事件。