首頁  >  文章  >  web前端  >  【吐血整理】Vue.js面試題彙總及答案解析(快來收藏)

【吐血整理】Vue.js面試題彙總及答案解析(快來收藏)

青灯夜游
青灯夜游轉載
2022-07-06 19:55:144195瀏覽

這篇文章為大家總結分享一些Vue面試題(附答案解析),帶你梳理基礎知識,增強Vue知識儲備,值得收藏,快來看看吧!

【吐血整理】Vue.js面試題彙總及答案解析(快來收藏)

(學習影片分享:vue影片教學

一、Vue.js基本問題

1.1.Vue 響應式原則

【吐血整理】Vue.js面試題彙總及答案解析(快來收藏)

#核心實作類別:
Observer :它的作用是為物件的屬性添加getter 和setter,用於依賴收集和派發更新
Dep : 用於收集當前響應式物件的依賴關係,每個響應式物件包括子物件都擁有一個Dep 實例(裡面subs 是Watcher 實例數組),當資料有變更時,會透過dep.notify()通知各個watcher。
Watcher : 觀察者物件, 實例分為渲染watcher (render watcher),計算屬性watcher (computed watcher),偵聽器watcher(user watcher)三種
Watcher 和Dep 的關係:
watcher 中實例化了dep 並向dep.subs 中新增了訂閱者,dep 透過notify 遍歷了dep.subs 通知每個watcher 更新。
依賴收集:
initState 時,對computed 屬性初始化時,觸發computed watcher 依賴收集
initState 時,對偵聽屬性初始化時,觸發user watcher 依賴收集
render()的過程,觸發render watcher 依賴收集
re-render 時,vm.render()再次執行,會移除所有subs 中的watcer 的訂閱,重新賦值。
派發更新:
元件中對回應的資料進行了修改,觸發setter 的邏輯
呼叫dep.notify()
遍歷所有的subs(Watcher 實例),呼叫每一個watcher 的update 方法。
原理:
當建立Vue 實例時,vue 會遍歷data 選項的屬性,利用Object.defineProperty 為屬性添加getter 和setter 對資料的讀取進行劫持(getter 用來依賴收集,setter 用來派發更新),並且在內部追蹤依賴,在屬性被存取和修改時通知變化。
每個元件實例會有對應的watcher 實例,會在元件渲染的過程中記錄依賴的所有資料屬性(進行依賴收集,還有computed watcher,user watcher 實例),之後依賴項被改動時,setter方法會通知依賴與此data 的watcher 實例重新計算(派發更新),從而使它關聯的元件重新渲染。
一句話總結:
vue.js 採用資料劫持結合發布-訂閱模式,透過Object.defineproperty 來劫持各個屬性的setter,getter,在資料變動時發佈訊息給訂閱者,觸發回應的監聽回呼

1.2.Vue.js 的特點

易用: 簡單,易學,上手快
靈活: (漸進式)不斷繁榮的生態系統,可以在一個庫和一套完整框架之間自如伸縮。
高效能: 20kB min gzip 運作大小;超快虛擬DOM;最省心的最佳化
雙向綁定:開發效率高
基於元件的程式碼共享
Web專案工程化,增加可讀性、可維護性

1.3. Vue.js 雙向綁定的原理

Vue.js 2.0 採用資料劫持(Proxy 模式)結合發布者-訂閱者模式(PubSub 模式)的方式,透過Object.defineProperty()來劫持各個屬性的setter,getter,在資料變動時發布訊息給訂閱者,觸發對應的監聽回呼。
每個元件實例都有對應的watcher程式實例,它會在元件渲染的過程中把屬性記錄為依賴,之後當依賴項的setter被呼叫時,會通知watcher重新計算,從而致使它關聯的組件得以更新。

Vue.js 3.0, 放棄了Object.defineProperty ,使用更快的ES6原生 Proxy (存取物件攔截器, 也稱為代理程式)

步驟:

1.需要observe的資料物件進行遞歸遍歷,包含子屬性物件的屬性,都加上setter和getter這樣的話,給這個物件的某個值賦值,就會觸發setter,那麼就能監聽到了數據變化
2.compile解析模板指令,將模板中的變量替換成數據,然後初始化渲染頁面視圖,並將每個指令對應的節點綁定更新函數,添加監聽數據的訂閱者,一旦資料有變動,收到通知,更新視圖
3.Watcher訂閱者是Observer和Compile之間通訊的橋樑,主要做的事情是: ①在自身實例化時往屬性訂閱器(dep)裡面新增自己②本身必須有一個update()方法③待屬性變動dep.notice()通知時,能呼叫自身的update()方法,並觸發Compile中綁定的回調,則功成身退。
4.MVVM作為資料綁定的入口,整合Observer、Compile和Watcher三者,透過Observer來監聽自己的model資料變化,透過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通訊橋樑,達到資料變化-> 視圖更新;視圖互動變化(input) -> 資料model變更的雙向綁定效果。

1.4.Vue中如何監控某個屬性值的變化?

例如現在需要監控data中, obj.a 的變化。 Vue中監控物件屬性的變化你可以這樣:

watch: {
      obj: {
      	handler (newValue, oldValue) {
        console.log('obj changed')
      },
      deep: true
    }

deep屬性表示深層遍歷,但是這麼寫會監控obj的所有屬性變化,並不是我們想要的效果,所以做點修改:

watch: {
   'obj.a': {
      	handler (newName, oldName) {
        console.log('obj.a changed')
      }
   }
  }

還有一個方法,可以透過computed 來實現,只需要:

computed: {
    a1 () {
      return this.obj.a    
      }
}

利用計算屬性的特性來實現,當依賴改變時,便會重新計算一個新值。

1.5.Vue.js 3.0 放棄defineProperty, 使用Proxy的原因

Object.defineProperty缺陷

1.監控到陣列下標的變化時,開銷很大。所以Vue.js放棄了下標變化的偵測;
2.Object.defineProperty只能劫持物件的屬性,而Proxy是直接代理物件。 3.Object.defineProperty需要遍歷物件的每個屬性,如果屬性值也是對象,則需要深度遍歷。而 Proxy 直接代理對象,不需要遍歷操作。
4.Object.defineProperty對新增屬性需要手動進行Observe。 vue2時需要使用vm.$set 才能確保新增的屬性也是響應式
5.Proxy支援13種攔截操作,這是defineProperty不具有的
6.Proxy 作為新標準,長遠來看, JS引擎會繼續最佳化Proxy,但getter 和setter 基本上不會再有針對性最佳化

1.6.Vue 2 中為data 中的物件屬性新增一個新的屬性時會發生什麼?如何解決?

檢視並未刷新。這是因為當Vue實例建立時,新屬性並未聲明,因此就沒有被Vue轉換為響應式的屬性,自然就不會觸發視圖的更新,這時就需要使用Vue的全域api $set():

this.$set(this.obj, 'new_property', 'new_value')

1.7.Computed和Watch的區別及運用場景

computed 計算屬性: 依賴其它屬性值,並且computed 的值有快取,只有它所依賴的屬性值改變,下一次取得computed 的值時才會重新計算computed 的值。
watch 偵聽器 : 更多的是觀察的作用,無緩存性,類似於某些資料的監​​聽回調,每 當監聽的資料變化時都會執行回調進行後續操作。

運用場景:

1.當我們需要進行數值計算,並且依賴於其它資料時,應該使用computed,因為可以利用computed 的快取特性,避免每次取得值時,都要重新計算。
2.當我們需要在資料變更時執行非同步或開銷較大的操作,應該使用watch,使用watch 選項允許我們執行非同步操作( 存取一個API ),限制我們執行該操作的頻率, 並且在我們得到最終結果前,設定中間狀態。這些都是計算屬性無法做到的。
3.多個因素影響一個顯示,用Computed;一個因素的變化影響多個其他因素、顯示,用Watch;

1.8. Computed 和Methods 的區別

1.computed: 計算屬性是基於它們的依賴進行緩存的,只有在它的相關依賴發生改變時才會重新求值對於method ,只要發生重新渲染,
2.method 呼叫總是會執行函數

1.9.虛擬DOM,diff演算法

#1.讓我們不用直接操作DOM元素,只操作資料就可以重新渲染頁面
2 .虛擬dom是為了解決瀏覽器效能問題而被設計出來的
當操作資料時,將改變的dom元素快取起來,都計算完後再透過比較映射到真實的dom樹上
3. diff演算法比較新舊虛擬dom。如果節點類型相同,則比較數據,修改數據;如果節點不同,直接幹掉節點及所有子節點,插入新的節點;如果給每個節點都設置了唯一的key,就可以準確的找到需要改變的內容,否則就會出現修改一個地方導致其他地方都改變的情況。例如A-B-C-D, 我要插入新節點A-B-M-C-D,實際上改變的了C和D。但是設定了key,就可以準確的找到B C並插入

1.10.為何需要Virtual DOM?

1.具備跨平台的優勢
2.操作 DOM 慢,js運作效率高。我們可以將DOM對比操作放在JS層,提高效率。
3.提升渲染效能

1.11.過濾器(Filter)

在Vue中使用filters來過濾(格式化)數據,filters不會修改數據,而是過濾(格式化)數據,改變用戶看到的輸出(計算屬性computed ,方法methods 都是透過修改數據來處理數據格式的輸出顯示。
使用場景: 例如需要處理時間、數字等的的顯示格式;

1.12.常見的事件修飾符及其作用

1) .stop:等同於JavaScript 中的event.stopPropagation() ,防止事件冒泡;
2).prevent :等同於JavaScript 中的event.preventDefault() ,防止執行預先設的行為(如果事件可取消,則取消該事件,而不停止事件的進一步傳播);
3).capture :當元素發生冒泡時,先觸發帶有該修飾符的元素。若有多個該修飾符,則由外而內觸發。如p1中嵌套p2中嵌套p3.capture中嵌套p4,那麼執行順序為:p3=》p4=》p2=》p1
4).self :只會觸發自己範圍內的事件,不包含子元素;
5).once :只會觸發一次。

