Vue面試題

什么是 mvvm?

MVVM 是 Model-View-ViewModel 的縮寫(xiě)。mvvm 是一種設(shè)計(jì)思想。Model 層代表數(shù)據(jù)模型,也可以在 Model 中定義數(shù)據(jù)修改和操作的業(yè)務(wù)邏輯;View 代表 UI 組件,它負(fù)責(zé)將數(shù)據(jù)模型轉(zhuǎn)化成 UI 展現(xiàn)出來(lái),ViewModel 是一個(gè)同步 View 和 Model 的對(duì)象。在 MVVM 架構(gòu)下,View 和 Model 之間并沒(méi)有直接的聯(lián)系,而是通過(guò) ViewModel 進(jìn)行交互,Model 和 ViewModel 之間的交互是雙向的, 因此 View 數(shù)據(jù)的變化會(huì)同步到 Model 中,而 Model 數(shù)據(jù)的變化也會(huì)立即反應(yīng)到 View 上。ViewModel 通過(guò)雙向數(shù)據(jù)綁定把 View 層和 Model 層連接了起來(lái),而 View 和 Model 之間的同步工作完全是自動(dòng)的,無(wú)需人為干涉,因此開(kāi)發(fā)者只需關(guān)注業(yè)務(wù)邏輯,不需要手動(dòng)操作 DOM, 不需要關(guān)注數(shù)據(jù)狀態(tài)的同步問(wèn)題,復(fù)雜的數(shù)據(jù)狀態(tài)維護(hù)完全由 MVVM 來(lái)統(tǒng)一管理。

mvvm 和 mvc 區(qū)別?

mvc 和 mvvm 其實(shí)區(qū)別并不大。都是一種設(shè)計(jì)思想。主要就是 mvc 中 Controller 演變成 mvvm 中的 viewModel。mvvm 主要解決了 mvc 中大量的 DOM 操作使頁(yè)面渲染性能降低,加載速度變慢,影響用戶體驗(yàn)。和當(dāng) Model 頻繁發(fā)生變化,開(kāi)發(fā)者需要主動(dòng)更新到 View 。

vue 的優(yōu)點(diǎn)是什么?

  • 低耦合。視圖(View)可以獨(dú)立于 Model 變化和修改,一個(gè) ViewModel 可以綁定到不同的"View"上,當(dāng) View 變化的時(shí)候 Model 可以不變,當(dāng) Model 變化的時(shí)候 View 也可以不變。
  • 可重用性。你可以把一些視圖邏輯放在一個(gè) ViewModel 里面,讓很多 view 重用這段視圖邏輯。
  • 獨(dú)立開(kāi)發(fā)。開(kāi)發(fā)人員可以專(zhuān)注于業(yè)務(wù)邏輯和數(shù)據(jù)的開(kāi)發(fā)(ViewModel),設(shè)計(jì)人員可以專(zhuān)注于頁(yè)面設(shè)計(jì),使用 Expression Blend 可以很容易設(shè)計(jì)界面并生成 xml 代碼。
  • 可測(cè)試。界面素來(lái)是比較難于測(cè)試的,而現(xiàn)在測(cè)試可以針對(duì) ViewModel 來(lái)寫(xiě)。

vue生命周期的理解?

答:總共分為 8 個(gè)階段創(chuàng)建前/后,載入前/后,更新前/后,銷(xiāo)毀前/后。

  • 創(chuàng)建前/后: 在 beforeCreate 階段,vue 實(shí)例的掛載元素 el 還沒(méi)有。
  • 載入前/后:在 beforeMount 階段,vue 實(shí)例的$el 和 data 都初始化了,但還是掛載之前為虛擬的 dom 節(jié)點(diǎn),data.message 還未替換。在 mounted 階段,vue 實(shí)例掛載完成,data.message 成功渲染。
  • 更新前/后:當(dāng) data 變化時(shí),會(huì)觸發(fā) beforeUpdate 和 updated 方法。
  • 銷(xiāo)毀前/后:在執(zhí)行 destroy 方法后,對(duì) data 的改變不會(huì)再觸發(fā)周期函數(shù),說(shuō)明此時(shí) vue 實(shí)例已經(jīng)解除了事件監(jiān)聽(tīng)以及和 dom 的綁定,但是 dom 結(jié)構(gòu)依然存在。

