Dieser Artikel fasst für Sie einige Auswahlmöglichkeiten aus dem Jahr 2023 zusammen, die es wert sind, gesammelt zu werdenvueHochfrequente Interviewfragen (mit Antworten). Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.
(Lernvideo-Sharing: vue-Video-Tutorial)
Object.defineProperty selbst verfügt über eine gewisse Fähigkeit, Änderungen in Array-Indizes zu überwachen, aber in Vue wurde diese Funktion unter Berücksichtigung der Kosteneffizienz von Leistung/Erfahrung aufgegeben (warum Vue Array-Änderungen nicht erkennen kann). Um dieses Problem zu lösen, können Sie nach der internen Vue-Verarbeitung die folgenden Methoden zur Überwachung des Arrays verwenden
push(); pop(); shift(); unshift(); splice(); sort(); reverse();
Da nur die oben genannten 7 Methoden gehackt werden, können die Eigenschaften anderer Arrays nicht erkannt werden und es gibt immer noch bestimmte Einschränkungen für sie. Einschränkung.
Object.defineProperty kann nur die Eigenschaften eines Objekts kapern, daher müssen wir jede Eigenschaft jedes Objekts durchlaufen. In Vue 2.x wird die Datenüberwachung durch Rekursion + Durchquerung des Datenobjekts erreicht. Wenn der Attributwert auch ein Objekt ist, ist eine tiefe Durchquerung erforderlich, wenn ein vollständiges Objekt gekapert werden kann.
Proxy kann das gesamte Objekt kapern und ein neues Objekt zurückgeben. Proxy kann nicht nur Proxy-Objekte, sondern auch Proxy-Arrays vertreten. Sie können auch dynamisch hinzugefügte Attribute als Proxy verwenden.
Wenn der Schlüssel nicht verwendet wird, verwendet Vue einen Algorithmus, der dynamische Elemente minimiert und versucht, Elemente desselben Typs so weit wie möglich an Ort und Stelle zu ändern/wiederzuverwenden. Der Schlüssel ist die einzige Markierung für vnode in Vue. Durch diesen Schlüssel kann unsere Diff-Operation genauer und schneller sein. Genauer: Da der Schlüssel nicht an derselben Stelle wiederverwendet wird. key === b.key kann die direkte Wiederverwendung während des Vergleichs vermeiden. Es wird also genauer sein.
Schneller: Die Verwendung der Eindeutigkeit des Schlüssels zum Generieren eines Kartenobjekts zum Erhalten des entsprechenden Knotens ist schneller als die Traversal-Methode
So wechseln Sie vom echten DOM zum virtuellen DOM
ast
-Baum. ast
verwendet Objekte, um die echte JS-Syntax zu beschreiben (reales DOM in virtuelles umwandeln). DOM) ast
树, ast
用对象来描述真实的JS语法(将真实DOM转换成虚拟DOM)
优化树
将 ast
树生成代码
Vue
是组件级更新,如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染,所以为了性能, Vue
会在本轮数据更新后,在异步更新视图。核心思想 nextTick
。
dep.notify()
通知 watcher进行更新, subs[i].update
依次调用 watcher 的 update
, queueWatcher
将watcher 去重放入队列, nextTick( flushSchedulerQueue
ast
-BaumWarum verwendet Vue asynchrones Rendering?
Vue
ist ein Update auf Komponentenebene. Wenn keine asynchronen Updates verwendet werden, wird die aktuelle Komponente jedes Mal neu gerendert, wenn die Daten aktualisiert werden Hier wird >Vue verwendet. Nach der Runde der Datenaktualisierungen wird die Ansicht asynchron aktualisiert. Kernidee nextTick
. dep.notify()
benachrichtigt den Watcher zur Aktualisierung, subs[i].update
ruft wiederum das update
des Watchers auf, queueWatcher Platzieren Sie den Watcher in der Warteschlange und nextTick (<code> FlushSchedulerQueue
) aktualisiert die Watcher-Warteschlange im nächsten Tick (asynchron). Warum müssen Daten in der Vue-Komponente eine Funktion sein?
Objekte sind Referenztypen, da die Datenobjekte alle auf dasselbe Datenobjekt verweisen. Wenn Daten in einer Komponente geändert werden, werden die Daten in anderen wiederverwendeten Komponenten gleichzeitig geändert Objekt Funktion, da jedes Mal, wenn ein neues Objekt (eine Instanz von Objekt) zurückgegeben wird und die Referenzadresse unterschiedlich ist, dieses Problem nicht auftritt.Modell: Der Teil der Anwendung das die Logik der Anwendungsdaten verwaltet. Normalerweise ist das Modellobjekt für den Zugriff auf Daten in der Datenbank verantwortlich.
Ansicht (Ansicht): Dies ist der Teil der Anwendung, der die Datenanzeige übernimmt. Normalerweise werden Ansichten basierend auf Modelldaten erstellt.
🎜Controller: Dies ist der Teil der Anwendung, der die Benutzerinteraktion abwickelt. Normalerweise ist der Controller dafür verantwortlich, Daten aus der Ansicht zu lesen, Benutzereingaben zu steuern und Daten an das Modell zu senden: Ein Satz Beschreibung ist, dass der Controller dafür verantwortlich ist, die Daten des Modells mithilfe der Ansicht anzuzeigen Das heißt, das Modell wird im Controller angezeigt. Die Daten werden der Ansicht zugewiesen. 🎜🎜🎜MVVM🎜🎜🎜MVVM hat eine neue VM-Klasse hinzugefügt🎜MVVM 与 MVC 最大的区别就是:它实现了 View 和 Model 的自动同步,也就是当 Model 的属性改变时,我们不用再自己手动操作 Dom 元素,来改变 View 的显示,而是改变属性后该属性对应 View 层显示会自动改变(对应Vue数据驱动的思想)
整体看来,MVVM 比 MVC 精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作 DOM 元素。因为在 MVVM 中,View 不知道 Model 的存在,Model 和 ViewModel 也观察不到 View,这种低耦合模式提高代码的可重用性
注意:Vue 并没有完全遵循 MVVM 的思想 这一点官网自己也有说明
那么问题来了 为什么官方要说 Vue 没有完全遵循 MVVM 思想呢?
- 严格的 MVVM 要求 View 不能和 Model 直接通信,而 Vue 提供了$refs 这个属性,让 Model 可以直接操作 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)接下来我们看看框架本身是如何实现的呢?
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 }
我们阅读以上源码可知,vm.$set 的实现原理是:
如果目标是数组,直接使用数组的 splice 方法触发相应式;
如果目标是对象,会先判读属性是否存在、对象是否是响应式,
最终如果要对属性进行响应式处理,则是通过调用 defineReactive 方法进行响应式处理
defineReactive 方法就是 Vue 在初始化对象时,给对象属性采用 Object.defineProperty 动态添加 getter 和 setter 的功能所调用的方法
Vue3.x 改用 Proxy 替代 Object.defineProperty。因为 Proxy 可以直接监听对象和数组的变化,并且有多达 13 种拦截方法。
相关代码如下
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对象的形式来描述整个模板)。 使用大量的正则表达式对模板进行解析,遇到标签、文本的时候都会执行对应的钩子进行相关处理。
Vue的数据是响应式的,但其实模板中并不是所有的数据都是响应式的。有一些数据首次渲染后就不会再变化,对应的DOM也不会变化。那么优化过程就是深度遍历AST树,按照相关条件对树节点进行标记。这些被标记的节点(静态节点)我们就可以跳过对它们的比对
,对运行时的模板起到很大的优化作用。
编译的最后一步是将优化后的AST树转换为可执行的代码
。
优点:
缺点:
diff
-Algorithmus eines Baums ist eine Zeitkomplexität von O(n*3)
, optimiert durch vue Convert zu O(n)
. Verstehen Sie: diff
算法是一个时间复杂度为 O(n*3)
,vue进行优化转化成 O(n)
。
理解:
最小量更新, key
很重要。这个可以是这个节点的唯一标识,告诉 diff
算法,在更改前后它们是同一个DOM节点
v-for
为什么要有 key
,没有 key
会暴力复用,举例子的话随便说一个比如移动节点或者增加节点(修改DOM),加 key
只会移动减少操作DOM。diff算法的优化策略:四种命中查找,四个指针
--- 问完上面这些如果都能很清楚的话,基本O了 ---
以下的这些简单的概念,你肯定也是没有问题的啦?
kb
;angular
的特点,在数据操作方面更为简单;react
的优点,实现了 html
的封装和重用,在构建单页面应用方面有着独特的优势;dom
操作是非常耗费性能的,不再使用原生的 dom
操作节点,极大解放 dom
操作,但具体操作的还是 dom
不过是换了另一种方式;react
而言,同样是操作虚拟 dom
,就性能而言, vue
key
ist sehr wichtig. Dies kann die eindeutige Kennung dieses Knotens sein, die dem diff
-Algorithmus mitteilt, dass es sich vor und nach der Änderung um denselben DOM-Knoten handelt.
v-for
Warum gibt es? ein key
, ohne key
kommt es zu einer gewaltsamen Wiederverwendung. Verschieben Sie beispielsweise einfach einen Knoten oder fügen Sie einen Knoten hinzu (ändern Sie DOM). wird nur DOM verschieben und reduzieren.
Nur wenn es sich um denselben virtuellen Knoten handelt, wird ein detaillierter Vergleich durchgeführt. Andernfalls wird der alte gewaltsam gelöscht und der neue eingefügt.
Es werden nur Vergleiche innerhalb derselben Ebene und keine Vergleiche zwischen Ebenen durchgeführt.Altes Vorher und Neues Vorher (zuerst den Anfang vergleichen, dann Knoten einfügen und löschen)
Alt vor und nach dem Neuen (Verglichen mit Kopf und Schwanz, wenn dies geschieht, müssen Knoten verschoben werden, dann wird der Knoten, auf den die neue Front zeigt, nach dem alten verschoben)
--- Wenn Sie es nach Nachfrage klarstellen können Die obigen Fragen Wenn ja, ist es im Grunde O---
angular
-Funktionen bei, wodurch Datenoperationen einfacher werden; react
, Realisierung der Kapselung und Wiederverwendung von html
, beim Erstellen von Einzelseitenanwendungen haben sie einzigartige Vorteile; Trennung von Ansichten, Daten und Strukturen: Vereinfachen Sie Datenänderungen, ohne dass der Logikcode geändert werden muss, und müssen Sie nur Daten bearbeiten, um verwandte Vorgänge abzuschließen. dom
wird nicht mehr verwendet, was die Operation dom
erheblich entlastet Die spezifische Operation ist immer noch dom
ist nur eine andere Möglichkeit; läuft schneller: Im Vergleich zu react
wird auch virtuelles dom
ausgeführt In Bezug auf die Leistung bietet vue
große Vorteile. Der Ausführungsprozess des Routing-Hooks ist: Global Guard, Routing Guard, Component Guard
🎜🎜Complete Navigationsanalyseprozess:🎜🎜🎜 🎜🎜Navigation wird ausgelöst. 🎜🎜🎜🎜Rufen Sie den beforeRouteLeave-Guard in der deaktivierten Komponente auf. 🎜🎜🎜🎜Rufen Sie vor jeder Wache die globale Wache an. 🎜🎜🎜🎜Call beforeRouteUpdate Guard (2.2+) in wiederverwendeten Komponenten. 🎜🎜🎜🎜Vorher anrufenIn der Routing-Konfiguration eingeben. 🎜🎜🎜🎜Asynchrone Routing-Komponenten auflösen. 🎜🎜🎜🎜Call beforeRouteEnter in der aktivierten Komponente. 🎜🎜🎜🎜Rufen Sie den globalen Schutz vor Resolve auf (2.5+). 🎜🎜🎜🎜Navigation bestätigt. 🎜🎜🎜🎜Rufen Sie den globalen AfterEach-Hook auf. 🎜🎜🎜🎜DOM-Update auslösen. 🎜调用 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,使用 vm.$nextTick
是在下次 DOM 更新循环结束之后立即执行延迟回调。在修改数据之后使用,则可以在回调中获取更新后的 DOM。
什么时候被调用?
watch/event
事件回调。无 $el
. render
函数首次被调用vm.$el
替换,并挂载到实例上去之后调用改钩子。每个生命周期内部可以做什么?
ajax放在哪个生命周期?:一般放在 mounted
中,保证逻辑统一性,因为生命周期是同步执行的, ajax
是异步执行的。单数服务端渲染 ssr
同一放在 created
中,因为服务端渲染不支持 mounted
方法。 什么时候使用beforeDestroy?:当前页面使用 $on
,需要解绑事件。清楚定时器。解除事件绑定, scroll mousemove
。
受现代 JavaScript 的限制 ,Vue 无法检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 Vue 将它转换为响应式的。但是 Vue 提供了 Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value)
来实现为对象添加响应式属性,那框架本身是如何实现的呢?
我们查看对应的 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 }
我们阅读以上源码可知,vm.$set 的实现原理是:
Das obige ist der detaillierte Inhalt vonTeilen von hochfrequenten Vue-Interviewfragen im Jahr 2023 (mit Antwortanalyse). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!