Vue常見面試題精講【持續更新】

1. v-if和v-show指令有什麼區別?

v-if 是 條件渲染指令,控制的是 組件是否建立(渲染),值爲true則渲染該組件,值爲false則不渲染該組件,對應Html元素則不會存在於瀏覽器的html文檔中,即 打開瀏覽器調試工具找不到該組件對應的渲染結果
v-show控制的是 組件是否可見,而且是 經過css樣式的display屬性來控制組件的顯示與隱藏,因此其值不管是true仍是false,對應Html元素都會存在於瀏覽器的html文檔中,即 打開瀏覽器調試工具都可以找到該組件對應的渲染結果,只不過值爲false的時候, 會在該組件上添加style="display: none;"
須要注意的是,在vue組件開發的時候,即 在.vue中使用v-show的時候當給<style>標籤添加上scoped會致使其中的css優先級變高,此時若是 添加了v-show的元素上同時使用了display樣式,那麼將會致使v-show爲false的時候添加的dispaly:none失效。

2. v-for 與 v-if 的優先級?

可參考v-for與v-if的優先級

v-for比v-if優先級更高,因此不建議v-for和v-if一塊兒使用,若是v-for和v-if同時使用,那麼數據發生變化時,v-for首先會進行遍歷,而後經過v-if進行判斷,這樣 v-for和v-if都會同時執行一遍,對性能和展示不友好。因此 vue建議用計算屬性進行替代,返回過濾後的列表再進行遍歷

3. v-for循環中key有什麼做用?

key的做用主要就是爲了 性能優化,key讓組件具備了惟一性,能讓diff算法更快的找到須要更新的組件dom,在綁定key的時候, 最好是一個惟一的值如item.id 而不能是簡單的index,若是不使用惟一key,那麼在有狀態組件中會出現渲染錯誤。由於它默認用 就地複用策略,若是數據項的順序被改變,那麼 vue將不是移動DOM元素來匹配數據項的改變,而是簡單複用此處每一個元素,不會從新排列元素的位置。若是是使用 key, 它會基於key從新排列元素順序,而且會移除 key 不存在的元素。
簡單說就是, 不使用key就會原地複用,使用key就會對元素位置進行從新排列,可以關聯數據狀態
<template>
  <div class="home">
    <input type="text" v-model="name">
    <button @click="add">添加</button>
    <ul>
      <li v-for="(item, index) in list" :key="item.id"><!--注意,這裏不能使用:key="index"-->
        <input type="checkbox">{{item.name}}
      </li>
    </ul>
  </div>
</template>
<script>
export default {
    data: () => {
        return {
            list: [
              { id: 0, name: 'A' },
              { id: 1, name: 'B' },
              { id: 2, name: 'C' }
            ]
        }
    },
     methods: {
        add() {
          this.list.unshift({ id:3, name:'D'}) // 將D添加到A的前面
        }
  },
}
</script>
若是v-for上不加key,那麼當勾選A前面的複選框後,再點擊添加按鈕,D會添加到A的前面,因爲原地複用原則,不會進行位置的移動,因此第一個位置的複選框是勾選狀態會被繼承到D上,即D會變成勾選狀態而A將失去勾選狀態,這個顯然與原來狀態不符;若是v-for上加上:key="item.id",那麼D添加到A前面以後,A、B、C都會向後移動,而後再將D插入到A的前面,因此插入D後,A仍然保持勾選狀態。

圖片描述
圖片描述

4. vue路由傳參數的三種方式?

query: 直接輸入url地址,url地址上帶上查詢參數,如: http://localhost:8080/home?foo=1 或者 經過路由對象$router調用push()方法進行傳參this.$router.push({path:"/home",query:{"foo":"1"}});而後經過this.$route.query.foo進行獲取傳遞過來的參數javascript

params: 經過路由對象$router調用push()方法進行傳參this.$router.push({name:"home", params:{foo: 1}});而後經過this.$route.params.foo獲取傳遞過來的參數css

動態路由傳參: 路由path位置爲/home/:foo,而後輸入url,如: http://localhost:8080/home/1 而後經過this.$route.params.foo獲取傳遞過來的參數html

5. v-on 經常使用修飾符?

