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)、傳參:

//聲明式 <router-link to="/user/01001">用戶01001的信息</router-link> //編程式 $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`
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章