1.13.v-show指令和v-if指令的差別是什麼?

v-show 只是控制元素的顯示方式,將display 屬性在block 和none 來回切換;而v-if會控制這個DOM 節點的存在與否。當我們需要經常切換某個元素的顯示/隱藏時,使用v-show會更加節省效能上的開銷;當只需要一次顯示或隱藏時,使用v-if會更加合理。

1.14.v-model 是如何實現的,語法糖實際上是什麼

作用在表單元素上v-model="message"等同於v-bind:value=“message” v-on:input="message=e v e n t . t a r g e t . v a l u e " 作用在組件上, 本質是一個父子組件通信的語法糖,透過prop和.emit實現, 等同於:value="message" @input=" $emit('input', $event.target.value)"

1.15.data為什麼是函數而不是物件

JavaScript中的物件是引用類型的數據,當多個實例引用同一個物件時,只要一個實例對這個物件進行操作,其他實例中的資料也會改變。
而在Vue中,我們更多的是想要復用元件,那就需要每個元件都有自己的數據,這樣元件之間才不會互相干擾。
所以元件的資料不能寫成物件的形式,而是要寫成函數的形式。資料以函數傳回值的形式定義,這樣當我們每次復用元件的時候,就會傳回一個新的data,也就是說每個元件都有自己的私有資料空間,它們各自維護自己的數據,不會幹擾其他組件的正常運作。

