vue路由面試題

1.mvvm 框架是什么?

定義:M:Model(服務器上的業務邏輯操作)? V:View(頁面)VM:ViewModel(Model與View之間核心樞紐,比如Vue.js)

大體上:vm層(視圖模型層)通過接口從后臺m層(model層)請求數據,vm層繼而和v(view層)實現數據的雙向綁定。

三者關系Model與ViewModel之間的雙向關系

Model通過Ajax通信,發送數據給ViewModel。

ViewModel也可以通過Ajax通信,發送請求給Model。

ViewModel與View之間的雙向關系

ViewModel中的數據改變,可以同時改變View上的顯示內容。

View上的內容改變(比如輸入框中的內容),也可以同時改變ViewModel中對應的數據。

前端框架MVVM出現的最大意義是什么:

mvvm層實現了前后端更好的分離(前端需要的數據只需要請求后端的接口即可)

MVVM 的出現促進了 GUI 前端開發與后端業務邏輯的分離,極大地提高了前端開發效率。

MVVM用接口實現了前后端數據的通信,這樣可以使前后端之間的業務邏輯沒有什么關系。

MVVM在感覺上要比mvc模式前后端要分的更開

前端框架MVVM中的vm層是干嘛的

ViewModel 是由前端開發人員組織生成和維護的視圖數據層。在這一層,前端開發者對從后端獲取的 Model 數據進行轉換處理,做二次封裝,以生成符合 View 層使用預期的視圖數據模型。需要注意的是 ViewModel 所封裝出來的數據模型包括視圖的狀態和行為兩部分,而 Model 層的數據模型是只包含狀態的,比如頁面的這一塊展示什么,那一塊展示什么這些都屬于視圖狀態(展示),而頁面加載進來時發生什么,點擊這一塊發生什么,這一塊滾動時發生什么這些都屬于視圖行為(交互),視圖狀態和行為都封裝在了 ViewModel 里。這樣的封裝使得 ViewModel 可以完整地去描述 View 層。由于實現了雙向綁定,ViewModel 的內容會實時展現在 View 層,這是激動人心的,因為前端開發者再也不必低效又麻煩地通過操縱 DOM 去更新視圖,MVVM 框架已經把最臟最累的一塊做好了,我們開發者只需要處理和維護 ViewModel,更新數據視圖就會自動得到相應更新,真正實現數據驅動開發。看到了吧,View 層展現的不是 Model 層的數據,而是 ViewModel 的數據,由 ViewModel 負責與 Model 層交互,這就完全解耦了 View 層和 Model 層,這個解耦是至關重要的,它是前后端分離方案實施的重要一環。


View一般就是我們平常說的HTML文本的Js模板,里面可以嵌入一些js模板的代碼,比如Mustache,比如jstl類似的模板偽代碼

ViewModule層里面就是我們對于這個視圖區域的一切js可視業務邏輯,舉個例子,比如圖片走馬燈特效,比如表單按鈕點擊提交,這些自定義事件的注冊和處理邏輯都寫在ViewModule里面了

Module就更簡單了,就是對于純數據的處理,比如增刪改查,與后臺CGI做交互


2.vue-router 是什么?它有哪些組件

路由就是SPA(單頁應用)的路徑管理器,適合用于構建單頁面應用。vue的單頁面應用是基于路由和組件的,路由用于設定訪問路徑,并將路徑和組件映射起來。傳統的頁面應用,是用一些超鏈接來實現頁面切換和跳轉的。在vue-router單頁面應用中,則是路徑之間的切換,也就是組件的切換。路由模塊的本質 就是建立起url和頁面之間的映射關系。

SPA(single page application):單一頁面應用程序,只有一個完整的頁面;它在加載頁面時,不會加載整個頁面,而是只更新某個指定的容器中內容。單頁面應用(SPA)的核心之一是: 更新視圖而不重新請求頁面;vue-router在實現單頁面前端路由時,提供了兩種方式:Hash模式和History模式;根據mode參數來決定采用哪一種方式。

1、Hash模式:

vue-router 默認 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,于是當 URL 改變時,頁面不會重新加載。?hash(#)是URL 的錨點,代表的是網頁中的一個位置,單單改變#后的部分,瀏覽器只會滾動到相應位置,不會重新加載網頁,也就是說 #是用來指導瀏覽器動作的,對服務器端完全無用,HTTP請求中也不會不包括#;同時每一次改變#后的部分,都會在瀏覽器的訪問歷史中增加一個記錄,使用”后退”按鈕,就可以回到上一個位置;所以說Hash模式通過錨點值的改變,根據不同的值,渲染指定DOM位置的不同數據

2、History模式:

由于hash模式會在url中自帶#,如果不想要很丑的 hash,我們可以用路由的 history 模式,只需要在配置路由規則時,加入"mode: 'history'",這種模式充分利用 history.pushState API 來完成 URL 跳轉而無須重新加載頁面。

//main.js文件中const router = new VueRouter({ mode: 'history', routes: [...]})

要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。

exportconstroutes = [

{path:"/", name:"homeLink", component:Home}

{path:"/register", name:"registerLink", component: Register},

{path:"/login", name:"loginLink", component: Login},

{path:"*", redirect:"/"}]

此處就設置如果URL輸入錯誤或者是URL 匹配不到任何靜態資源,就自動跳到到Home頁面

常用的形式:

<router-link :to='' class='active-class'> //路由聲明式跳轉 ,active-class是標簽被點擊時的樣式

<router-view>? ? ? ? ? ? ? ? ? //渲染路由的容器

<keep-alive>? ? ? ? ? ? ? ? ? ? //緩存組件


3.active-class 是哪個組件的屬性?

active-class屬于vue-router的樣式方法 當routerlink標簽被點擊時將會應用這個樣式 使用有兩種方法routerLink標簽內使用

<router-link to='/'active-class="active">首頁</router-link>

首頁的active有時會有bug,會一直被應用

為了解決上面的問題,還需加入一個屬性exact,類似也有兩種方式:

在router-link中寫入exact

<router-link to='/'active-class="active"exact>首頁</router-link>

4.怎么定義 vue-router 的動態路由? 怎么獲取傳過來的值

可以通過query ,param兩種方式

區別:?query通過url傳參,刷新頁面還在? ? params刷新頁面不在了

? ? params的類型:

配置路由格式:/router/:id

傳遞的方式:在path后面跟上對應的值

?傳遞后形成的路徑:/router/123

<!-- 動態路由-params -->

//在APP.vue中

? ? <router-link :to="'/user/'+userId" replace>用戶</router-link>? ?

//在index.js

? ? ?{

? ? path: '/user/:userid',

? ? component: User,

? ? },

跳轉方法:

// 方法1:

<router-link :to="{ name: 'users', params: { uname: wade }}">按鈕</router-link>

// 方法2:

this.$router.push({name:'users',params:{uname:wade}})

// 方法3:

this.$router.push('/user/' + wade)

可以通過$route.params.userid 獲取你說傳遞的值

? ?query的類類型

? 配置路由格式:/router,也就是普通配置

? 傳遞的方式:對象中使用query的key作為傳遞方式

? 傳遞后形成的路徑:/route?id=123

<!--動態路由-query -->

//01-直接在router-link 標簽上以對象的形式

<router-link :to="{path:'/profile',query:{name:'why',age:28,height:188}}">檔案</router-link>

/*

? ? 02-或者寫成按鈕以點擊事件形式

? ? <button @click='profileClick'>我的</button>? ?

*/

//點擊事件

profileClick(){

? this.$router.push({

? ? ? ? path: "/profile",

? ? ? ? query: {

? ? ? ? ? name: "kobi",

? ? ? ? ? age: "28",

? ? ? ? ? height: 198

? ? ? ? }

? ? ? });

}

跳轉方法:

// 方法1:

<router-link :to="{ name: 'users', query: { uname: james }}">按鈕</router-link>

// 方法2:

this.$router.push({ name: 'users', query:{ uname:james }})

// 方法3:

<router-link :to="{ path: '/user', query: { uname:james }}">按鈕</router-link>

// 方法4:

this.$router.push({ path: '/user', query:{ uname:james }})

// 方法5:

this.$router.push('/user?uname=' + jsmes)

可以通過$route.query?獲取你說傳遞的值


5.vue-router 有哪幾種導航鉤子?

1、全局守衛:router.beforeEach
使用router.beforeEach注冊一個全局前置守衛:

constrouter=newVueRouter({...})? router.beforeEach((to,from, next) =>{// ...})

當一個導航觸發時,全局前置守衛按照創建順序調用。守衛是異步解析執行,此時導航在所有守衛resolve 完之前一直處于等待中。

每個守衛方法接收三個參數:

to: Route: 即將要進入的目標 路由對象

from: Route: 當前導航正要離開的路由

next: Function: 一定要調用該方法來resolve這個鉤子。執行效果依賴 next 方法的調用參數。

next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是confirmed(確認的)。

next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到 from 路由對應的地址。

next('/') 或者 next({ path: '/' }): 跳轉到一個不同的地址。當前的導航被中斷,然后進行一個新的導航。你可以向next 傳遞任意位置對象,且允許設置諸如replace: true、name: 'home' 之類的選項以及任何用在router-link的to prop或router.push中的選項。

next(error): (2.4.0+) 如果傳入 next 的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給router.onError()注冊過的回調。

確保要調用next方法,否則鉤子就不會被 resolved。

2、全局解析守衛:router.beforeResolve

你可以用?router.beforeResolve?注冊一個全局守衛。這和?router.beforeEach?類似,區別是:在導航被確認之前,同時在所有組件內守衛和異步路由組件被解析之后,解析守衛就被調用。

3、全局后置鉤子:router.afterEach

你也可以注冊全局后置鉤子,然而和守衛不同的是,這些鉤子不會接受 next 函數也不會改變導航本身:

router.afterEach((to,from) =>{// ...})

4、路由獨享的守衛:beforeEnter

constrouter=newVueRouter({routes:[{path:'/foo',component: Foo,beforeEnter:(to,from, next) =>{// ...}}]})

這些守衛與全局前置守衛的方法參數是一樣的。

5、組件內的守衛:beforeRouteEnter、beforeRouteUpdate (2.2 新增)、beforeRouteLeave

const Foo={ template: `...`,?

beforeRouteEnter(to, from,next){

//在渲染該組件的對應路由被 confirm 前調用

//不!能!獲取組件實例 `this`//因為當守衛執行前,組件實例還沒被創建

},

//不過,你可以通過傳一個回調給next來訪問組件實例。

//在導航被確認的時候執行回調,并且把組件實例作為回調方法的參數。

?beforeRouteEnter(to, from,next){next(vm=>{//通過 `vm` 訪問組件實例})},?

beforeRouteUpdate(to, from,next){

//在當前路由改變,但是該組件被復用時調用//舉例來說,對于一個帶有動態參數的路徑/foo/:id,在/foo/1和/foo/2之間跳轉的時候,

//由于會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。

//可以訪問組件實例 `this`},?

?beforeRouteLeave(to, from,next){

//導航離開該組件的對應路由時調用

//可以訪問組件實例 `this`}}

注意:beforeRouteEnter是支持給next 傳遞回調的唯一守衛。對于beforeRouteUpdate和beforeRouteLeave來說,this已經可用了,所以不支持傳遞回調,因為沒有必要了:

beforeRouteUpdate(to,from, next){// just use `this`this.name= to.params.name

? next()}

離開守衛beforeRouteLeave:通常用來禁止用戶在還未保存修改前突然離開。該導航可以通過next(false)來取消:

beforeRouteLeave(to, from,next){

constanswer= window.confirm('Do you really want to leave? you have unsaved changes!')

if(answer){next()}else{next(false)}}

6.route和router 的區別

1.router是VueRouter的一個對象,通過Vue.use(VueRouter)和VueRouter構造函數得到一個router的實例對象,這個對象中是一個全局的對象,他包含了所有的路由包含了許多關鍵的對象和屬性。

舉例:history對象

$router.push({path:'home'});本質是向history棧中添加一個路由,在我們看來是?切換路由,但本質是在添加一個history記錄

方法:

$router.replace({path:'home'});//替換路由,沒有歷史記錄

2.route是一個跳轉的路由對象,每一個路由都會有一個route對象,是一個局部的對象,可以獲取對應的name,path,params,query等

$route.path

字符串,等于當前路由對象的路徑,會被解析為絕對路徑,如"/home/news"。

$route.params

對象,包含路由中的動態片段和全匹配片段的鍵值對

$route.query

對象,包含路由中查詢參數的鍵值對。例如,對于/home/news/detail/01?favorite=yes,會得到$route.query.favorite == 'yes'。

$route.router

路由規則所屬的路由器(以及其所屬的組件)。

$route.matched

數組,包含當前匹配的路徑中所包含的所有片段所對應的配置參數對象。

$route.name

當前路徑的名字,如果沒有使用具名路徑,則名字為空。

$route.path, $route.params, $route.name, $route.query這幾個屬性很容易理解,主要用于接收路由傳遞的參數



7.vue-router響應路由參數的變化

當使用路由參數時,例如從?/user/aside導航到?/user/foo,原來的組件實例會被復用。因為兩個路由都渲染同個組件,比起銷毀再創建,復用則更加高效。不過,這也意味著組件的生命周期鉤子不會再被調用。

注意:

(1)從同一個組件跳轉到同一個組件。

(2)生命周期鉤子created和mounted都不會調用。

可以使用router的組件內鉤子函數

beforeRouteUpdate(to,from,next){

//在這個鉤子函數中:to表示將要跳轉的路由對象,from表示從哪個路由跳轉過來,next多數就是需要調用

//created和mounted不調用,無法拿到需要的動態值,就通過to.path,to.params等

//可以在這個函數中打印to,具體看to對象有什么可以使用的屬性

}

添加watch監聽

watch: {

// 方法1 //監聽路由是否變化

? '$route' (to, from) {

? if(to.query.id !== from.query.id){

? ? ? ? ? ? this.id = to.query.id;

? ? ? ? ? ? this.init();//重新加載數據

? ? ? ? }

? }

}

//方法 2? 設置路徑變化時的處理函數

watch: {

'$route': {

? ? handler: 'init',

? ? immediate: true

? }

}

為了實現這樣的效果可以給router-view添加一個不同的key,這樣即使是公用組件,只要url變化了,就一定會重新創建這個組件。

<router-view :key="$route.fullpath"></router-view>


8.vue-router實現路由懶加載( 動態加載路由 )

1. vue異步組件技術

vue-router配置路由,使用vue的異步組件技術,可以實現按需加載。

但是,這種情況下一個組件生成一個js文件。

舉例如下:

{path:'/promisedemo',name:'PromiseDemo',component:resolve=>require(['../components/PromiseDemo'],resolve)}

ts文件下需要設置

2. es提案的import()

推薦使用這種方式(需要webpack > 2.4)

webpack官方文檔:webpack中使用import()

vue官方文檔:路由懶加載(使用import())

vue-router配置路由,代碼如下:

// 下面2行代碼,沒有指定webpackChunkName,每個組件打包成一個js文件。

const ImportFuncDemo1 = () => import('../components/ImportFuncDemo1')

const ImportFuncDemo2 = () => import('../components/ImportFuncDemo2')

// 下面2行代碼,指定了相同的webpackChunkName,會合并打包成一個js文件。

// const ImportFuncDemo = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/ImportFuncDemo')

// const ImportFuncDemo2 = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '../components/ImportFuncDemo2')

export default new Router({

routes: [

????????{ path: '/importfuncdemo1', name: 'ImportFuncDemo1', component: ImportFuncDemo1 },

????????{ path: '/importfuncdemo2', name: 'ImportFuncDemo2', component: ImportFuncDemo2 } ]

})

3、webpack提供的require.ensure()

vue-router配置路由,使用webpack的require.ensure技術,也可以實現按需加載。

這種情況下,多個路由指定相同的chunkName,會合并打包成一個js文件。

舉例如下:

{path:'/promisedemo',name:'PromiseDemo',component:resolve=>require.ensure([],()=>resolve(require('../components/PromiseDemo')),'demo')},{path:'/hello',name:'Hello',// component: Hellocomponent:resolve=>require.ensure([],()=>resolve(require('../components/Hello')),'demo')

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。