.stop 該修飾符將 阻止事件向上冒泡。同理於調用 event.stopPropagation() 方法,即若是當前元素添加了.stop修飾符,那麼當點擊該元素時候,click事件不會冒泡到其父元素上,即 父元素不會觸發click事件
.prevent 該修飾符會 阻止當前事件的默認行爲。同理於調用 event.preventDefault() 方法,即若是<a href="http://www.baidu.com" @click.prevent="show">鏈接,點擊後默認會跳轉到百度,可是添加上.prevent修飾符以後,就 不會跳轉到百度了而是執行show()方法了
.self 該指令 只有當事件是從事件綁定的元素自己觸發時才觸發回調,即 冒泡事件到達該元素上時並不會觸發事件,可是 其不影響事件繼續向上冒泡其父元素仍然會觸發冒泡事件
.native 就是 給自定義組件的根元素添加一個原生事件,因此其一般用在自定義組件上, 若是給普通的HTML元素添加.native修飾符那麼該HTML元素將沒法監聽到該事件了
.capture 就是 讓事件監聽變成捕獲,默認爲冒泡, 一般用於修飾父元素,若是給父元素添加@click.capture修飾符,那麼當點擊子元素的時候,父元素的click事件將先觸發,而後纔是子元素的click事件。
.once 該修飾符表示綁定的事件 只會被觸發一次

6. 什麼是動態組件?

簡單的說,動態組件就是 將幾個組件放在一個掛載點下,這個掛載點就是 <component>標籤,其須要 綁定is屬性,屬性值爲 父組件中的變量,變量對應的值爲要掛載的組件的組件名,而後根據父組件裏某個變量來動態顯示哪一個,也能夠都不顯示,如:
<template>
  <div class="home">
      <component :is="currentComponent"></component>
  </div>
</template>
<script>
import Tab0 from "@/components/Tab0.vue";
import Tab1 from "@/components/Tab1.vue";
export default {
    data: () => {
        return {
            currentIndex: 0 // 經過改變currentIndex改變要掛載的組件名
        }
    },
    components: {
        "tab-0": Tab0,
        "tab-1": Tab1
    }
    currentComponent() { // 動態計算要掛載的組件的組件名
      return `tab-${this.currentIndex}`; // "tab-0" 、"tab-1"
    }
}
</script>
能夠將動態組件放到<keep-alive>組件內對動態組件進行緩存,這樣動態組件進行切換的時候,就不會每次都從新建立了。
<template>
  <div class="home">
     <keep-alive>
          <component :is="currentComponent"></component>
     </keep-alive>
  </div>
</template>

7. 如何讓CSS只在當前組件中起做用?

將當前組件的<style>修改成<style scoped>

//foo.vuevue

<style scoped>
<!--其中的css樣式只在foo.vue組件起做用-->
</style>

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

vue-router模塊的 router-link組件

9. Vue子組件調用父組件的方法?

子組件須要調用父組件的方法,那麼能夠經過 this.$parent獲取到父組件實例,而後就能夠調用父組件上的方法了。還有一種方法就是, 子組件向父組件emit一個事件父組件在子組件上監聽到該事件後,就能夠調用父組件上的方法了。

10. vue中的 ref 是什麼?

ref 被用來給元素或子組件註冊引用信息,引用信息將會註冊在父組件的 $refs 對象上,即 相似於給組件或者DOM元素上添加一個標識id,而後經過這個標識id拿到對應的DOM元素或組件實例,若是在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;若是用在子組件上,引用就指向組件實例。

11. $route和$router的區別?

$route是" 路由信息對象",包括path,params,hash,query,fullPath,matched,name等路由信息參數。
$router是" 路由實例"對象包括了路由的跳轉方法,鉤子函數等。

12. 怎麼定義組件?

全局定義:調用Vue的component()方法建立, Vue.component(組件名, {template: 模板字符串})
局部定義:在 建立Vue實例時傳遞的options對象中的components對象中進行定義,components:{組件名: {template: 模板字符串}}
單文件組件:在 .vue文件中定義,包含template,script,style三部分。

13. Vue-cli的src文件夾中有哪些文件?

assets文件夾是放 靜態資源
components是放 組件
router是定義 路由相關的配置;
view 視圖
app.vue是一個 應用主組件
main.js是 入口文件

14. 對於MVVM的理解?

MVVM 是 Model-View-ViewModel 的縮寫。
Model表明數據模型,也能夠在Model中定義數據修改和操做的業務邏輯。
View 表明UI 組件,它負責將數據模型轉化成UI 展示出來。
ViewModel 監聽模型數據的改變和控制視圖行爲、處理用戶交互,簡單理解就是一個同步View 和 Model的對象,鏈接Model和View。
在MVVM架構下,View 和 Model 之間並無直接的聯繫,而是經過ViewModel進行交互,Model 和 ViewModel 之間的交互是雙向的, 所以View 數據的變化會同步到Model中,而Model 數據的變化也會當即反應到View 上。
ViewModel 經過雙向數據綁定把 View 層和 Model 層鏈接了起來,而View 和 Model 之間的同步工做徹底是自動的,無需人爲干涉,所以開發者只需關注業務邏輯,不須要手動操做DOM, 不須要關注數據狀態的同步問題,複雜的數據狀態維護徹底由 MVVM 來統一管理。