1.16.Vue template 到render 的過程

1.呼叫parse方法將template轉換為ast(抽象語法樹, abstract syntax tree )
2.對靜態節點做最佳化。如果為靜態節點,他們產生的DOM永遠不會改變,這對運行時模板更新起到了極大的優化作用。
3.產生渲染函數.渲染的回傳值是VNode,VNode是Vue的虛擬DOM節點,裡面有(標籤名,子節點,文字等等)

1.17 .Vue template 到render 的過程

呼叫parse方法將template轉換為ast(抽象語法樹, abstract syntax tree)
對靜態節點做最佳化。如果為靜態節點,他們產生的DOM永遠不會改變,這對運行時模板更新起到了極大的優化作用。
產生渲染函數. 渲染的回傳值是VNode,VNode是Vue的虛擬DOM節點,裡面有(標籤名,子節點,文字等等)

1.18.axios是什么

易用、简洁且高效的http库, 支持node端和浏览器端,支持Promise,支持拦截器等高级配置。

1.19.sass是什么?如何在vue中安装和使用?

sass是一种CSS预编译语言安装和使用步骤如下。

1.用npm安装加载程序( sass-loader、 css-loader等加载程序)。
2.在 webpack.config.js中配置sass加载程序。

1.20.Vue.js页面闪烁

Vue. js提供了一个v-cloak指令,该指令一直保持在元素上,直到关联实例结束编译。当和CSS一起使用时,这个指令可以隐藏未编译的标签,直到实例编译结束。用法如下

1.21.如何解决数据层级结构太深的问题

在开发业务时,经常会岀现异步获取数据的情况,有时数据层次比较深,如以下代码: , 可以使用vm.$set手动定义一层数据:

vm.$set("demo",a.b.c.d)

1.22.在 Vue. js开发环境下调用API接口,如何避免跨域