為什么vue中data必須是一個(gè)函數(shù)?

對(duì)象為引用類(lèi)型,當(dāng)重用組件時(shí),由于數(shù)據(jù)對(duì)象都指向同一個(gè)data對(duì)象,當(dāng)在一個(gè)組件中修改data時(shí),其他重用的組件中的data會(huì)同時(shí)被修改;而使用返回對(duì)象的函數(shù),由于每次返回的都是一個(gè)新對(duì)象(Object的實(shí)例),引用地址不同,則不會(huì)出現(xiàn)這個(gè)問(wèn)題。

組件之間的傳值?

1.父組件與子組件傳值

//父組件通過(guò)標(biāo)簽上面定義傳值
<template>
    <Main :obj="data"></Main>
</template>
<script>
    //引入子組件
    import Main form "./main"

    exprot default{
        name:"parent",
        data(){
            return {
                data:"我要向子組件傳遞數(shù)據(jù)"
            }
        },
        //初始化組件
        components:{
            Main
        }
    }
</script>


//子組件通過(guò)props方法接受數(shù)據(jù)
<template>
    <div>{{obj}}</div>
</template>
<script>
    exprot default{
        name:"son",
        //接受父組件傳值
        props:["obj"]
    }
</script>

2.子組件向父組件傳遞數(shù)據(jù)

//子組件通過(guò)$emit方法傳遞參數(shù)
<template>
   <div v-on:click="events"></div>
</template>
<script>
    //引入子組件
    import Main form "./main"

    exprot default{
        methods:{
            events:function(params){
              console.log(params)
            }
        }
    }
</script>


//

<template>
    <div v-on:click="emitEvent">{{data}}</div>
</template>
<script>
    exprot default{
        name:"son",
        //接受父組件傳值
        props:["data"],
        methods: {
          emitEvent() {
            this.$emit('event', params) // 派發(fā)函數(shù),并傳遞值,params是你自己想傳的值
          }
        }
    }
</script>

active-class 是哪個(gè)組件的屬性?

vue-router 模塊的 router-link 組件。

嵌套路由怎么定義?

在實(shí)際項(xiàng)目中我們會(huì)碰到多層嵌套的組件組合而成,但是我們?nèi)绾螌?shí)現(xiàn)嵌套路由呢?因此我們需要在 VueRouter 的參數(shù)中使用 children 配置,這樣就可以很好的實(shí)現(xiàn)路由嵌套。index.html,只有一個(gè)路由出口

<div id="app">
    <!-- router-view 路由出口, 路由匹配到的組件將渲染在這里 -->
    <router-view></router-view>
</div>

main.js,路由的重定向,就會(huì)在頁(yè)面一加載的時(shí)候,就會(huì)將 home 組件顯示出來(lái),因?yàn)橹囟ㄏ蛑赶蛄?home 組件,redirect 的指向與 path 的必須一致。children 里面是子路由,當(dāng)然子路由里面還可以繼續(xù)嵌套子路由。

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

//引入兩個(gè)組件

import home from "./home.vue"
import game from "./game.vue"
//定義路由
const routes = [
    { path: "/", redirect: "/home" },//重定向,指向了home組件
    {
        path: "/home", component: home,
        children: [
            { path: "/home/game", component: game }
        ]
    }
]
//創(chuàng)建路由實(shí)例
const router = new VueRouter({routes})

new Vue({
    el: '#app',
    data: {
    },
    methods: {
    },
    router
})

home.vue,點(diǎn)擊顯示就會(huì)將子路由顯示在出來(lái),子路由的出口必須在父路由里面,否則子路由無(wú)法顯示。

路由之間跳轉(zhuǎn)?

  • 聲明式(標(biāo)簽跳轉(zhuǎn))
  • 編程式( js 跳轉(zhuǎn)) router.push('index')

懶加載(按需加載路由)(常考)