15. vue等單頁面應用及其優缺點?

優勢:Vue 的目標是經過儘量簡單的 API 實現響應的數據綁定和組合的視圖組件,核心是一個響應的數據綁定系統。MVVM、數據驅動、組件化、輕量、簡潔、高效、快速、模塊友好。
缺點:不支持低版本的瀏覽器,最低只支持到IE9;不利於SEO的優化(若是要支持SEO,建議經過服務端來進行渲染組件);第一次加載首頁耗時相對長一些;不可使用瀏覽器的導航按鈕須要自行實現前進、後退。

16. 路由的跳轉方式?

① <router-link to='/home'> router-link標籤會渲染爲<a>標籤,點擊該a標籤便可跳轉到/home路由;
② 另外一種是經過js跳轉,即經過路由對象this.$router的push()方法進行跳轉, 好比 router.push('/home')

17. 計算屬性(computed)、方法(methods)和偵聽屬性(watch)的區別與使用場景?

methods VS 計算屬性
咱們能夠將同一函數定義爲一個 method 而不是一個計算屬性。對於最終的結果,兩種方式確實是相同的。
然而,不一樣的是計算屬性是基於它們的依賴進行緩存的。計算屬性只有在它的相關依賴發生改變時纔會從新求值。這就意味着只要 message 尚未發生改變,屢次訪問 reversedMessage 計算屬性會當即返回以前的計算結果,而沒必要再次執行函數。
相比而言,只要發生從新渲染,method 調用總會執行該函數。總之,從新計算開銷很大的話請選計算屬性,不但願有緩存的請選methods。
watch VS 計算屬性
當你在模板內使用了複雜邏輯的表達式時,你應當使用計算屬性。
偵聽屬性是一個對象,鍵是須要觀察的表達式,值是對應回調函數。值也能夠是方法名,或者包含選項的對象。
當你有一些數據須要隨着其它數據變更而變更時,或者當須要在數據變化時執行異步或開銷較大的操做時,你可使用 watch。

18. axios是什麼?怎麼使用?

axios是 基於Promise的,用於瀏覽器和nodeJS的http客戶端,主要做用就是 向後臺發送請求。其存在許多優勢:
  • 支持Promise
  • 支持併發請求
  • 提供攔截器
  • 瀏覽器支持防止csrf(跨站請求僞造)

19. axios、fetch、ajax(jquery)的區別?

axios和fetch是基於Promise的,ajax是基於callback的形式。fetch脫離了xhr,是新的語法,默認是不傳cookie的, 監聽不到請求進度

20. vuex是什麼?哪一種功能場景使用它?

vuex是一個專門爲vue構建的狀態機管理機制,它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化,主要 解決組件間數據共享的問題,其實就是 採用相似全局對象的形式來管理全部組件的公共數據,其強調的是集中式管理,主要是爲了便於維護、組件解耦,適合大型項目,有多個視圖組件共同依賴一個狀態的狀況下使用,好比商城系統、外賣系統。
vuex的核心: stategettersmutationsactionsmodules

21. 說出4個vue當中經常使用的指令及其用法?

  • v-if: 這是一個條件渲染指令,表明存在和銷燬,用於控制組件的建立與否;
  • v-bind: 這是一個綁定指令,用於綁定屬性,可簡寫爲冒號;
  • v-on: 這是一個監聽指令,用於監聽事件,可簡寫爲@;
  • v-for: 這是一個循環指令,用於遍歷數組;

22. 導航鉤子有哪些?它們有哪些參數?

導航主要有三類鉤子: 全局級路由鉤子路由級路由鉤子組件級路由鉤子。主要參數有to(目標路由對象)、from(當前路由對象)、next(是一個函數,用於控制是否放行,便是否能經過當前守衛)。
  • 全局級路由鉤子: beforeEach和afterEach,每次路由跳轉全局路由鉤子都會執行,beforeEach(to, from, next)鉤子有三個參數,可是afterEach是已經跳轉結束了,因此其沒有next參數,afterEach(to, from),全局路由鉤子由router對象調用
  • 路由級路由鉤子: 路由級鉤子只有一個即beforeEnter,其是在配置路由表的時候配置,也是有to、from、next三個參數,只有進入該路由的時候纔會執行,若是是動態路由之間的切換,那麼則不會觸發beforeEnter鉤子,由於是同一個路由,只是參數不同
  • 組件級路由鉤子: beforeRouteEnter(路由進入該組件的時候執行)、beforeRouteUpdate(動態路由切換時候執行)、beforeRouteLeave(路由離開當前組件的時候執行),須要注意的是,路由鉤子是優先於組件的生命週期的,也就是說路由鉤子所有執行完畢以後纔會開始組件的生命週期,因此其鉤子執行順序: beforeRouteLeave --> beforeEach --> beforeEnter --> beforeRouteEnter --> afterEach --> beforeCreate --> created --> mountedbeforeRouteUpdate只有動態路由切換的時候纔會執行,即/user/1切換到/user/2纔會執行