config/ index.js内对 proxyTable项配置代理。

1.23.批量异步更新策略

Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
换句话说,只要观察到数据变化,就会自动开启一个队列,并缓冲在同一个事件循环中发生的所以数据改变。在缓冲时会去除重复数据,从而避免不必要的计算和 DOM 操作。

1.24.vue 的 nextTick 方法的实现原理

1.vue 用异步队列的方式来控制 DOM 更新和 nextTick 回调先后执行
2.microtask 因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕

1.25.Vue 组件 data 为什么必须是函数 ?

因为组件是可以复用的,JS 里对象是引用关系,如果组件 data 是一个对象,那么子组件中的 data 属性值会互相污染。
所以一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。

1.26.v-if和v-for一起使用的弊端及解决办法

由于v-for的优先级比v-if高,所以导致每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。

解决办法:

1.在v-for的外层或内层包裹一个元素来使用v-if
2.用computed处理

1.27.vue常用指令

1.v-model 多用于表单元素实现双向数据绑定(同angular中的ng-model)
2.v-bind 动态绑定 作用: 及时对页面的数据进行更改
3.v-on:click 给标签绑定函数,可以缩写为@,例如绑定一个点击函数 函数必须写在methods里面
4.v-for 格式: v-for=“字段名 in(of) 数组json” 循环数组或json(同angular中的ng-repeat)
5.v-show 显示内容 (同angular中的ng-show)
6.v-hide 隐藏内容(同angular中的ng-hide)
7.v-if 显示与隐藏 (dom元素的删除添加 同angular中的ng-if 默认值为false)
8.v-else-if 必须和v-if连用
9.v-else 必须和v-if连用 不能单独使用 否则报错 模板编译错误
10.v-text 解析文本
11.v-html 解析html标签
12.v-bind:class 三种绑定方法 1、对象型 ‘{red:isred}’ 2、三元型 ‘isred?“red”:“blue”’ 3、数组型 ‘[{red:“isred”},{blue:“isblue”}]’
13.v-once 进入页面时 只渲染一次 不在进行渲染
14.v-cloak 防止闪烁
15.v-pre 把标签内部的元素原位输出

1.28. 组件传值方式有哪些

1.父传子:子组件通过props[‘xx’] 来接收父组件传递的属性 xx 的值
2.子传父:子组件通过 this.$emit(‘fnName’,value) 来传递,父组件通过接收 fnName 事件方法来接收回调
3.其他方式:通过创建一个bus,进行传值
4.使用Vuex

1.30.vue中 key 值的作用

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM

1.31.为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?

Object.defineProperty 本身有一定的监控到数组下标变化的能力,但是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性(Vue 为什么不能检测数组变动 )。为了解决这个问题,经过 vue 内部处理后可以使用以下几种方法来监听数组

push();
pop();
shift();
unshift();
splice();
sort();
reverse();

由于只针对了以上 7 种方法进行了 hack 处理,所以其他数组的属性也是检测不到的,还是具有一定的局限性。

Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 2.x 里,是通过 递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择。
Proxy 可以劫持整个对象,并返回一个新的对象。Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。

1.32.谈一谈 nextTick 的原理

JS 运行机制

JS 执行是单线程的,它是基于事件循环的。事件循环大致分为以下几个步骤:

所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
主线程不断重复上面的第三步。

【吐血整理】Vue.js面試題彙總及答案解析(快來收藏)
主线程的执行过程就是一个 tick,而所有的异步结果都是通过 “任务队列” 来调度。 消息队列中存放的是一个个的任务(task)。 规范中规定 task 分为两大类,分别是 macro task 和 micro task,并且每个 macro task 结束后,都要清空所有的 micro task。

for (macroTask of macroTaskQueue) {
  // 1. Handle current MACRO-TASK
  handleMacroTask();

  // 2. Handle all MICRO-TASK
  for (microTask of microTaskQueue) {
    handleMicroTask(microTask);
  }}

在浏览器环境中 :

常见的 macro task 有 setTimeout、MessageChannel、postMessage、setImmediate

常见的 micro task 有 MutationObsever 和 Promise.then

异步更新队列

可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。
如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。
然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。
在 vue2.5 的源码中,macrotask 降级的方案依次是:setImmediate、MessageChannel、setTimeout

vue 的 nextTick 方法的实现原理:

vue 用异步队列的方式来控制 DOM 更新和 nextTick 回调先后执行
microtask 因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
考虑兼容问题,vue 做了 microtask 向 macrotask 的降级方案