webpack 中提供了 require.ensure()來(lái)實(shí)現(xiàn)按需加載。以前引入路由是通過(guò) import 這樣的方式引入,改為 const 定義的方式進(jìn)行引入。

  • 不進(jìn)行頁(yè)面按需加載引入方式:import home from '../../common/home.vue'
  • 進(jìn)行頁(yè)面按需加載的引入方式:const home = r => require.ensure( [], () => r (require('../../common/home.vue')))

vuex 是什么?怎么使用?哪種功能場(chǎng)景使用它?

vue 框架中狀態(tài)管理。在 main.js 引入 store,注入。新建了一個(gè)目錄 store,….. export 。場(chǎng)景有:?jiǎn)雾?yè)應(yīng)用中,組件之間的狀態(tài)。音樂(lè)播放、登錄狀態(tài)、加入購(gòu)物車(chē)

// 新建 store.js
import vue from 'vue'
import vuex form 'vuex'
vue.use(vuex)
export default new vuex.store({
    //...code
})

//main.js
import store from './store'
...

vue-router 有哪幾種導(dǎo)航鉤子?

三種

  • 全局導(dǎo)航鉤子
    router.beforeEach(to, from, next),
    router.beforeResolve(to, from, next),
    router.afterEach(to, from ,next)
  • 組件內(nèi)鉤子
    beforeRouteEnter,
    beforeRouteUpdate,
    beforeRouteLeave
  • 單獨(dú)路由獨(dú)享組件
    beforeEnter

自定義指令(v-check, v-focus) 的方法有哪些? 它有哪些鉤子函數(shù)? 還有哪些鉤子函數(shù)參數(shù)

  • 全局定義指令:在 vue 對(duì)象的 directive 方法里面有兩個(gè)參數(shù), 一個(gè)是指令名稱, 另一個(gè)是函數(shù)。
  • 組件內(nèi)定義指令:directives鉤子函數(shù): bind(綁定事件出發(fā))、inserted(節(jié)點(diǎn)插入時(shí)候觸發(fā))、update(組件內(nèi)相關(guān)更新)
  • 鉤子函數(shù)參數(shù): el、binding

說(shuō)出至少 4 種 vue 當(dāng)中的指令和它的用法

v-if(判斷是否隱藏)、v-for(把數(shù)據(jù)遍歷出來(lái))、v-bind(綁定屬性)、v-model(實(shí)現(xiàn)雙向綁定)

