ホームページ > 記事 > ウェブフロントエンド > 2023 年の Vue の高頻度面接質問の共有 (回答分析付き)
この記事では、2023 年に選ばれた、収集する価値のある高頻度の面接の質問 (回答付き) をいくつかまとめています。一定の参考値があるので、困っている友達が参考になれば幸いです。
Vue-router ナビゲーション ガードとは何ですか?push(); pop(); shift(); unshift(); splice(); sort(); reverse();
上記 7 つのメソッドのみがハッキングされるため、他の配列のプロパティを検出することはできません。特定の制限。Object.defineProperty はオブジェクトのプロパティのみをハイジャックできるため、各オブジェクトの各プロパティをトラバースする必要があります。 Vue 2.x では、データ モニタリングはデータ オブジェクトを再帰的に走査することによって実現されます。属性値もオブジェクトである場合は、深い走査が必要です。完全なオブジェクトをハイジャックできる場合は、明らかにそれがより良い選択です。
v-for キーを追加する理由プロキシはオブジェクト全体をハイジャックして、新しいオブジェクトを返すことができます。プロキシはオブジェクトをプロキシするだけでなく、配列をプロキシすることもできます。動的に追加された属性をプロキシすることもできます。
: key を使用すると、 not インプレース再利用は、sameNode 関数 a.key === b.key 比較で回避できます。したがって、より正確になります。
: キーの一意性を使用してマップ オブジェクトを生成し、対応するノードを取得します。これはトラバーサル メソッドよりも高速です。
#テンプレートを
ast に変換します。オブジェクトを使用して実際の JS 構文を記述します (実際の DOM を仮想 DOM に変換します) 最適化します。 tree
Put
ast この一連のデータ更新の後、ビューは非同期的に更新されます。コアアイデア 次のティック
。 dep.notify()
ウォッチャーに更新を通知します。
ウォッチャーの update
、 queueWatcher を呼び出します。 in sequence
ウォッチャーをキューに入れると、nextTick (lushSchedulerQueue
) が次のティックでウォッチャー キューを (非同期的に) 更新します。 vue コンポーネント内のデータはなぜ関数でなければならないのですか?
MVC の正式名は Model View Controller、つまりモデルビューです。 (ビュー) - コントローラーの略語、ソフトウェア設計モデル
モデル (モデル): アプリケーション データ ロジックを処理するために使用されるアプリケーションの一部です。通常、モデル オブジェクトはデータベース内のデータへのアクセスを担当します。View (ビュー): データの表示を処理するアプリケーションの一部です。通常、ビューはモデル データに基づいて作成されます。MVVM は新しい VM クラスを追加しました MVVM 与 MVC 最大的区别就是:它实现了 View 和 Model 的自动同步,也就是当 Model 的属性改变时,我们不用再自己手动操作 Dom 元素,来改变 View 的显示,而是改变属性后该属性对应 View 层显示会自动改变(对应Vue数据驱动的思想) 整体看来,MVVM 比 MVC 精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作 DOM 元素。因为在 MVVM 中,View 不知道 Model 的存在,Model 和 ViewModel 也观察不到 View,这种低耦合模式提高代码的可重用性 那么问题来了 为什么官方要说 Vue 没有完全遵循 MVVM 思想呢? 1)Vue为什么要用vm.$set() 解决对象新增属性不能响应的问题 Vue使用了Object.defineProperty实现双向数据绑定 在初始化实例时对属性执行 getter/setter 转化 属性必须在data对象上存在才能让Vue将它转换为响应式的(这也就造成了Vue无法检测到对象属性的添加或删除) 所以Vue提供了Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value) 2)接下来我们看看框架本身是如何实现的呢? 我们阅读以上源码可知,vm.$set 的实现原理是: 如果目标是数组,直接使用数组的 splice 方法触发相应式; 如果目标是对象,会先判读属性是否存在、对象是否是响应式, 最终如果要对属性进行响应式处理,则是通过调用 defineReactive 方法进行响应式处理 Vue3.x 改用 Proxy 替代 Object.defineProperty。因为 Proxy 可以直接监听对象和数组的变化,并且有多达 13 种拦截方法。 相关代码如下 简单说,Vue的编译过程就是将 首先解析模版,生成 Vue的数据是响应式的,但其实模板中并不是所有的数据都是响应式的。有一些数据首次渲染后就不会再变化,对应的DOM也不会变化。那么优化过程就是深度遍历AST树,按照相关条件对树节点进行标记。这些被标记的节点(静态节点)我们就可以 编译的最后一步是 优点: 缺点: 再レンダリングはすぐには同期的に実行されません。 Vue の応答性は、データが変更された直後に DOM が変更されることを意味するのではなく、DOM が特定の戦略に従って更新されることを意味します。 Vue は DOM を非同期的に更新します。データ変更をリッスンしている限り、Vue はキューを開き、同じイベント ループ内で発生するすべてのデータ変更をバッファーに入れます。 同じウォッチャーが複数回トリガーされた場合、キューにプッシュされるのは 1 回だけです。バッファリング中のこの重複排除は、不必要な計算や DOM 操作を回避するために重要です。次に、次のイベント ループ ティックで、Vue はキューをフラッシュし、実際の (重複排除された) 作業を実行します。 時間計算量: 理解: 最小限の更新、 diff アルゴリズムの最適化戦略 : 4 つのヒット検索、4 つのポインター Vue の利点 完全なナビゲーション解析プロセス: ナビゲーションがトリガーされます。 #ナビゲーションを確認しました。 グローバル afterEach フックを呼び出します。 DOM 更新をトリガーします。 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。 简而言之,就是先转化成AST树,再得到的render函数返回VNode(Vue的虚拟DOM节点),详细步骤如下: 首先,通过compile编译器把template编译成AST语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以创建编译器的。另外compile还负责合并option。 然后,AST会经过generate(将AST语法树转化成render funtion字符串的过程)得到render函数,render的返回值是VNode,VNode是Vue的虚拟DOM节点,里面有(标签名、子节点、文本等等) Vue 实现响应式并不是在数据发生后立即更新 DOM,使用 什么时候被调用? 每个生命周期内部可以做什么? ajax放在哪个生命周期?:一般放在 受现代 JavaScript 的限制 ,Vue 无法检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 Vue 将它转换为响应式的。但是 Vue 提供了 我们查看对应的 Vue 源码: 我们阅读以上源码可知,vm.$set 的实现原理是:注意:Vue 并没有完全遵循 MVVM 的思想 这一点官网自己也有说明
Vue 为什么要用 vm.$set() 解决对象新增属性不能响应的问题 ?你能说说如下代码的实现原理么?
Vue 源码位置:vue/src/core/instance/index.js
export function set (target: Array<any> | Object, key: any, val: any): any {
// target 为数组
if (Array.isArray(target) && isValidArrayIndex(key)) {
// 修改数组的长度, 避免索引>数组长度导致splcie()执行有误
target.length = Math.max(target.length, key)
// 利用数组的splice变异方法触发响应式
target.splice(key, 1, val)
return val
}
// key 已经存在,直接修改属性值
if (key in target && !(key in Object.prototype)) {
target[key] = val
return val
}
const ob = (target: any).__ob__
// target 本身就不是响应式数据, 直接赋值
if (!ob) {
target[key] = val
return val
}
// 对属性进行响应式处理
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}
defineReactive 方法就是 Vue 在初始化对象时,给对象属性采用 Object.defineProperty 动态添加 getter 和 setter 的功能所调用的方法
Vue3.0 和 2.0 的响应式原理区别
import { mutableHandlers } from "./baseHandlers"; // 代理相关逻辑
import { isObject } from "./util"; // 工具方法
export function reactive(target) {
// 根据不同参数创建不同响应式对象
return createReactiveObject(target, mutableHandlers);
}
function createReactiveObject(target, baseHandler) {
if (!isObject(target)) {
return target;
}
const observed = new Proxy(target, baseHandler);
return observed;
}
const get = createGetter();
const set = createSetter();
function createGetter() {
return function get(target, key, receiver) {
// 对获取的值进行放射
const res = Reflect.get(target, key, receiver);
console.log("属性获取", key);
if (isObject(res)) {
// 如果获取的值是对象类型,则返回当前对象的代理对象
return reactive(res);
}
return res;
};
}
function createSetter() {
return function set(target, key, value, receiver) {
const oldValue = target[key];
const hadKey = hasOwn(target, key);
const result = Reflect.set(target, key, value, receiver);
if (!hadKey) {
console.log("属性新增", key, value);
} else if (hasChanged(value, oldValue)) {
console.log("属性值被修改", key, value);
}
return result;
};
}
export const mutableHandlers = {
get, // 当获取属性时调用此方法
set, // 当修改属性时调用此方法
};
Vue模版编译原理知道吗,能简单说一下吗?
template
转化为render
函数的过程。会经历以下阶段:
AST语法树
(一种用JavaScript对象的形式来描述整个模板)。 使用大量的正则表达式对模板进行解析,遇到标签、文本的时候都会执行对应的钩子进行相关处理。跳过对它们的比对
,对运行时的模板起到很大的优化作用。将优化后的AST树转换为可执行的代码
。
MVVM的优缺点?
Vue データのプロパティの値が変更された後、ビューはすぐに同期的に再レンダリングされますか?
diff アルゴリズム
ツリーの完全な
diff アルゴリズムの時間計算量は # です。 # #O(n*3)
、Vue が最適化して O(n)
に変換します。
key
は非常に重要です。これは、このノードの一意の識別子となり、変更の前後で同じ DOM ノードであることを diff
アルゴリズムに伝えます v-for
key
があるのはなぜですか。key
がないと激しく再利用されます。ノードの移動やノードの追加 (DOM の変更)、key# の追加などの例を挙げてください。 ## は DOM の操作を減らしてのみ移動します。
古いものと新しいもの (最初に先頭を比較し、次に挿入とノードの削除)
次のような単純な概念です。問題はありませんか?
軽量フレームワーク: データを構築するビューのコレクションであるビュー レイヤーのみに焦点を当てています。サイズはわずか数十です
kb;
シンプルで学習しやすい: によって開発されました。中国語、中国語のドキュメント、言語の壁がなく、理解と学習が簡単;
コンポーネント化:
react のカプセル化を実現し、再利用することで、単一ページのアプリケーションを構築する際に独自の利点があります。
ビュー、データの分離、および構造: ロジック コードを変更せずに、データを操作するだけでデータの変更を簡素化します。関連操作;
操作ノードは使用されなくなり、
dom 操作が大幅に解放されますが、特定の操作は依然として
dom ですが、別の方法で行われます。
実行速度が速い:
react を操作する場合、パフォーマンスの点では
vue に大きな利点があります。
ルーティングフックの実行プロセスとフック関数の種類: グローバル ガード、ルーティング ガード、コンポーネント ガード
Vue.js的template编译
$nextTick 是什么?
vm.$nextTick
是在下次 DOM 更新循环结束之后立即执行延迟回调。在修改数据之后使用,则可以在回调中获取更新后的 DOM。说说Vue的生命周期吧
watch/event
事件回调。无 $el
. render
函数首次被调用vm.$el
替换,并挂载到实例上去之后调用改钩子。
mounted
中,保证逻辑统一性,因为生命周期是同步执行的, ajax
是异步执行的。单数服务端渲染 ssr
同一放在 created
中,因为服务端渲染不支持 mounted
方法。 什么时候使用beforeDestroy?:当前页面使用 $on
,需要解绑事件。清楚定时器。解除事件绑定, scroll mousemove
。Vue 怎么用 vm.$set() 解决对象新增属性不能响应的问题 ?
Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value)
来实现为对象添加响应式属性,那框架本身是如何实现的呢?vue/src/core/instance/index.js
export function set (target: Array<any> | Object, key: any, val: any): any {
// target 为数组
if (Array.isArray(target) && isValidArrayIndex(key)) {
// 修改数组的长度, 避免索引>数组长度导致splcie()执行有误
target.length = Math.max(target.length, key)
// 利用数组的splice变异方法触发响应式
target.splice(key, 1, val)
return val
}
// key 已经存在,直接修改属性值
if (key in target && !(key in Object.prototype)) {
target[key] = val
return val
}
const ob = (target: any).__ob__
// target 本身就不是响应式数据, 直接赋值
if (!ob) {
target[key] = val
return val
}
// 对属性进行响应式处理
defineReactive(ob.value, key, val)
ob.dep.notify()
return val
}
以上が2023 年の Vue の高頻度面接質問の共有 (回答分析付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。