1.33.谈谈 Vue 事件机制,手写on,off,emit,once

Vue 事件机制 本质上就是 一个 发布-订阅 模式的实现。

class Vue {
  constructor() {
    //  事件通道调度中心
    this._events = Object.create(null);
  }
  $on(event, fn) {
    if (Array.isArray(event)) {
      event.map(item => {
        this.$on(item, fn);
      });
    } else {
      (this._events[event] || (this._events[event] = [])).push(fn);
    }
    return this;
  }
  $once(event, fn) {
    function on() {
      this.$off(event, on);
      fn.apply(this, arguments);
    }
    on.fn = fn;
    this.$on(event, on);
    return this;
  }
  $off(event, fn) {
    if (!arguments.length) {
      this._events = Object.create(null);
      return this;
    }
    if (Array.isArray(event)) {
      event.map(item => {
        this.$off(item, fn);
      });
      return this;
    }
    const cbs = this._events[event];
    if (!cbs) {
     return this;
    }
    if (!fn) {
      this._events[event] = null;
      return this;
    }
    let cb;
    let i = cbs.length;
    while (i--) {
      cb = cbs[i];
      if (cb === fn || cb.fn === fn) {
        cbs.splice(i, 1);
        break;
      }
    }
    return this;
  }
  $emit(event) {
    let cbs = this._events[event];
    if (cbs) {
      const args = [].slice.call(arguments, 1);
      cbs.map(item => {
        args ? item.apply(this, args) : item.call(this);
      });
    }
    return this;
  }}

1.34.vue-router有哪几种导航钩子?

三种:

一种是全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。第二种:组件内的钩子;第三种:单独路由独享组件

1.35.vuex是什么?怎么使用?哪种功能场景使用它?

vue框架中状态管理。在main.js引入store,注入。新建了一个目录store,…… export 。
场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车
【吐血整理】Vue.js面試題彙總及答案解析(快來收藏)

1.36.MVVM和MVC差別?和其他框架(jquery)區別?那些場景適用?

MVVM和MVC都是一種設計思想,主要是MVC中的Controller演變成ViewModel,,MVVM主要透過資料顯示視圖層而不是操作節點,解決了MVC中大量的DOM操作使頁面渲染效能降低,載入速度慢,影響使用者體驗問題。主要用於資料操作比較多的場景。
場景:資料操作比較多的場景,更方便
【吐血整理】Vue.js面試題彙總及答案解析(快來收藏)

#1.37.聊聊你對Vue.js的範本編譯的理解

簡而言之,就是先轉換成AST樹,再得到的渲染函數返回VNODE(Vue公司的虛擬DOM節點)
詳情步驟:

首先,透過編譯編譯器把模板編譯成AST語法樹(抽象語法樹即原始碼的抽象語法結構的樹狀表現),編譯是createCompiler的回傳值,createCompiler是用以創建編譯器的。負責合併選項。
然後,AST會經過產生(將AST語法樹轉換成渲染功能字串的過程)得到渲染函數,渲染的回傳值是VNode,VNode是Vue的虛擬DOM節點,裡面有(標籤名,子節點,文本等等)

1.38.的作用是什麼,如何使用?

答案:包裹動態元件時,會快取不活動的元件實例,主要用於保留元件狀態或避免重新渲染;
使用:簡單頁面時
快取:
不緩存:

1.39.vue和react區別

相同點:都鼓勵元件化,都有'props'的概念,都有自己的建構工具,Reat與Vue只有框架的骨架,其他的功能如路由、狀態管理等是框架分離的元件。

不同點:React:資料流單向,語法—JSX,在React中你需要使用setState()方法去更新狀態。 Vue:資料雙向綁定,語法–HTML,state物件並不是必須的,資料由data屬性在Vue物件中進行管理。適用於小型應用,但對於大型應用而言較不適合。

1.40.vue生命週期的理解?

參考大神文章:vue筆記- 生命週期第二次學習與理解
【吐血整理】Vue.js面試題彙總及答案解析(快來收藏)

beforeCreate是new Vue()之後觸發的第一個鉤子,在當前階段data、methods、computed以及watch上的資料和方法都不能被存取。

created在實例創建完成後發生,當前階段已經完成了數據觀測,也就是可以使用數據,更改數據,在這裡更改數據不會觸發updated函數。可以做一些初始資料的獲取,在當前階段無法與Dom進行交互,如果非要想,可以透過vm.$nextTick來存取Dom。