vue 的雙向綁定的原理是什么(???

vue.js 是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過(guò) Object.defineProperty()來(lái)劫持各個(gè)屬性的 setter,getter,在數(shù)據(jù)變動(dòng)時(shí)發(fā)布消息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽(tīng)回調(diào)。
具體步驟:
第一步:需要 observe 的數(shù)據(jù)對(duì)象進(jìn)行遞歸遍歷,包括子屬性對(duì)象的屬性,都加上 setter 和 getter 這樣的話,給這個(gè)對(duì)象的某個(gè)值賦值,就會(huì)觸發(fā) setter,那么就能監(jiān)聽(tīng)到了數(shù)據(jù)變化
第二步:compile 解析模板指令,將模板中的變量替換成數(shù)據(jù),然后初始化渲染頁(yè)面視圖,并將每個(gè)指令對(duì)應(yīng)的節(jié)點(diǎn)綁定更新函數(shù),添加監(jiān)聽(tīng)數(shù)據(jù)的訂閱者,一旦數(shù)據(jù)有變動(dòng),收到通知,更新視圖
第三步:Watcher 訂閱者是 Observer 和 Compile 之間通信的橋梁,主要做的事情是:
在自身實(shí)例化時(shí)往屬性訂閱器(dep)里面添加自己自身必須有一個(gè) update()方法待屬性變動(dòng) dep.notice()通知時(shí),能調(diào)用自身的 update() 方法,并觸發(fā) Compile 中綁定的回調(diào),則功成身退。
第四步:MVVM 作為數(shù)據(jù)綁定的入口,整合 Observer、Compile 和 Watcher 三者,通過(guò) Observer 來(lái)監(jiān)聽(tīng)自己的 model 數(shù)據(jù)變化,通過(guò) Compile 來(lái)解析編譯模板指令,最終利用 Watcher 搭起 Observer 和 Compile 之間的通信橋梁,達(dá)到數(shù)據(jù)變化 -> 視圖更新;視圖交互變化(input) -> 數(shù)據(jù) model 變更的雙向綁定效果。

vuex 有哪幾種屬性

有 5 種,分別是 state、getter、mutation、action、module

vuex 的 store 特性是什么

vuex 就是一個(gè)倉(cāng)庫(kù),倉(cāng)庫(kù)里放了很多對(duì)象。其中 state 就是數(shù)據(jù)源存放地,對(duì)應(yīng)于一般 vue 對(duì)象里面的 datastate 里面存放的數(shù)據(jù)是響應(yīng)式的,vue 組件從 store 讀取數(shù)據(jù),若是 store 中的數(shù)據(jù)發(fā)生改變,依賴這相數(shù)據(jù)的組件也會(huì)發(fā)生更新它通過(guò) mapState 把全局的 state 和 getters 映射到當(dāng)前組件的 computed 計(jì)算屬性

vuex 的 getter 特性是什么

getter 可以對(duì) state 進(jìn)行計(jì)算操作,它就是 store 的計(jì)算屬性雖然在組件內(nèi)也可以做計(jì)算屬性,但是 getters 可以在多給件之間復(fù)用如果一個(gè)狀態(tài)只在一個(gè)組件內(nèi)使用,是可以不用 getters

vuex 的 mutation 特性是什么

action 類(lèi)似于 muation, 不同在于:action 提交的是 mutation,而不是直接變更狀態(tài)action 可以包含任意異步操作

vue 中 ajax 請(qǐng)求代碼應(yīng)該寫(xiě)在組件的 methods 中還是 vuex 的 action 中

如果請(qǐng)求來(lái)的數(shù)據(jù)不是要被其他組件公用,僅僅在請(qǐng)求的組件內(nèi)使用,就不需要放入 vuex 的 state 里如果被其他地方復(fù)用,請(qǐng)將請(qǐng)求放入 action 里,方便復(fù)用,并包裝成 promise 返回

不用 vuex 會(huì)帶來(lái)什么問(wèn)題

  • 可維護(hù)性會(huì)下降,你要修改數(shù)據(jù),你得維護(hù) 3 個(gè)地方
  • 可讀性下降,因?yàn)橐粋€(gè)組件里的數(shù)據(jù),你根本就看不出來(lái)是從哪里來(lái)的
  • 增加耦合,大量的上傳派發(fā),會(huì)讓耦合性大大的增加,本來(lái) Vue 用 Component 就是為了減少耦合,現(xiàn)在這么用,和組件化的初衷相背

vuex 原理

vuex 僅僅是作為 vue 的一個(gè)插件而存在,不像 Redux,MobX 等庫(kù)可以應(yīng)用于所有框架,vuex 只能使用在 vue 上,很大的程度是因?yàn)槠涓叨纫蕾囉?vue 的 computed 依賴檢測(cè)系統(tǒng)以及其插件系統(tǒng),vuex 整體思想誕生于 flux,可其的實(shí)現(xiàn)方式完完全全的使用了 vue 自身的響應(yīng)式設(shè)計(jì),依賴監(jiān)聽(tīng)、依賴收集都屬于 vue 對(duì)對(duì)象 Property set get 方法的代理劫持。最后一句話結(jié)束 vuex 工作原理,vuex 中的 store 本質(zhì)就是沒(méi)有 template 的隱藏著的 vue 組件;

使用 Vuex 只需執(zhí)行 Vue.use(Vuex),并在 Vue 的配置中傳入一個(gè) store 對(duì)象的示例,store 是如何實(shí)現(xiàn)注入的?美團(tuán)

Vue.use(Vuex) 方法執(zhí)行的是 install 方法,它實(shí)現(xiàn)了 Vue 實(shí)例對(duì)象的 init 方法封裝和注入,使傳入的 store 對(duì)象被設(shè)置到 Vue 上下文環(huán)境的store中。因此在VueComponent任意地方都能夠通過(guò)this.store 訪問(wèn)到該 store。

