The MVVM pre –
mvc mvvm
Both are designed to solve the coupling problem between the Model layer and the View layer.
MVC
The early MVC pattern was mostly applied in the background.
- In the early days, the front end was only responsible for the display of the View, and the Model layer and control layer were in the background.
- When Ajax became popular and there was a real front-end MVC, flexibility became very poor and code readability and maintainability issues
- View changes are notified to the controller to modify the model layer data
The advantages and disadvantages
The hierarchy is clear, but most of the logic is modified through the Control layer, resulting in messy, bloated and difficult to maintain code.
MVVM(Data-driven view)
- At its core is the ViewModel layer, which automatically responds to changes in the Model layer through a data response mechanism. At the same time, an automatic update strategy is implemented to convert data changes into view updates.
- At the same time, the ViewModel listens for changes in the view layer through events to modify the data in the Model
- MVVM keeps the View and Model coupling low, allowing developers to focus on business logic, improving development efficiency and code execution
The advantage is that a lot of code is needed to maintain the mapping between the Model layer and the View layer, such as how the view is updated after data is updated. Improved development efficiency and code readability while maintaining superior performance.
Differences between MVC and MVVM
MVC is just static rendering, updates are dependent on manipulation dom.mvVM with data-driven views,
virtual Dom
For some complex pages, DOM structure is very complex, every time to operate DOM, rendering engine needs to rearrange, redraw and other operations, and these operations in the case of complex pages, is very time-consuming
- The essence of Virtual DOM is to use a native JS object to describe a DOM node, which is a layer of abstraction of the real DOM.
Comparative advantage
- It’s a performance vs. maintainability trade-off. The Virtual DOM has been optimized within the framework to make its performance acceptable no matter how much data is rendered each time, and to make the code easier to maintain.
- Using Virtual DOM as a compatibility layer allows us to connect to non-Web systems and achieve cross-end development. Taro, UniApp, etc., are compiled through the virtual DOM and then through the AST tree to adapt to other different platforms.
- Through Virtual DOM we can render to other platforms, such as SSR, isomorphic rendering and so on.
- Achieve a high degree of abstraction of components
Vue principle
What happened after New Vue
function Vue(options) {
this._init(options);
}
Copy the code
- 1. Initialization, mainly doing a few things: merging configurations, initializing life cycles, initializing event center, initializing render, initializing props, Methods, Data, computed, watcher, etc
initLifecyle: // Initialize attributes like $parent, $children. The root instance has no $parent, and $children starts out as an empty array until its child instance goes into initLifecycle and puts itself into the parent's $children. So $children must be an instance of the component.
initEvents $on,$once,$off,$emit
initRender // Initialize render dependencies such as $createElement
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm) //Initialize state · Initialize props · Initialize Methods · Initialize data · Initialize computed · Initialize watch So you can use values on props in data, and vice versa. initProvide(vm)// resolve provide after data/props
callHook(vm, 'created')
Copy the code
- 2. Start mounting: If the EL attribute is detected. The $mount method is called to hang on the vue instance and render the template into the final DOM. Then call the mountComponent method to start rendering
- 3. Start calling the beforeMount hook function in the mountComponent. Instantiate a rendered Watcher that calls an updateComponent callback. Finally, the DOM is generated by calling the _update method
if (vm.$options.el) {
vm.$mount(vm.$options.el);
}
Copy the code
What is the responsivity principle of VUE
A simplified version
- Vue responsivity principle is mainly implemented by data hijacking combined with the publisher-subscriber pattern
- During vUE initialization, getters and setters are added to props and data via Object.defineProperty. The purpose is to automatically perform some logic when accessing and writing data: Getters do things that depend on collections, setters do things that issue updates, and each property has an instance of a Dep dependent collector.
- When Vue executes a component, it instantiates a rendered Watcher. Before executing, Watcher assigns the Watcher itself to the global variable dep. target, which accesses data on the VM. This triggers the getter for the object, subscribing the current Watcher to the data-dependent collector.
- When a data responsive property is updated, the update is issued in the setter, notifying the Watcher in the dependency set to update().
Completion version
- The core of the vUE responsivity principle is to observe the change of data and inform the corresponding observer to execute his logic when the data changes
- The DEP is a bridge between the data and the observer. During vUE initialization, every attribute on the data and props object becomes responsive, and an instance of the DEP is held internally.
- When we access these properties, deP’s Depend method is triggered to collect dependencies. The collection is the current DEP. target, which is subscribed to as a subscriber for property changes.
- When we modify the property, we call dep.notify() to notify the subscribers to update().
- Computed creates a computed Watcher inside computed. An instance of deP is held, and when we access a property, the EMIT calculation method is called, and the watcher being evaluated is collected as a dependency. When properties in computed change, and internal computations detect that the results returned have changed, notify the subscribers of computed to update the deP as well
- Watch creates a user Watcher to observe data changes. The deP is notified when observed data changes, triggering the user Watcher update method.
- Vue executes the mount method for each component, creating a unique render Watcher that calls updateComponent when notified of the change to update the component
= = = = = = = = = = = = = = =
- Call vm._update(vm._render()) again to update the component’s view
- The Dep class has a static property target, which is globally unique. Only one global Watcher can point to dep.target at any time
updateComponent = () = > {
vm._update(vm._render(), hydrating);
};
new Watcher(
vm,
updateComponent,
noop,
{
before() {
if (vm._isMounted) {
callHook(vm, 'beforeUpdate'); }}},true /* isRenderWatcher */
);
Copy the code
Vue bidirectional binding principle
Vue’s bidirectional binding principle is a combination of V-Model syntax sugar and VUE’s responsive principle to achieve
- In simple terms, two-way data binding means adding addEventListner to a listener that has a V-XXX directive that calls the setter as soon as an event occurs, This calls dep.notify() to notify all dependencies that watcher calls watcher.update() to update
<input v-model="sth" /> // This row is equal to the next row
<input v-bind:value="sth" v-on:input="sth = $event.target.value" />
Copy the code
Why does VUE use asynchronous rendering
Rendering every update has a performance drain if rendered synchronously.
Updates after property changes
- The dep.notify current property notifies all watcher dependencies on it to update().
- Update () will use (queueWatcher) to add the watcher to a queue and then execute the flushSchedulerQueue after nextTick. For batch updates.
// Points to note
-
1. Update components from parent to child; Because the parent component is created before the child, the Watcher should be created after the parent and executed in the same order.
-
2. User custom Watcher takes precedence over rendering Watcher; Because the user custom Watcher is created before rendering the Watcher.
-
3. If a component is destroyed during the parent component’s Watcher execution, its corresponding Watcher execution can be skipped, so the parent component’s Watcher should be executed first.
How does vue render asynchronously, i.e., updated
- Each Watcherd Update () method is called after the update is dispatched in the setter.
- The update method calls the queueWatcher method, which places all watcher instances in a queue
- Then executing those Watcher’s run methods after nextTick will get its current value through this.get(),
- When the this.get() method is evaluated, the updateComponent method is executed to trigger an update to the component:
The specific mechanism for component updates
- 1.Vue will update only the current component that depends on the collection, and will not update the child component recursively
- 2. If there are child components, only functions and listeners declared on the component are updated, but no updates are made internally.
- If the props property is used in the child component, it enters the update process for the child component
- 3. If a child component has a slot in it that uses the parent component’s property, it calls the child’s $forceUpdate() function, so both parent components are re-rendered
if (hasChildren) {
vm.$slots = resolveSlots(renderChildren, parentVnode.context);
vm.$forceUpdate();
}
Copy the code
<component :data=" MSG ">1</component> < Component >2</component> <component>3</component> <ul>Copy the code
$forceUpdate()
Vm. $forceUpdate essentially triggers a re-execution of the rendered Watcher, in the same way that you would change a responsive property to trigger an update. It just calls vm._watcher.update() for you.
Vue compilation process
- 1. Parse the template as an AST
- 2. Optimize the AST
- 3. Turn the AST into a render function, walk through the AST and generate different code according to different conditions.
Talk about your understanding of slots
- Common slot Named slot and unnamed slot
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
</div>
Copy the code
- Scope slots to allow access to child component data
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
Copy the code
Differences between normal slots and scoped slots
- Normal slots generate vNodes during compilation and rendering of the parent component, so the data is scoped to the parent component instance, and the child component gets the rendered VNodes directly when rendering
- ScopedSlots. The parent component does not generate vnodes directly during compilation and rendering. Instead, it keeps a scopedSlots object in the parent vnode’s data, storing slots with different names and their corresponding rendering functions. The render function is executed to generate vNodes only during the compilation and rendering of the subcomponents, and since it is executed in the subcomponent environment, the corresponding data scope is the subcomponent instance.
nextTick (src/core/util/next-tick.js )
-
The order of asynchronous task execution is above the establishment and priority. By default, vUE’s asynchronous queue gives priority to micro Task by taking advantage of its high-priority feature to ensure that all the micro tasks in the queue are executed in a cycle.
-
Test for Promise -> MutationObserver -> setImmediate -> setTimeout and use it as an API to perform asynchronous callback queues
-
The nextTick method then wraps the cb callback in a try-catch and pushes it into the callbacks task queue array in an anonymous function
-
Tasks can also be pushed to the task queue before the asynchronous task queue method executes.
-
When the asynchronous method of the task queue starts the callback execution, the task in the queue is executed.
-
Also in timerFunc execution for the nextTick method, the status of a pending flag bit is checked to ensure that the asynchronous callback method is not executed each time the $nextTick method is called. Instead, after a nextTick asynchronous call is executed, the flag is reset and the task queue is emptied. So new tasks are pushed into the queue.
-
This queue may be a microTask queue or a macroTask queue
const callbacks = []
let pending = false
function flushCallbacks () {
pending = false
const copies = callbacks.slice(0)
/ / to empty
callbacks.length = 0
// Loop the execution queue
for (let i = 0; i < copies.length; i++) {
copies[i]()
}
}
export function nextTick(cb? Function, ctx: Object) {
let _resolve
// The CB callback handles pressing into the Callbacks array uniformly
callbacks.push(() = > {
if(cb) {
try {
cb.call(ctx)
} catch(e) {
handleError(e, ctx, 'nextTick')}}else if (_resolve) {
_resolve(ctx)
}
})
if(! pending) { pending =true;
timerFunc();
}
timerFunc(flushCallbacks)
Copy the code
The disadvantage of Object. DefineProperty
- Unable to detect additions or deletions of object properties
- PS object.defineProperty can listen to the subscript changes of the array. The performance cost is not proportional to the user experience benefit, so we use the method of rewriting the array method to achieve responsive update
/ / segmentfault.com/a/119000001…
Resolves additions or deletions for undetected object attributes
Vue provides a set method internally
- First check whether the array is an array, with the array has been overwritten method to observe
- It then checks if it already exists and returns the value
- Then determine if the response is an object and if the prototype has an __ob__
- If neither calls defineReactive for bidirectional binding,
- Then manually dispatch the update.
For the array can not listen, the array method for interception
- Point the array prototype to the one that changed the array method. (arr__proto__ == arrayMtehods)
- Rewrite all methods that change the array itself, such as ‘push’, ‘pop’, ‘shift’, ‘unshift’, ‘splice’, ‘sort’, ‘reverse’.
- The three methods push, unshift and splice that can increase the length of the array are evaluated to get the inserted value and then turn the newly added value into a responsive object
- And call ob.dep.notify() again to trigger dependency notification manually
export function set(target: Array<any> | Object, key: any, val: any) :any {
// Check whether it is an array and whether the subscript is valid
if (Array.isArray(target) && isValidArrayIndex(key)) {
// Call the splice function to trigger the dispatch of updates
// This function has been overwritten
target.length = Math.max(target.length, key);
target.splice(key, 1, val);
return val;
}
// Check whether the key already exists
if (key intarget && ! (keyin Object.prototype)) {
target[key] = val;
return val;
}
const ob = (target: any).__ob__;
// If the object is not a reactive object, the assignment returns
if(! ob) { target[key] = val;return val;
}
// Perform bidirectional binding
defineReactive(ob.value, key, val);
// Manually send updates
ob.dep.notify();
return val;
}
Copy the code
const arrayProto = Array.prototype;
export const arrayMethods = Object.create(arrayProto);
const methodsToPatch = ['push'.'pop'.'shift'.'unshift'.'splice'.'sort'.'reverse'];
/** * Intercept mutating methods and emit events */
methodsToPatch.forEach(function (method) {
// cache original method
const original = arrayProto[method];
def(arrayMethods, method, function mutator(. args) {
const result = original.apply(this, args);
const ob = this.__ob__;
let inserted;
switch (method) {
case 'push':
case 'unshift':
inserted = args;
break;
case 'splice':
inserted = args.slice(2);
break;
}
if (inserted) ob.observeArray(inserted);
// notify change
ob.dep.notify();
return result;
});
});
Copy the code
Why is data in a component a function
- If you declare the component multiple times in the template, data in the component will refer to the same reference.
- If you modify data in one component, data in other components will be contaminated. This problem can be avoided by using functions that have separate references to data in each component.
Why does VUE use key,vue’s diff procedure
The DIff process of VUE
At the heart of component updates is the process of diff between new and old nodes
1. Different nodes:
If isSameNode is false, destroy the old vNode and render the new vNode. This also explains why diff is synonymous.
2. Same node
- If the vNode is a text node and the new and old text are different, the text content is replaced directly. If they are not text nodes, their children are determined,
If there are new children and no old children,
If children are added, directly addVnodes adds a new child node.If there are old children and no new children
To delete children, remove the old child nodes directly from removeVnodes- If both exist, use Update Dren for comparison.
updateChildren
// Old first node
let oldStartIdx = 0;
// New first node
let newStartIdx = 0;
// Old tail node
let oldEndIdx = oldCh.length - 1;
// New tail node
let newEndIdx = newCh.length - 1;
Copy the code
Loop for contrast, loop for logic
-
oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx
-
1. Compare the old first node with the new first node using sameNode.
-
2. Compare the old tail node with the new tail node using sameNode
-
3. Compare the old first node with the new tail node using sameNode
-
4. Compare the old tail node with the new first node using sameNode
-
A new node needs to be added. If oldStartIdx > oldEndIdx is displayed after the update, it indicates that the old nodes have been patched, but there may be new nodes that have not been processed. It then decides whether to add child nodes.
-
Some old nodes need to be deleted. If the new node is patched first, newStartIdx > newEndIdx will be used to delete the excess old child nodes.
function sameVnode(a, b) {
returna.key === b.key && a.tag === b.tag && a.isComment === b.isComment && isDef(a.data) === isDef(b.data) && sameInputType(a, b); }Copy the code
When does v-for use index as the key and when does it not use index
- It is more efficient to use index as key when V-for performs simple list rendering operations.
When Vue is updating a list of elements rendered using V-for, it defaults to the “update in place” policy. If the order of data items is changed, Vue will not move DOM elements to match the order of data items. Instead, each element will be updated in place. This strategy is efficient, but only for list rendering output that does not depend on child component state or temporary DOM state (such as form input values).
- Index is not recommended for complex operations such as reordering or adding or deleting data from a list
- Random number as the key, the old node will be deleted, the new node will be created.
Transformation of order
- SameNode is used for comparison. This step matches the logic
- Then the patchVnode operation is performed on the first Vnode in the old node and the first vnode in the new node
After deleting data // juejin.cn/post/684490…
The sameNode will only evaluate the key, tag, presence of data (regardless of internal values), annotation node, and same input type to determine whether the node can be reused.
Since index is used, the values of the old nodes can be reused and the extra nodes deleted. The last node is always deleted
What are the advantages of Vue
- Easy to learn, easy to get started and fast development projects
- Mature lightweight framework, a lot of internal optimization, good performance
Vue has some built-in methods
What is the difference between computed and Watch
-
Computed is cacheable. In computed, there is a calculated watcher with a dirty attribute inside that determines whether the computed value needs to be recalculated or reused
-
Watch listens for a property and updates it immediately if it changes
The computed version 2.6
summary
- When a computed property is initialized, the Watcher that calculates the property is instantiated through a loop. When the instance is initialized, only one dependency instance of the DEP is generated, and no dependencies are collected.
- When a page rendering accesses a computed property, it determines whether dirty is true, that is, dirty data. If so, the callback function is called to evaluate; if not, the cached value is returned. Defaults to true and is evaluated. This is the concept of calculating a property cache
- For a computed responsive data update, it adds both the calculated and rendered watcher to its dependency set. When the change starts, the update() calculation of watcher sets dirty to true, whereas rendering Watcher, after re-rendering the page, reads computed dirty, which is true, and evaluates it again.
- Changes in other data do not affect computed values.
- Version 2.5 executes the getter for user computed again every time a computed dependency is updated. It's just too many calculations. - versions prior to 2.5 have a judgment that if conputed returns the same value it will not be re-rendered, it will be recalculated but not re-rendered. -2.6 It will be rerendered whenever the dependencies in computed changeCopy the code
Summary summary 2
Differences between ComputedWatcher and ordinary Watcher: 1. Using lazy as true indicates that it is a calculation Watcher 2. Get and set to calculate Watcher are overridden by the defineComputed() method when initializing (initComputed) 3. Computedwatcher.update () is also called when the attributes it depends on change, but because its lazy attribute is true, it only performs the operation that sets dirty to true. QueueWatcher () or run() 4 is not executed like the other Watcher. ComputedWatcher get is triggered only when it is useful, such as when it is called during view rendering, but since the GET is overwritten during initialization, It evaluates whether dirty is true to evaluate() 5. Hence the lazy nature of the calculation: when the property on which the calculation depends changes, it is not recalculated immediately (just by setting dirty to true), but only when it is read somewhere else (triggering an overridden GET).Copy the code
A detailed description
Initialize the
- Instantiate a watcher instead of evaluating the properties in computed, but instantiate a DEP dependency set.
- When we access a computed property, we determine whether dirty is true and then call watcher.evaluate(), and if it is false we skip returning the value directly, which is the concept of computed property caching
update
-
First, when templates use computed properties, the global DEP. target is the watcher for component rendering.
The dep. target is render watcher and the targetStack is [Render Watcher].
-
This.get() is called to evaluate watcher. Evaluate, which sets the evaluation watcher itself to dep.target and waits for the dependency to be collected.
The dep. target is calculated watcher, and the targetStack is [Render watcher, calculate Watcher].
-
Sum then executes the method passed in, this.count executes its setter to collect the dependency, and count adds the watcher dependency to the calculation.
-
And the dePS for the property that we’re calculating is the DEP for count
-
Then, watcher.depend() is executed, so the count deP stores the rendered watcher in its subs.
Subs: [sum calculated watcher, render watcher]
-
When count is updated, the watcher saved in subs calls their update method in turn
-
Update () on watcher will set dirty to true, update on watcher will re-render the view, and sum will be evaluated when read again
Summary Version 2.6 computes property updates
- 1. Reactive value count updates, with computed Watcher and rendered Watcher updates notified
- 2.computed Watcher update will set dirty to true and wait for the next time it is called
- 3. Figure rendering reads the value of computed, so computed Watcher is re-evaluated because of dirty.
{
computed: {
sum() {
return this.count + 1}}},// After computed is initialized
{
deps: [].dirty: true.getter: ƒ sum (),lazy: true.value: undefined
}
Object.defineProperty(vm, 'sum', {
get() {
// Get computed Watcher from the component instance just described
const watcher = this._computedWatchers && this._computedWatchers[key]
if (watcher) {
// ✨ note! This is only reevaluated if it's dirty
if (watcher.dirty) {
// Get is evaluated here
watcher.evaluate()
}
// ✨ is also a key point
if (Dep.target) {
watcher.depend()
}
// Returns the calculated value
return watcher.value
}
}
})
evaluate () {
this.value = this.get()
this.dirty = false
}
get () {
pushTarget(this)
let value
const vm = this.vm
try {
value = this.getter.call(vm, vm)
} finally {
popTarget()
}
return value
}
Copy the code
watch
It is also time for component initialization, after computed, initWatch. Loop through the watcher and call the createrWatcher method, which creates a user watcher with vm.$watch
Watch will set options.user = true, this.get() will collect the dependencies, and execute the callback function directly if the data changes.
Attributes on _data can be accessed directly from the VM using the proxy method. proxy(vm,`_data`, key)
Copy the code
Sync in watcher
Watcher.update () is triggered, but the watcher is pushed to a queue, and the watcher callback is actually executed after nextTick. Once we set sync, we can execute watcher’s callback function synchronously in the current Tick.
update () {
/* istanbul ignore else */
// computed
if (this.lazy) {
this.dirty = true
} else if (this.sync) {
// watch
this.run()
} else {
/ / other
queueWatcher(this)}}Copy the code
Deep in Watcher
When deep is set, a traverse() method is executed after the get() method is executed, which is essentially a deep recursive traverse of an object, because traversal is a call to a child object that triggers their getter so that dependencies can be collected,
Keep the principle of the alive
<keep-alive>
<component><component />
</keep-alive>
Copy the code
- Keepalive components are not initialized again, which means that the lifecycle function is not reinitialized. Instead, there are two lifecycle hooks: activated and deactivated:
- Include /exclude conditional matching determines the cache
- How it works: Generates a cache key based on the component ID and tag, and looks in the cache object to see if the instance has been cached. If so, fetch the cached value and update the key’s position in this.keys (updating the key’s position is the key to implement the LRU substitution strategy)
LRU cache elimination algorithm
- Push the most recently accessed component to the end of this.keys. This. Keys [0] is the component that has not been accessed for the longest.
The difference between VUE2 and VUE3
The difference is essentially the difference between proxy-based and object.defineProperty,
- Object.defineproperty can only listen for existing values and cannot respond to new attributes. This can only be done by implementing a syntax
- 2.Proxy does not change the key value.
const raw = {};
const data = new Proxy(raw, {
get(target, key) {},
set(target, key, value){}});Copy the code
Vuex
1. Communication mode between components
Father and son components
props/$emit
- Parent and parent and parent and children, access instances of parent and child components
- Provide/inject: In simple terms, the parent component provides variables through provide, and the child component obtains variables through inject.
- The parent component fetches its children through refs
Brother components
- EventBus, also known as the eventBus, can be used in vue as a bridge concept, as all components share the same event center to which they can register to send and receive events, so that components can notify other components
- Vuex state manager
- localStorage / sessionStorage
Across the communication level
-
EventBus; Vuex; Provide/inject, attrs/attrs /attrs /listeners
-
Attrs contains attribute bindings (except class and style) that are not recognized (and retrieved) as prop in the parent scope. When a component does not declare any prop, it contains all parent-scoped bindings (except class and style), And v−bind=”attrs contains attribute bindings (except class and style) that are not recognized (and retrieved) as prop in the parent scope. When a component does not declare any prop, it contains all parent-scoped bindings (except class and style), And v-bind=”attrs contains attribute bindings (except class and style) that are not recognized (and retrieved) as prop in the parent scope. When a component does not declare any prop, all parent-scoped bindings (except class and style) are included, and the internal component can be passed in via v−bind=”attrs”
/ / parent
<child-com1
:name="name"
:age="age"
:gender="gender"
:height="height"
title="Programmer growth is north."
></child-com1>
/ / the child
props: {
name: String // Name is bound as the props property
},
created() {
console.log(this.$attrs); // There is no name, because it is declared in props
/ / {" age ", "18", "gender" : "female" and "height" : "158", "title" : "programmers growth refers to the north"}
}
=
Copy the code
The advantages of vuex
Vuex can make data flow clear, traceable and predictable, and can easily realize advanced functions such as time travel, greatly improving the stability and scalability of projects
Vuex principle
How is vuex accessed from within a component
-
Vuex, like all vue plug-ins, calls the Install method at initialization.
-
Install takes advantage of vue’s mixin mechanism by mixing the beforeCreat hook. Inject store into the vue component instance. This allows all vUE component instances to access store injected into vUE component instances. This allows all vUE component instances to access store injected into vUE component instances. This allows all vUE component instances to access the Store
Vuex implementation logic
-
State: In the store constructor there is a resetStoreVM function, which is called by new Vue
-
Vuex takes advantage of vue’s mixin mechanism by mixing beforeCreate hooks, injecting store into vUE component instances, and registering the vuex Store reference property $store!
-
The state of VUEX is realized by means of vUE’s responsive data.
-
Getters are implemented using vUE’s computed property, computed.
-
The design idea is the same as the VUE central event bus.
// When this method is called, the plugin's install method is called.
Vue.use(Vuex);
Vue.use = function (plugin) {
plugin.install.apply(plugin, args);
};
Vuex install method
Vue.mixin({
beforeCreate() {
if (this.$options && this.$options.store) {
// Find the root component main to hang a $store
this.$store = this.$options.store;
// console.log(this.$store);
} else {
// The non-root component points to its parent's $store
this.$store = this.$parent && this.$parent.$store; }}});// What's in the store class
// Key method, reset VM
resetStoreVM(this, state);
function resetStoreVM(store, state, hot) {
// omit extraneous code
Vue.config.silent = true;
store._vm = new Vue({
data: {
$$state: state
},
computed
});
}
Copy the code
vue-router
What is front-end routing
- Front-end routing is that the front-end monitors the change of route URLS and maps them to different views according to different paths. In essence, it detects URL changes, intercepts URL addresses, and implements UI updates by parsing and matching routing rules.
- Compared with the back-end route, the front-end route performs view switching without completely refreshing the page.
The mechanism of vue Router
-
When Vue writes plug-ins, it usually provides static install methods. When we pass vue.use (plugin), we are executing install methods.
-
The vue-Router install method injects the beforeCreate and DeStoryed hook functions for each component and performs private attribute definitions and route initialization for the beforeCreate.
-
Routing will always maintain the current line, the routing switch when the current line switch to the goal line, switch will perform a series of navigation in the process of guard hook function, can change the url, will also apply colours to a drawing the corresponding component, after the switch to the target line update to replace the current line, it will be used as the basis for the next path switching
model
- Hash pattern
- The history mode
- The ‘abstract’ mode, which does not involve records associated with the browser address, is the same as ‘HashHistory’ in that it emulates the browser history stack with arrays
Hash pattern
Listen for URL changes through the Hashchange event
The history mode
- Background configuration is required to proxy all urls to the current index.html
- With html5’s new features, pushState() and replaceState() can modify the browser history stack. These methods change the PATH portion of the URL without causing a page refresh
- PopState event listener status change
- Popstate events are triggered when urls are changed forward or backward by the browser
- Changing the URL with pushState/replaceState or <\a> tags does not trigger a PopState event. Fortunately, we can intercept calls to pushState/replaceState and click events on <\a> tags to detect URL changes
- Trigger this event by calling the back, go, and forward methods of history with js
window.history.replaceState({ key: _key }, ' ', url);
window.history.back(); / / back
window.history.forward(); / / to go forward
window.history.go(-3); // Back up three pages
/ / the window. The history. PushState, window. History. ReplaceState and window. History. Go
Copy the code
VUE3
The principle of
- Vue3 uses es6 Proxy to listen for changes in objects and arrays
The proxy can only listen on the first layer
- If reflect. get returns an Object value, reactive will act as a Proxy.
Get /set may be triggered multiple times when listening on arrays
- Trigger can only be executed if key is the property of the current proxied object target and the old value is equal to the new value
Performance Optimization 2.0
The code level
- When I loop, key,
- Use v-if or V-show depending on the situation
- Route lazy loading is loaded on demand
webpack
- Echarts, Vuex, VRouter, Vue, Element-UI, packaged into DLLS,