beforeMount發生在掛載之前,在這之前template模板已導入渲染函數編譯。而當前階段虛擬Dom已經創建完成,即將開始渲染。在此時也可以對資料進行更改,不會觸發updated。

mounted在掛載完成後發生,在當前階段,真實的Dom掛載完畢,資料完成雙向綁定,可以存取到Dom節點,使用$refs屬性對Dom進行操作。

beforeUpdate發生在更新之前,也就是響應式數據發生更新,虛擬dom重新渲染之前被觸發,你可以在當前階段進行更改數據,不會造成重渲染。

updated發生在更新完成之後,目前階段元件Dom已完成更新。要注意的是避免在此期間更改數據,因為這可能會導致無限循環的更新。

beforeDestroy發生在實例銷毀之前,在目前階段實例完全可以被使用,我們可以在這時進行善後收尾工作,例如清除計時器。

destroyed發生在實例銷毀之後,這個時候只剩下了dom空殼。元件已被拆解,資料綁定被卸除,監聽被移出,子實例也統統被銷毀。

1.41.Vue2.x與Vue3.x渲染器的diff演算法分別說一下

簡單來說,diff演算法有以下過程

#1.同級比較,再比較子節點
2.先判斷一方有子節點一方沒有子節點的情況(如果新的children沒有子節點,將舊的子節點移除)
3.比較都有子節點的情況(核心diff)
3.遞迴比較子節點

正常Diff兩棵樹的時間複雜度是O(n^3),但實際情況下我們很少會進行跨層級的移動DOM,所以Vue將Diff進行了最佳化,從O(n^3) -> O(n),只有當新舊children都為多個子節點時才需要用核心的Diff演算法進行同層級比較。

Vue2的核心Diff演算法採用了雙端比較的演算法,同時從新舊children的兩端開始進行比較,借助key值找到可重複使用的節點,再進行相關操作。相較於React的Diff演算法,同樣情況下可以減少移動節點次數,減少不必要的效能損耗,更加的優雅。

Vue3.x借鑒了
ivi演算法和inferno演算法

在創建VNode時就確定其類型,以及在mount/patch 的過程中採用位元運算來判斷一個VNode的類型,在這個基礎之上再配合核心的Diff演算法,使得效能上較Vue2.x有了提升。 (實際的實作可以結合Vue3.x源碼看。)

此演算法中也運用了動態規劃的想法來求解最長遞歸子序列。

1.42.你都做過哪些Vue的效能最佳化?

編碼階段

1.盡量減少data中的數據,data中的數據都會增加getter和setter,會收集對應的2.watcher
3 .v-if和v-for不能連用
4.如果需要使用v-for給每項元素綁定事件時使用事件代理
5.SPA 頁面採用keep-alive快取元件
6.在更多的情況下,使用v-if替代v-show
7.key保證唯一
8.使用路由懶載入、非同步元件
9.防手震、節流
10.第三方模組按需導入
11.長列表捲動到視覺區域動態載入
12.圖片懶載入

##SEO最佳化

1.預先渲染

2.服務端渲染SSR

打包最佳化

1.壓縮程式碼

2.Tree Shaking/Scope Hoisting
# 3.使用cdn載入第三方模組
4.多執行緒打包happypack
5.splitChunks抽離公共檔案
6.sourceMap優化

使用者體驗


##1.骨架螢幕 2.PWA也可以使用快取(客戶端快取、服務端快取)最佳化、服務端開啟gzip壓縮等。

1.43.hash路由與history路由實作原理說一下


#location.hash
的值實際上是URL中#後面的東西。

history

實際上採用了HTML5中提供的API來實現,主要有
history.pushState()

history.replaceState()

1.44.SPA 單一頁面的理解,它的優缺點分別是什麼



SPA( single-page application )僅在Web 頁面初始化時載入對應的HTML 、JavaScript 和CSS
一旦頁面載入完成,SPA 不會因為使用者的操作而進行頁面的重新載入或跳轉
取而代之的是利用路由機制實現HTML 內容的變換, UI 與使用者的交互,避免頁面的重新載入

優點:

1、使用者體驗好、快,內容的改變不需要重新載入整個頁面,避免了不必要的跳躍和重複渲染 2 、基於上面一點,SPA 相對對伺服器壓力小

3、前後端職責分離,架構清晰,前端進行交互邏輯,後端負責資料處理