state 內(nèi)部支持模塊配置和模塊嵌套,如何實(shí)現(xiàn)的?美團(tuán)

在 store 構(gòu)造方法中有 makeLocalContext 方法,所有 module 都會(huì)有一個(gè) local context,根據(jù)配置時(shí)的 path 進(jìn)行匹配。所以執(zhí)行如 dispatch('submitOrder', payload)這類(lèi) action 時(shí),默認(rèn)的拿到都是 module 的 local state,如果要訪問(wèn)最外層或者是其他 module 的 state,只能從 rootState 按照 path 路徑逐步進(jìn)行訪問(wèn)。

在執(zhí)行 dispatch 觸發(fā) action(commit 同理)的時(shí)候,只需傳入(type, payload),action 執(zhí)行函數(shù)中第一個(gè)參數(shù) store 從哪里獲取的?美團(tuán)

store 初始化時(shí),所有配置的 action 和 mutation 以及 getters 均被封裝過(guò)。在執(zhí)行如 dispatch('submitOrder', payload)的時(shí)候,actions 中 type 為 submitOrder 的所有處理方法都是被封裝后的,其第一個(gè)參數(shù)為當(dāng)前的 store 對(duì)象,所以能夠獲取到 { dispatch, commit, state, rootState } 等數(shù)據(jù)。

Vuex 如何區(qū)分 state 是外部直接修改,還是通過(guò) mutation 方法修改的?美團(tuán)

Vuex 中修改 state 的唯一渠道就是執(zhí)行 commit('xx', payload) 方法,其底層通過(guò)執(zhí)行 this._withCommit(fn) 設(shè)置_committing 標(biāo)志變量為 true,然后才能修改 state,修改完畢還需要還原_committing 變量。外部修改雖然能夠直接修改 state,但是并沒(méi)有修改_committing 標(biāo)志位,所以只要 watch 一下 state,state change 時(shí)判斷是否_committing 值為 true,即可判斷修改的合法性。

調(diào)試時(shí)的"時(shí)空穿梭"功能是如何實(shí)現(xiàn)的?美團(tuán)

devtoolPlugin 中提供了此功能。因?yàn)?dev 模式下所有的 state change 都會(huì)被記錄下來(lái),'時(shí)空穿梭' 功能其實(shí)就是將當(dāng)前的 state 替換為記錄中某個(gè)時(shí)刻的 state 狀態(tài),利用 store.replaceState(targetState) 方法將執(zhí)行 this._vm.state = state 實(shí)現(xiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、什么是MVVM? MVVM是一個(gè)model+view+viewModel框架。MVVM是一種設(shè)計(jì)思想。Mode...
    花開(kāi)有聲是我閱讀 3,562評(píng)論 1 79
  • vue是什么? vue是構(gòu)建數(shù)據(jù)驅(qū)動(dòng)的web界面的漸進(jìn)式框架。Vue.js 的目標(biāo)是通過(guò)盡可能簡(jiǎn)單的 API 實(shí)現(xiàn)...
    九四年的風(fēng)閱讀 8,813評(píng)論 2 131
  • 一、什么是MVVM?MVVM是Model-View-ViewModel的縮寫(xiě)。MVVM是一種設(shè)計(jì)思想。Model ...
    陳老板_閱讀 1,578評(píng)論 2 38
  • 一、什么是MVVM? MVVM是Model-View-ViewModel的縮寫(xiě)。MVVM是一種設(shè)計(jì)思想。Model...
    Ht_何甜閱讀 2,267評(píng)論 2 71
  • 眼看明天就大年三十了,雖不盼望著過(guò)年,但也是逃不脫過(guò)年。 雖然怕長(zhǎng)一歲,但也不得不長(zhǎng)一歲,依然在矛盾中為過(guò)年準(zhǔn)備著...
    清幽勵(lì)志文苑閱讀 272評(píng)論 2 3

友情鏈接更多精彩內(nèi)容