1. 程式人生 > 其它 >VUE面試題系列02

VUE面試題系列02

VUE面試題系列02,前端面試題

16、動態路由傳參2種方式params與query

1)、params

宣告式:
<router-link :to="{ name: 'user', params: { id: 123 }}">User</router-link>
程式設計式:
$router.push({ name: 'user', params: { id: '123' }})

//模板裡的寫法:
$route.params.引數名
 
//腳本里的寫法:
this.$route.params.引數名

動態路由匹配也行。
1)、路由配置:{ path: '/user/:id', component: User }
2)、傳參:
//宣告式

使用者01001的資訊 //程式設計式 $router.push("/user/01001");
3)、接值:
//模板裡的寫法: $route.params.引數名
//腳本里的寫法: this.$route.params.引數名

2)、query

傳:

// 帶查詢引數,變成 /register?plan=private
$router.push({ path: '/register', query: { plan: 'private' }})
注意:如果提供了 path,那麼params 會被忽略

接:

 //模板裡的寫法:
 $route.query.引數名 
 //腳本里的寫法:
 this.$route.query.引數名

17、vue例項和vue元件寫法的區別

1、 data是個函式(面試題) 一個元件的 data 選項必須是一個函式,且要有返回object,只有這樣,每個例項(vue元件物件)就可以維護一份被返回物件的獨立的拷貝,否則元件複用時,資料相互影響,也就是說,元件的作用域是獨立的。

2、元件模板(html程式碼)只能有一個根標籤

3、元件名不可和html官方的標籤名同名

4、元件沒有el選項,只有根例項存在el

5、書寫:元件名如果駝峰,那麼使用時,用短橫線(羊肉串的寫法)

18、談談你對vueX的理解

1、vueX是幹什麼的

vuex能夠儲存全域性資料,供整個應用使用,可以在元件之間傳遞資料。

vuex儲存的資料是響應式的

vuex儲存的資料可以跟蹤狀態的變化

2、vueX的核心概念

state : 資料倉庫 ,儲存所有的 共享資料 ,相當於vue元件裡的data getter : 在state的基礎上 派生的資料, 相當於vue元件裡 computed mutation:修改state的資料時,用mutation,這與跟蹤狀態 有關係 action:解決mutation裡只能有同步程式碼的問題,action裡可以有非同步程式碼

3、vueX的資料流

元件裡 dispatch(派發)vueX中的 action,action裡commit(提交)mutation,mutation裡修改state。state被修改後,會響應式到元件上。

19、vue路由懶載入

vue的SPA(Single Page Application)應用裡,當(webpack)打包構建時,會把所有的js打在一起,JavaScript 包會變得非常大,並在第一次請求時全部下載完畢,影響頁面載入(效能)。如果我們能把不同路由對應的元件分割成不同的程式碼塊,然後當路由被訪問的時候才載入對應元件,這樣就更加高效了。

目前有三種方式實現路由元件的懶載入,分別是:

  • vue非同步元件

  • es 的 import()

  • webpack的require.ensure()

1)、 vue非同步元件

把路由配置,進行修改

{
​
    path: '/shopcar',
​
    name: 'shopcar',
​
    component: resolve => require(['@/pages/ShopCar'],resolve)
​
},

1)、執行是開啟chrome的network,就會看到進入路由 /shopcar 時,會多出另外 一個js檔案。一般是0.js或者1.js

2)、用npm run build打包時,wepback就會多打了一個 js檔案(如:0.b5a82d6947b2e30edcc8.js),這個js檔案就是把ShopCar檔案進行了單獨打包。同樣的在network裡,就會看到進入路由 /shopcar 時,多出一個單獨的js檔案的請求

注:這種方式,webpack會把每個非同步元件單獨打成一個js檔案。

2)、es的import()

主要是把原來的引入方式進行修改 ,路由配置就不用改了:

1、不指定webpackChunkName,每個元件單獨打一個js檔案

原來是:import ShopCar from '@/pages/ShopCar'

修改後:const ShopCar = () => import('@/pages/ShopCar');

修改後的做法是定義了一個函式,由於函式不呼叫不執行,所有,一開始時,並不會引入該元件,只有路由跳轉時才會呼叫該函式。

2、指定webpackChunkName,相同的webpackChunkName就會打在同一個js檔案裡

1)、以下兩個元件的webpackChunkName相同,所以,打在一個js檔案裡

const ShopCar = () => import(/* webpackChunkName: 'demot' */ '@/pages/ShopCar');
​
const GoodsDetailPage = () => import(/* webpackChunkName: 'demot' */ '@/pages/GoodsDetailPage');

2)、下面這個元件的webpackChunkName和上面兩個不一樣,所以,單獨打在一個js檔案裡

const Login = () => import(/* webpackChunkName: 'demoty' */ '@/pages/Login');

3)、webpack的require.ensure()

這種方式,只改路由配置即可。

如:

{
​
    path: '/GoodsDetailPage',
​
    name: 'GoodsDetailPage',
​
    component: r => require.ensure([], () => r(require('@/pages/GoodsDetailPage')), 'demot')
​
},
​
{
​
    path: '/Login',
​
    name: 'Login',
​
    component: r => require.ensure([], () => r(require('@/pages/Login')), 'demot')
​
},
​
{
​
    path: '/shopcar',
​
    name: 'shopcar',
    
    component: r => require.ensure([], () => r(require('@/pages/ShopCar')), 'demoty')
​
},

以上程式碼中,我把Login和GoodsDetailPage使用了相同的chunkName

20、MV*(MVC,MVP,MVVM)

答:

這是專案的架構模式。優點:耦合度低、重用性高、生命週期成本低、部署快、可維護性高、有利軟體工程化管理。