##缺點:
1、初次載入耗時多:為實現單頁Web 應用功能及顯示效果, 需要在載入頁面的時候將JavaScript、CSS 統一加載,部分頁面按需載入 2、前進後退路由管理:由於單頁應用程式在一個頁面中顯示所有的內容,
所以不能使用瀏覽器的前進後退功能,所有的頁面切換需要自己建立堆疊管理 3、SEO 難度較大:由於所有的內容都在一個頁面中動態替換顯示,所以在SEO 上其有著天然的弱勢

1.45.vue.cli中怎樣使用自訂的元件?有遇到過哪些問題嗎?

第一步:在components目錄新建立你的元件檔案(indexPage.vue),script一定要

export default {}

第二步:在需要用的頁面(元件)中導入:import indexPage from '@/components/indexPage.vue'
第三步:注入到vue的子元件的components屬性上面, components:{indexPage}
第四步:在template視圖view中使用, 例如有indexPage命名,使用的時候則index-page

######1.46 .vue如何實作按需載入配合webpack設定############webpack中提供了###require.ensure()###來實作按需載入。先前引入路由是透過import 這樣的方式引入,改為const定義的方式進行引入。 ### 不進行頁面按需載入引入方式:###import home from '../../common/home.vue'###### 進行頁面按需載入的引入方式:###const home = r => require.ensure( [], () => r (require('../../common/home.vue')))#######

二、组件 Component

2.1.vue中如何编写可复用的组件 (编写组件的原则)

以组件功能命名
只负责ui的展示和交互动画,不要在组件里与服务器打交道(获取异步数据等)
可复用组件不会因组件使用的位置、场景而变化。尽量减少对外部条件的依赖。

2.2.如何让CSS只在当前组件中起作用?

在每一个Vue.js组件中都可以定义各自的CSS、 JavaScript代码。如果希望组件内写的CSS只对当前组件起作用,只需要在Style标签添加Scoped属性即可

2.3.keep-alive是什么?

如果需要在组件切换的时候,保存一些组件的状态防止多次渲染,就可以使用 keep-alive 组件包裹需要保存的组件。

两个重要属性,include 缓存组件名称,exclude 不需要缓存的组件名称。

2.4.如何在 Vue. js动态插入图片

对“src”属性插值将导致404请求错误。应使用 v-bind:src (简写:src)格式代替。

2.5.父子组件的生命周期顺序(可参照上方图解)

加载渲染过程:
beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
子组件更新过程:父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程:父beforeUpdate->父updated
销毁过程:父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

三、Vuex

3.1.vuex的核心概念

1.state => 基本数据
2.getters => 从基本数据派生的数据
3.mutations => 修改数据,同步
4.actions => 修改数据,异步 (Action 提交的是 mutation,而不是直接变更状态)
5.modules => 模块化Vuex

3.2.vuex是什么?怎么使用?哪种功能场景使用它?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理器,采用集中式存储管理应用的所有组件的状态,主要是为了多页面、多组件之间的通信。
Vuex有5个重要的属性,分别是 State、Getter、Mutation、Action、Module,由 view 层发起一个 Action 给 Mutation,在 Mutation 中修改状态,返回新的状态,通过 Getter暴露给 view层的组件或者页面,页面监测到状态改变于是更新页面。如果你的项目很简单,最好不要使用 Vuex,对于大型项目,Vuex 能够更好的帮助我们管理组件外部的状态,一般可以运用在购物车、登录状态、播放等场景中。

3.3.多个组件之间如何拆分各自的state,每块小的组件有自己的状态,它们之间还有一些公共的状态需要维护,如何思考这块

1.公共的数据部分可以提升至和他们最近的父组件,由父组件派发
2.公共数据可以放到vuex中统一管理,各组件分别获取

3.4.Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中?

1.如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。

2.如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。如果不要复用这个请求,那么直接写在vue文件里很方便

3.5.Vuex中如何异步修改状态

actions与mutations作用类似,都是可以对状态进行修改。不同的是actions是异步操作的。

actions是可以调用Mutations里的方法的。

const actions={
	addActions(context){
		context.commit('add',10);//调用mutations中的方法
		setTimeout(()=>{context.commit('reduce')},5000)
	//	setTimeOut(()=>{context.commit('reduce')},3000);
		console.log('我比reduce提前执行');
	},
	
	reduceActions({commit}){
		commit('reduce');
	}}

3.6.Vuex中actions和mutations的区别

Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }})

Action Action 类似于 mutation,不同在于:

Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }})

3.7.怎么在组件中批量使用Vuex的state状态?

