The virtual DOM is a lightweight JavaScript object representation of the real DOM. Vue 3 has undergone a significant refactoring of the virtual DOM to optimize performance and reduce memory usage. Its core is a tree-like structure where each node corresponds to an element or component in the real DOM. The basic VNode contains key properties such as type, attributes, and child nodes. Vue 3 applies special handling to static nodes through hoisting optimizations to avoid repeated creation. Component nodes have unique processing logic, and fragment nodes are supported, allowing multiple root nodes to be returned. The introduction of `patchFlag` marks dynamic content to optimize the diffing process. The slot system has been refactored and represented as special VNode types, with static hoisting and caching to reduce redundant creation. Dynamic child nodes generate a block tree structure to narrow the diffing scope. Built-in components receive special handling, and asynchronous components are supported. The Composition API affects the internal structure, but the VNode representation remains largely unchanged. The compiler generates optimized code, and server-side rendering has dedicated processing. Custom renderers are supported, and the type system is more precise.
Read moreVue 3's reactivity system has undergone significant improvements compared to Vue 2, with its core adopting Proxy to replace Object.defineProperty for data interception. Proxy can detect newly added properties and array changes, returning a new object without modifying the original one. In Vue 2, Vue.set was required to handle new properties, and array methods needed to be rewritten. Vue 3 provides Composition APIs like ref and reactive, supporting more flexible reactive data declaration. Performance-wise, Vue 3 implements lazy reactivity and caching, optimizing dependency tracking by replacing the Dep class with an effect system. It also extends support for collection types like Map and Set, enhances debugging capabilities, and offers better TypeScript integration. Additionally, Vue 3 provides more reactive utility functions such as toRefs and markRaw. Overall, Vue 3's reactivity system delivers substantial enhancements in functionality, performance, and developer experience.
Read moreVue 3's reactivity system, based on Proxy, offers enhanced capabilities compared to Vue 2 but still requires handling special scenarios. Primitive values need to be wrapped with `ref`, and array operations require attention to `length` settings and sparse array property deletion. Behavior differs between plain objects and `Map`/`Set`. `NaN` comparisons are specially handled, while circular references are correctly identified. Modifying non-configurable properties fails silently. Prototype chain properties are non-reactive by default. Asynchronous updates batch changes but can be forced synchronously with `flushSync`. The `__v_skip` marker allows skipping reactivity. Large arrays can be optimized with `readonly`, and custom reactivity logic can be implemented via `customRef`. Developers must pay special attention to these edge cases to ensure the reactivity system functions correctly.
Read moreVue3's reactivity system is based on Proxy to automate dependency tracking and trigger updates, but in certain scenarios, manual control over stopping reactivity is required. The fundamental principle involves clearing dependency relationships. The `stop` method from the returned value of an `effect` can halt side effects. At the component level, the `stop` function can deactivate the entire reactivity. For nested objects, recursive stopping is necessary. Internally, the reactivity system implements stopping operations via the `ReactiveEffect` class. Performance optimization may involve temporarily stopping reactivity in non-visible areas. Refs converted by `toRefs` require individual stopping. Stopped reactive objects can be restored by recreating effects. The source code exposes multiple stopping APIs, and edge cases require attention to repeated stops and memory management. Server-side rendering demands special handling for reactivity deactivation.
Read moreVue 3's reactivity system, based on Proxy implementation, offers significant improvements over Vue 2's Object.defineProperty. The core mechanism establishes dependency tracking and update triggering through the `track` and `trigger` functions. For nested objects, a lazy conversion strategy is adopted, where they are only converted upon access. The handling of primitive values is optimized by wrapping them with `ref`. Dependency collection employs a lazy tracking strategy, where only the actual dependencies used during the first run of an `effect` are collected, and `effectStack` is utilized to avoid duplicate collection. The update mechanism implements batched updates via an asynchronous queue to minimize DOM operations and supports custom schedulers to control update timing. Compile-time optimizations include PatchFlag marking and static hoisting to reduce runtime overhead. APIs like `shallowReactive` and `markRaw` enable fine-grained control. Memory management leverages `WeakMap` to prevent leaks and caches Proxy objects. In development mode, reactivity tracking and performance monitoring are supported for easier debugging and optimization.
Read moreIn Vue 3, both `watch` and `watchEffect` are reactive data monitoring APIs but exhibit significant differences. `watch` requires explicitly specifying the data source and callback function, while `watchEffect` automatically tracks internal reactive dependencies. `watch` completes dependency collection during initialization, whereas `watchEffect` dynamically establishes dependencies during execution. `watch` is lazy by default and triggers only when dependencies change, while `watchEffect` executes immediately once. Both support scheduler control. In the source code, they are implemented via `doWatch` but differ in parameter handling. Both return a stop function. `watchEffect` is more suitable for scenarios requiring automatic cleanup of side effects, while `watch` is ideal for precisely monitoring specific data. `watch` supports deep monitoring, while `watchEffect` automatically performs deep tracking. Both support debugging hooks, though debugging `watchEffect` is more complex. They are linked to the component lifecycle and automatically stop when unmounted. `watch` performs value comparison, while `watchEffect` unconditionally re-executes. `watchEffect` may impact rendering, but this can be controlled via `flush`. In TypeScript, `watch` offers more precise type inference, while `watchEffect` relies on contextual inference.
Read moreVue3's computed is a core part of the reactive system, automatically calculating and caching results based on reactive dependencies. When dependencies change, it recalculates; otherwise, it returns the cached value to improve performance. The implementation revolves around the `ComputedRefImpl` class, which includes a getter function, dependency tracking, and a caching mechanism. It manages dependencies through `trackRefValue` and `triggerRefValue`, using the `_dirty` flag to control caching logic. It also supports setters to enable writable computed properties. Often used alongside `watch`, computed properties differ fundamentally—they are ideal for complex data transformations, filtering, sorting lists, form validation, and state management. Compared to Vue2, Vue3 introduces significant improvements, such as a Proxy-based reactive system and finer-grained dependency tracking. The source code is primarily located in the `reactivity` module. During development, the `onTrack` and `onTrigger` hooks can be used for debugging. Edge cases like circular dependencies and synchronous dependency modifications need handling. Compared to React's `useMemo`, Vue's computed offers automatic dependency tracking, deeper integration with the reactive system, and a more intelligent native caching strategy.
Read moreVue 3's reactivity system significantly improves array handling with Proxy compared to Vue 2. It rewrites seven array mutation methods to optimize performance, ensuring a single update trigger per call. Direct index modifications can trigger reactivity, but excessively long indices require explicit `length` property setting. Changes to `length` trigger dependency cleanup. Multidimensional arrays are recursively converted to maintain reactivity. When using `watch` to observe arrays, note the differences between reference and content changes. Performance-wise, it implements batching, lazy reactivity, and caching strategies. Unlike Vue 2, it no longer requires the `set` method, can detect `length` changes, and handles sparse arrays more reasonably. In templates, `ref` arrays are automatically unwrapped, and the compiler optimizes array operation reactivity. Internally, dependencies are managed via `track` and `trigger`, ensuring proper dependency collection for search-based methods.
Read moreVue3's reactivity system is implemented based on Proxy, which deeply proxies nested objects using a lazy proxy strategy—converting them into reactive objects only upon first property access. The get interceptor recursively handles nested objects, with special optimizations for arrays to ensure element modifications trigger reactivity. It uses WeakMap to cache proxies and avoid duplicate conversions, while providing shallow reactivity and markRaw for performance optimization. Compared to Vue2's recursive conversion, it is more efficient for handling complex nested data structures, automatically manages circular references and Symbol properties, and unwraps Refs automatically when used together. The core logic is implemented in files like reactive.ts and baseHandlers.ts.
Read moreVue 3's reactivity system, based on Proxy, offers significant improvements over Vue 2's Object.defineProperty. The `reactive` function creates a reactive proxy while checking if the object has already been proxied and setting an identifier property. The base handler (`baseHandlers`) includes interceptors like `get` and `set`: `get` handles dependency tracking and recursive proxying, while `set` triggers updates. The `track` function establishes the association between effects and properties, and `trigger` executes related effects. Special handling is required for arrays and primitive values. Performance optimizations include proxy caching and shallow reactivity. Non-proxiable objects and circular references also have corresponding handling mechanisms.
Read more