23. v-model是什麼?

v-model主要用於數據的雙向綁定,其內部主要完成了兩個操做: 經過v-bind綁定value屬性值監聽input事件,並更新數據,如:
<template>
    <!-- <input v-model="msg"/>{{msg}} -->
    <input v-bind:value="msg" @input="msg=$event.target.value"/>{{msg}} <!--兩者是等價的-->
</template>
<script>
    export default {
        data: () => {
            return {
                msg: "hello"
            }
        }
    }
</script>

24. 什麼是路由懶加載?其原理是什麼?

所謂路由懶加載,即在項目打包的時候,項目中一般會有多個路由,若是將全部路由對應的組件都打包到一個文件中,那麼最終打包的文件就會變得很是大,會影響頁面的加載性能,若是咱們能把不一樣路由對應的組件 分割成不一樣的代碼塊,而後 當路由被訪問的時候才異步加載出對應組件,這樣就會變得更加高效。
因此其原理就是利用了 webpack的代碼分割(按需加載)機制和 vue的異步組件功能,代碼被分割後就會變成一個單獨的文件,因此 路由被訪問的時候須要向服務器發起請求加載該組件,這是一個 異步的過程,因此須要使用到vue的異步組件機制。

異步組件?java

異步組件,就是在註冊組件的時候, 傳入一個函數,而後這個函數返回一個Promise對象, resolve的值爲這個組件對象,如:
export default new Router({
    routes: [
        {
          path: '/about',
          name: 'about',
          component: () => { // 註冊爲一個異步組件
              const About = require("./views/About.vue");
              return Promise.resolve(About);
          }
        }
    ]
});

或者在註冊異步組件的時候傳入resolve和reject,如:node

export default new Router({
    routes: [
        {
          path: '/about',
          name: 'about',
          component: (resolve, reject) => { // 註冊爲一個異步組件
              const About = require("./views/About.vue");
              resolve(About);
          }
        }
    ]
});

webpack提供的import()函數會返回一個Promise對象,而且會對引入的組件進行代碼分割,因此能夠經過import()同時實現代碼分割和組件異步加載,即路由懶加載,如:jquery

export default new Router({
    routes: [
        {
          path: '/about',
          name: 'about',
          component: () => import('./views/About.vue') // 等價於註冊異步組件並返回一個Promise對象,分割代碼的同時進行異步加載
        }
    ]
});

25. 用過插槽嗎?用過哪些類型的插槽?

插槽其實就是 組件中提供的佔位符,因此 插槽佔位符在組件中使用,插槽有三種: 匿名插槽具名插槽做用域插槽
  • 匿名插槽:即沒有名字的插槽,即<slot></slot>,使用組件的時候會將組件中的innerHTML插入到<slot></slot>位置上,至關於動態向組件內部傳遞數據。
// About.vue組件
<template>
  <div class="hello">
    <slot></slot>
  </div>
</template>

// 使用About組件
<About>
    <h1>hello world</h1><!--該內容會插入到上面<slot></slot>位置上,即替換掉<slot></slot>-->
</About>
  • 具名插槽: 即有名字的插槽,須要在<slot>標籤上添加一個name屬性,指定<slot>的名稱,即<slot name="header"></slot>,同時使用組件的時候須要給其中的innerHTML添加slot屬性,屬性值爲<slot>的name屬性值,如:
// About.vue組件
<template>
  <div class="hello">
    <slot name="header"></slot> <!--定義slot的名稱爲header-->
  </div>
</template>

// 使用About組件
<About>
    <h1 slot="header">header</h1> <!--該內容會被插入到名稱爲header的slot上-->
</About>
  • 做用域插槽: 做用域插槽能夠理解爲組件向外輸出數據,咱們能夠在組件的<slot>標籤上添加上一些屬性,而後其中的屬性值能夠傳到組件外使用,會將slot標籤上的因此屬性合併到一個對象對外輸出,組件外經過slot-scope指定一個變量名來接收這個對象,如:
// About.vue組件
<template>
  <div class="hello">
    <h1 slot="footer" slot-scope="innerData">{{innerData.msg}} {{innerData.foo}}</h1><!--指定innerData變量接收組件slot標籤中屬性集對象-->
  </div>
</template>

// 使用About組件
<About>
    <slot name="footer" msg="haha" foo="foo"></slot><!--會將其中的屬性合併成一個對象對外輸出-->
</About>

26. 什麼是vue-loader?

vue-loader就是 .vue組件的加載器能夠將.vue組件轉換爲javascript模塊,及 動態渲染一些數據,同時vue-loader還對.vue組件中的三個標籤都進行了相應的優化。 <template>標籤中可使用src屬性引入一個組件,引入的組件能夠直接使用當前組件中的數據, <script>標籤中能夠直接使用ES6語法<style>標籤能夠默認使用sass而且支持scoped做用域選擇。如:

// foo.vuewebpack

<template>
    <h1>{{msg}}</h1><!--能夠直接使用hello.vue中的數據-->
</template>

// hello.vueios

<template src="./foo.vue"> <!--直接經過src引入foo.vue-->
  
</template>

<script>
export default {
  name: 'HelloWorld',
  data: () => {
    return {
      msg: "to foo.vue"
    }
  }
}
</script>
<style scoped>

</style>

27. Vue中keep-alive 的做用以及用法?

keep-alive是vue中一個內置的組件,主要用於 緩存組件,其會在組件created的時候,將須要緩存的組件放到緩存中,而後再render的時候再根據name進行取出。<keep-alive>主要配合路由進行使用,在配置路由的時候添加上meta元數據對象,裏面添加上keepAlive屬性,表示是否緩存該組件,而後將<router-view>放到<keep-alive>中,router-view經過v-if指令,從路由配置上的meta對象中取出keepAlive的值進行判斷是否須要緩存,如:
<template>
  <div id="app">
      <keep-alive>
        <router-view v-if="$route.meta.keepAlive"/> <!--這個是須要緩存的-->
      </keep-alive>
        <router-view v-if="!$route.meta.keepAlive"></router-view><!--這個是不須要緩存的-->
  </div>
</template>

// 路由配置git

export default new Router({
    routes: [
        {
          path: '/',
          name: 'home',
          component: Home,
          meta: {
            keepAlive: true
          }
        },
        {
          path: '/about',
          name: 'about',
          component: About,
          meta: {
            keepAlive: false
          }
        }
    ]
});
組件緩存後就不會執行組件的beforeCreate、created和beforeMount、mounted鉤子了,因此其提供了actived和deactived鉤子, actived鉤子主要用於承擔原來created鉤子中獲取數據的任務

28. Vue 組件中 data 爲何必須是函數?

由於 組件是能夠屢次複用的,也就是說 會有多個組件實例同時存在,同時因爲 對象是引用數據類型,若是全部組件實例都共用一個data數據對象,那麼一個組件對data數據對象進行修改,那麼 其餘組件實例也會受到影響,因此須要使用函數返回data對象的獨立拷貝, 使得每一個組件實例都會擁有本身的data數據對象,相互之間獨立,不會互相受影響,便於組件維護。

29. Vue組件複用時,vue-router如何響應路由參數的變化?

當使用路由參數時,例如從 /user/lucy 導航到 /user/lily, 原來的組件實例會被複用。由於兩個路由都渲染同個組件,比起銷燬再建立,複用則顯得更加高效。不過,這也意味着 組件的生命週期鉤子不會再被調用,複用組件時,想對路由參數的變化做出響應的話,有兩種方式:
  • 監聽$route對象數據變化
export default {
  watch: {
    '$route': (to, from) =>{
      console.log("route change");// 對路由變化做出響應...

    }
  }
}
  • 經過beforeRouteUpdate路由鉤子
export default {
  beforeRouteUpdate(to, from ,next) {
    console.log("beforeRouteUpdate hook run.");
    next();
  }
}

30. 簡述Vue的響應式原理?

當一個Vue實例建立時,vue會遍歷data選項的屬性,用 Object.defineProperty 將它們轉爲 getter/setter而且在內部追蹤相關依賴,在屬性被訪問和修改時通知變化。 每一個組件實例都有相應的 watcher 程序實例,它會在組件渲染的過程當中把屬性記錄爲依賴,以後當依賴項的 setter 被調用時,會通知 watcher 從新計算,從而導致它關聯的組件得以更新。
相關文章
相關標籤/搜索