使用mapState辅助函数, 利用对象展开运算符将state混入computed对象中

import {mapState} from 'vuex' export default{ computed:{ ...mapState(['price','number']) } }

3.8.Vuex中状态是对象时,使用时要注意什么?

对象是引用类型,复制后改变属性还是会影响原始数据,这样会改变state里面的状态,是不允许,所以先用深度克隆复制对象,再修改。

四、Router

4.1.vue-router 路由模式有几种

1.Hash: 使用 URL 的 hash 值来作为路由。支持所有浏览器。 带#。如:http://localhost:8080/#/pageA。改变hash,浏览器本身不会有任何请求服务器动作的,但是页面状态和url已经关联起来了。
2.History: 以来 HTML5 History API 和服务器配置。参考官网中 HTML5 History 模式,不带#, 如:http://localhost:8080/ 正常的而路径,并没有#。基于HTML5的 pushState、replaceState实现
3.Abstract: 支持所有 javascript 运行模式。如果发现没有浏览器的 API,路由会自动强制进入这个模式。

4.2.vue-router如何定义嵌套路由

通过children 数组:

const router = new VueRouter({
  routes: [
    {
      path: "/parentPage",
      component: testPage,
      children: [
        {
          path: "/childrenA",
          component: childrenComponentA,
        },
        {
          path: "/childrenB",
          component: childrenComponentB,
        },
      ],
    },
    {
      // 其他和parentPage平级的路由
    },
  ],});

4.3.vue-router有哪几种导航钩子?

1.全局导航钩子:router.beforeEach(to,from,next)
2.组件内的钩子beforeRouteEnter (to, from, next) beforeRouteUpdate (to, from, next) beforeRouteLeave (to, from, next)
3.单独路由独享组件 beforeEnter: (to, from, next)

参数:有to(去的那个路由)、from(离开的路由)、next(一定要用这个函数才能去到下一个路由,如果不用就拦截)最常用就这几种

4.4. $ route和$ router的区别

1、$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。

1.$route.path 字符串,对应当前路由的路径,总是解析为绝对路径如"/foo/bar"。
2. $route.params 一个 key/value 对象,包含了 动态片段 和 全匹配片段, 如果没有路由参数,就是一个空对象。
3. $route.query 一个 key/value 对象,表示 URL 查询参数。 例如,对于路径 /foo?user=1,则有$route.query.user == 1, 如果没有查询参数,则是个空对象
4. $route.hash 当前路由的hash值 (不带#) ,如果没有 hash 值,则为空字符串
5. $route.fullPath 完成解析后的 URL,包含查询参数和hash的完整路径。
6. $route.matched 数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
7. $route.name 当前路径名字
8. $ route.meta 路由元信息

2、$router是“路由实例”对象包括了路由的跳转方法,钩子函数等

实例方法:

1)、push

1.字符串this.$router.push('home')
2. 对象this.$router.push({path:'home'})
3. 命名的路由this.$router.push({name:'user',params:{userId:123}})
4.带查询参数,变成 /register?plan=123this.$router.push({path:'register',query:{plan:'123'}})
push方法其实和是等同的。
注意:push方法的跳转会向 history 栈添加一个新的记录,当我们点击浏览器的返回按钮时可以看到之前的页面。

2)、go
页面路由跳转
前进或者后退this.$router.go(-1) // 后退

3)、replace
push方法会向 history 栈添加一个新的记录,而replace方法是替换当前的页面,
不会向 history 栈添加一个新的记录

4.5.路由之间跳转的方式

1.声明式(标签跳转)
2.编程式( js跳转)

4.6.active-class是哪个组件的属性

vue-router 模块 的router-link组件

4.7.vue-router实现路由懒加载(动态加载路由)

把不同路由对应的组件分割成不同的代码块,然后当路由被访问时才加载对应的组件即为路由的懒加载,可以加快项目的加载速度,提高效率

const router = new VueRouter({
  routes: [
    {
      path: '/home',
      name: 'Home',      
      component:() = import('../views/home')
	}
  ]})

4.8.怎么定义vue-router的动态路由以及如何获取传过来的动态参数?

在router目录下的index.js文件中,对path属性加上/:id
使用router对象的params id

面试官:我难道问不倒这小子了?(面试官持续懵逼中) 对大家有帮助的话三连呀~ 持续更新

【相關影片教學推薦:vuejs入門教學web前端入門

以上是【吐血整理】Vue.js面試題彙總及答案解析(快來收藏)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除