1、MVC是從後端演變後的專案架構模式。

M:model,模型,主要完成業務功能,在資料庫相關的專案中,資料庫的增刪改查屬於模型(重點)。 V:view,檢視,主要負責資料的顯示 C:controller,控制器,主要負責每個業務的核心流程,在專案中體現在路由以及中介軟體上。

2、MVP

MVP是由MVC演變過來的。

P:Presenter 代替裡C。

在MVP中View並不直接使用Model,而在MVC中View可以繞過Controller從直接Model中讀取資料。

3、MVVM

MVVM是Model-View-ViewModel的縮寫,MVVM模式把Presenter改名為ViewModel,基本與MVP模式相似。 唯一區別是:MVVM採用資料雙向繫結的方式

在做vue的開發時,程式設計師寫的程式碼和vue框架本身合起來是屬於MVVM模式。

21、你瞭解Vue.js嗎?

這種題,一般是比較難以回答的,問得很模糊,

如果不想多說,那就直接回答:瞭解並做過五個專案。

如果想回答詳細的話,參考思路如下:

1)、vueJS是基於MVVM的JS框架

2)、有(常見的)13個指令:

3)、有(常見的)8個配置項:el,data,computed,watch,components,filter,directives,mixins

4)、vue例項生命週期分為四個階段,八個生命週期函式

5)、vue做專案時會用到的全家桶技術:vueJS框架,vueX,vue-router,aixos,vant元件庫等等

6)、我用vue框架一共做過五個專案。

22、vue-router的兩種路由模式的區別

路由模式分為兩種:hash和history;通過設定vueRouter物件的mode屬性來完成修改。

區別:

1)、外觀上

hash模式時,路徑上有#。

history模式時,路徑上沒有#。

2)、原理上

hash模式通過修改location.href來完成

使用錨點連線的思路,使用hash模式不會給後端發請求。當然,在hash值變化時,會同時觸發window物件的onhashchange事件,並可以通過事件物件的oldURL屬性和newURL屬性 得到新舊URL。


<body>
    <div>
        <a href="#p01" >p01</a><br/>
        <a href="#p02" >p02</a><br/>
        <a href="#p03" >p03</a>
    </div>
    <br/><br/><br/><br/><br/><br/>
    <a name="p01">我是第一個p</a>
    <br/><br/><br/><br/><br/><br/>
    <a name="p02">我是第二個p</a>
    <br/><br/><br/><br/><br/><br/>
    <a name="p03">我是第三個p</a>
    <br/><br/><br/><br/><br/><br/>
</body>
</html>
<script>
window.onhashchange = function(event){
    console.log("舊url",event.oldURL);
    console.log("新的url",event.newURL);
}
</script>

2)、通過修改history.pushState來完成

window.history.pushState(null,null,"p01.html");
window.location.reload();//想測試的話,儘量加上這句話,要不然,地址變了,但是頁面並沒有出現。

history模式會給後端發請求(如果重新整理當前頁面的話),一旦,後端和前端提供了同樣的路徑,那麼,瀏覽器的請求結果就會有問題,到底是後端的資源還是前端的資源(不同的後端處理思路不停),還好,我們一般在後端apiserver的請求路徑的前面習慣性的有個 /api。

所以,由於不同服務端的處理思路不同。所以,需要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面(單頁面),這個頁面就是你 app 依賴的頁面。否則,就會返回404。

你可以改成history的模式,測試一下,如果重新整理當前頁面,那麼,瀏覽器會朝後端傳送請求(給當前路徑)。

23、Vue路由守衛的三種方式,及其鉤子函式和引數

1)、全域性守衛

全域性守衛有前置守衛和後置守衛,是vueRouter物件的兩個鉤子函式,分別是 beforeEach和afterEach。

前置守衛:

router.beforeEach((to, from, next) => {
    //  to: 目標路由
    //  from: 當前路由
​
    // next() 跳轉  一定要呼叫
    next(false);//不讓走
    next(true);//繼續前行
    next('/login')//走哪
    next({path:'/detail/2',params:{},query:{}})//帶點貨
 }

後置守衛:

router.afterEach((to,from)=>{
  //全域性後置守衛業務
})

如果能夠回答上過程,肯定有加分:

//過程:
1、請求一個路徑:如:/Index
2、經歷前置守衛 決定了能去哪個路徑
3、根據去的路徑,找對應component(路由配置)
4、經過後置守衛 5、建立元件

2)、路由獨享守衛

寫在路由配置裡。鉤子函式名:beforeEnter,只有前置守衛

如:

// src/router/index.js
{
  path: '/user',
  component: User,
  beforeEnter: (to,from,next)=>{ //路由獨享守衛 前置 
    console.log('路由獨享守衛');
    if(Math.random()<.5){
      next()
    }else{
      next('/login')
    }
  }
 }

3)、元件內部守衛

寫在元件物件裡。分別有前置守衛,後置守衛,路由改變守衛(當前元件被複用的情況,不是路徑改變)三個鉤子函式。

export default{
    data(){return {}}
    ……………………  
​
    //元件內部鉤子
    beforeRouteEnter (to, from, next) {//前置
      // 不!能!獲取元件例項 `this`
      // 因為當守衛執行前,元件例項還沒被建立
    },
    beforeRouteUpdate (to, from, next) {
      // 在當前路由改變,但是該元件被複用時呼叫
      // 舉例來說,對於一個帶有動態引數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
      // 由於會渲染同樣的 Foo 元件,因此元件例項會被複用。而這個鉤子就會在這個情況下被呼叫。
      // 可以訪問元件例項 `this`
    },
    beforeRouteLeave (to, from, next) {//後置
      // 導航離開該元件的對應路由時呼叫
      // 可以訪問元件例項 `this`
    }
}