Vue notes

Stoney_ S 2021-05-03 20:54:04
vue notes


1, What is? MVC MVP MVVM

MVC

  • Model: Representative data model , The main task is to manipulate the data ;
  • View: representative UI View , The main task is to transform the data model into ui The view shows .
  • Controller: controller , The main task is to be responsible for business logic ;

View Send instructions to Controller,Controller After completing the business logic , requirement Model Change state ,Model Send new data to View, Users get feedback ;

MVP

  1. Communication between parts , It's all two-way ;
  2. View And Model No contact , All pass Presenter Pass on ;
  3. view Very thin , Don't deploy any business logic , be called “ Passive view ”(Passive View), That is, there is no initiative , and Presenter Very thick , All the logic is deployed there ;

MVVM

  • Model Representative data model , The main task is to manipulate the data ;
  • View representative UI View , The main task is to transform the data model into UI The view shows ;
  • ViewModel Monitor model data changes and control view behavior , Dealing with user interaction , Simple understanding is a synchronization View and Model The object of , Connect Model and View;

stay mvvm Under the architecture ,View and Model There is no direct connection , But through ViewModel Interact ,Model and ViewModel The interaction is two-way , therefore View The changes in the data will be synchronized to Model in , and Model Changes in the data are also immediately felt View On .ViewModel Through two-way data binding View Layer and the Model The layers are connected , and View and Model The synchronization between the two works completely automatically , So developers only need to focus on business logic , No manual operation is required DOM, There is no need to focus on data state synchronization , Complex data state maintenance completely by MVVM To unify management ;

2, Introduce to you VUE

VUE It's a progressive framework , You can put VUE Use as a third party Library , You can also use vue Building complex single page projects ;

  • characteristic : It's easy to get started , Just learn to html,css,js Can , If it is react You have to learn es6, jsx, Functional programming ;
  • flexible : Can be used as a third party Library , It can also be used to frame projects ;
  • Efficient : fictitious DOM;
  • Easy to use : Instructions , Template , Data bidirectional binding . and react comparison , Data bidirectional binding can be modified automatically ,react It needs to be done manually setState;
  • Component words : and react comparison ,vue Component words are more easily accepted by novices html,css, js, and react It's all through js Realization ;

3, In the component data Why not use objects

When components are reused , All component instances will be shared data, If data If it's the object , It will result in a component modification data in the future , It affects all the other components , So we need to data Change it to a function , Call the function once every time you use it to get a new object ; When we use new Vue() The way when , Whether we will data It's OK to set it as an object or a function , because new Vue() The way to do this is to generate a root component , This component will not be reused , There is no sharing data The situation of the ;

VueComponent.prototype.$options = {
data: {name: 'stoney'}
}
let vc1 = new VueComponent();
vc1.$options.data = 'eric';
let vc2 = new VueComponent();
console.log(vc2.$options.data);
 Copy code 

The same component is reused multiple times , Multiple instances are created , These instances use the same constructor , If data If it's an object , So all components share the same object . In order to ensure the data independence of components, each component must pass through data Function returns a new object as the state of the component ;

principle :core/global-api/extend.js;

 Sub.options = mergeOptions(
Super.options,
extendOptions
)
function mergeOptions() {
function mergeField (key) {
const strat = strats[key] || defaultStrat
options[key] = strat(parent[key], child[key], vm, key)
}
strats.data = function (
parentVal: any,
childVal: any,
vm?: Component
): ?Function {
if (!vm) { // Merging will determine subclasses data It has to be a function
if (childVal && typeof childVal !== 'function') {
process.env.NODE_ENV !== 'production' && warn(
'The "data" option should be a function ' +
'that returns a per-instance value in component ' +
'definitions.',
vm
)
return parentVal
}
return mergeDataOrFn(parentVal, childVal)
}
return mergeDataOrFn(parentVal, childVal, vm)
}
 Copy code 

4,Vue Medium v-if and v-show The difference between

  • v-if If the condition is not true, it will not render the node where the current instruction is located dom Elements
  • v-show Just switch the current dom To show or hide

principle :

v-if The template is compiled as follows :

const VueTemplateCompiler = require('vue-template-compiler')
let r1 = VueTemplateCompiler.compile(`<div v-if="true"><span v-for="i in 3">hello</span></div>`)
console.log(r1)
render:
'with(this){return (true)?_c(\'div\',_l((3),function(i){return _c(\'span\',[_v("hello")])}),0):_e()}',
 Copy code 

v-show The template is compiled as follows :

let r2 = VueTemplateCompiler.compile(`<div v-show="true"></div>`)
console.log(r2)
/**
* with(this){
* return _c(\'div\',
* {directives:[{
* name:"show",
* rawName:"v-show",
* value:(true),
* expression:"true"
* }]
* })
* }
*/
//v-show The operation is pattern , It's defined in platforms/web/runtime/directives/show.js
export default {
bind (el: any, { value }: VNodeDirective, vnode: VNodeWithData) {
vnode = locateNode(vnode)
const transition = vnode.data && vnode.data.transition
const originalDisplay = el.__vOriginalDisplay =
el.style.display === 'none' ? '' : el.style.display
if (value && transition) {
vnode.data.show = true
enter(vnode, () => {
el.style.display = originalDisplay
})
} else {
el.style.display = value ? originalDisplay : 'none'
}
},
 Copy code 

5, Why? v-for and v-if It can't be used together

const r3 = VueTemplateCompiler.compile(`<div v-if="false" v-for="i in 3">hello</div>`)
console.log(r3)
/**
* with(this){
* return _l((3),function(i){
* return (false)?_c(\'div\',[_v("hello")]):_e()
* })
* }
* errors:
[ 'Cannot use v-for on stateful component root element because it renders multiple elements.' ],
*/
 Copy code 

v-for Than v-if Higher priority , If used together ,v-if I'll add a little bit to each element , Will cause performance waste ;

6, ajax In which lifecycle is the request placed

  • stay created When , In the view dom It's not rendered , So if I were to go ahead and do it dom node , Cannot find related element ;
  • stay mounted in , Because of this time dom It's already rendered , So you can do it directly dom node ;

In general, they are put in mounted in , Guarantee the unity of logic , Because the lifecycle is synchronized ,ajax It's asynchronous ; Server side rendering does not support mounted Method , So in the case of server-side rendering, we put it on the server created in ;

7, When to use beforeDestroy

  • The current page uses $on Method , You need to unbind the component before it's destroyed
  • Clear your own timer
  • Unbind the event scroll mousemove...

8, Vue in v-html What problems will lead to

  • May lead to xss attack
  • v-html Will replace the child elements inside the tag

principle

let r4 = VueTemplateCompiler.compile(`<div v-html=" '<span>hrllo</span>' "></div>`)
console.log(r4)
/**
* with(this){return _c(\'div\',{domProps:{"innerHTML":_s( \'<span>hrllo</span>\' )}})}
*/
 Copy code 

9, Vue Parent child component life cycle call order

Load Render Pass

Father beforeCreated -> Father created -> Father beforeMount -> Son beforeCreated -> Son created -> Son beforeMount -> Son mounted -> Father moubted

Subcomponent update process

Father beforeUpdate -> Son beforeUpdate -> Son updated -> Father updated

Parent component update process

Father beforeUpdate -> Father updated

Destruction process

Father beforeDestroy -> Son beforeDestroy -> Son destroyed -> Father destroyed

summary

  • Components are called in the order of pay first and then sub , The order in which rendering is done must be son before father ;
  • The destruction of a component is a parent after a child , The destruction is finished after the father ;

10, Vue Component related

What is componentization , What are the benefits

Any page can be abstracted into a component tree composed of a bunch of components . Up to a page , As small as a button can be a component , A page is composed of many nested components , This is componentization ;

Benefits of componentization

  • Strong reusability
  • Division of labor development
  • The code is easy to manage
  • Low coupling

vue How to create components

Global components

Vue.component( The name of the component '', Object of component details );

Local components

new Vue({
...
components: {
The name of the component : Component details object
}
})
 Copy code 

Single file component

.vue file

<template>
<script>
<style>
 Copy code 

Vue How components communicate

  • Father son communication Father -> Son through props, Son -> Father , o n , on, emit;
  • How to get parent-child component instances , p a r e n t , parent, children;
  • Provide child components in the parent component for consumption Provider, inject;
  • Ref Get the instance's way to call the component's properties or methods ;
  • Event Bus Achieve cross component communication ;
  • slot
  • Vuex State management realizes communication ;
  • attrs: Contains inaction in the parent scope prop Be identified ( And get ) Of attribute binding (class and style With the exception of ), When a component does not declare anything prop when , This will include all bindings for the parent scope (class and style With the exception of ), And through v-bind="$attrs" Incoming internal components - Very useful when creating high-level components ;
  • provider inject; provide and inject Mainly in the development of high-level plug-ins / When using component library , It is not recommended for normal application code ; Pass... In the parent component provider To provide variables , And then in the subcomponent through inject To inject variables . No matter how deep the subcomponents are , Just call inject Method , Then you can inject provider Data in ; Instead of being limited to the prop Property to get data , As long as within the life cycle of the parent component , All subcomponents can call ;
  • v-model: Parent component passed v-model When passed to a subcomponent , Will automatically send a value Of prop Properties of , Pass in subcomponent this.$emit9'input', val) Automatically modify v-model The value of the binding ;

11, Vue How to separate the same logic in

Vue.mixin usage , Give components every lifecycle , Functions are mixed with some common logic ;

12, Please talk about the principle of responsive data

  • emphasis :Object.defineProperty
  • Default Vue Initializing Data time , Will give data Property usage for Object.defineProperty Redefine all properties , When the page gets the corresponding property , Dependency collection will be conducted ( But before the collection of components watcher), If the property changes, the related dependency will be notified to update ;

444.png

Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend() // Collection dependency
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
},
set: function reactiveSetter (newVal) {
const value = getter ? getter.call(obj) : val
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter()
}
// #7981: for accessor properties without setter
if (getter && !setter) return
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
childOb = !shallow && observe(newVal)
dep.notify() // Notify dependent to update
}
})
 Copy code 

13, Vue How to detect array changes in

  • Using function hijacking , Overriding array method
  • Vue take data In the array , The prototype chain is rewritten , It points to the array prototype method defined by itself , So when you call an array api when , Dependency updates can be notified , If the array contains reference types , The reference types in the array are monitored again ;

5555.png

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) { // Rewrite prototype method
// cache original method
const original = arrayProto[method] // Call the original array 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() // When the array method is called , Manually notify view updates
return result
})
})
this.observeArray(value) // Conduct in-depth monitoring
 Copy code 

14, why Vue Asynchronous rendering

vue It's a component level update , If you don't use asynchronous updates , Then each time the data is updated, the current component will be re rendered , For performance ,Vue After this round of data update , To update the view asynchronously ;

666.png

 update () {
/* istanbul ignore else */
if (this.lazy) {
this.dirty = true
} else if (this.sync) {
this.run()
} else {
queueWatcher(this) // When data changes , take watcher Put in a queue for batch update
}
}
export function queueWatcher (watcher: Watcher) {
const id = watcher.id
if (has[id] == null) {
has[id] = true
if (!flushing) {
queue.push(watcher)
} else {
// if already flushing, splice the watcher based on its id
// if already past its id, it will be run next immediately.
let i = queue.length - 1
while (i > index && queue[i].id > watcher.id) {
i--
}
queue.splice(i + 1, 0, watcher)
}
// queue the flush
if (!waiting) {
waiting = true
if (process.env.NODE_ENV !== 'production' && !config.async) {
flushSchedulerQueue()
return
}
nextTick(flushSchedulerQueue) // call nextTick Method , Batch update operation
}
}
}
 Copy code 

15, nextTick Realization principle

nextTick The method mainly uses macro task and micro task to define an asynchronous method , Multiple calls nextTick Method will be queued , Clear the current queue through this asynchronous method , So this nextTick Methods are asynchronous methods ;

export function nextTick (cb?: Function, ctx?: Object) {
let _resolve
callbacks.push(() => {
if (cb) {
try {
cb.call(ctx)
} catch (e) {
handleError(e, ctx, 'nextTick')
}
} else if (_resolve) {
_resolve(ctx)
}
})
if (!pending) {
pending = true
timerFunc()
}
// $flow-disable-line
if (!cb && typeof Promise !== 'undefined') {
return new Promise(resolve => {
_resolve = resolve
})
}
}
let timerFunc
// The nextTick behavior leverages the microtask queue, which can be accessed
// via either native Promise.then or MutationObserver.
// MutationObserver has wider support, however it is seriously bugged in
// UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It
// completely stops working after triggering a few times... so, if native
// Promise is available, we will use it:
/* istanbul ignore next, $flow-disable-line */
if (typeof Promise !== 'undefined' && isNative(Promise)) {
const p = Promise.resolve()
timerFunc = () => {
p.then(flushCallbacks)
// In problematic UIWebViews, Promise.then doesn't completely break, but
// it can get stuck in a weird state where callbacks are pushed into the
// microtask queue but the queue isn't being flushed, until the browser
// needs to do some other work, e.g. handle a timer. Therefore we can
// "force" the microtask queue to be flushed by adding an empty timer.
if (isIOS) setTimeout(noop)
}
isUsingMicroTask = true
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
isNative(MutationObserver) ||
// PhantomJS and iOS 7.x
MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
// Use MutationObserver where native Promise is not available,
// e.g. PhantomJS, iOS7, Android 4.4
// (#6466 MutationObserver is unreliable in IE11)
let counter = 1
const observer = new MutationObserver(flushCallbacks)
const textNode = document.createTextNode(String(counter))
observer.observe(textNode, {
characterData: true
})
timerFunc = () => {
counter = (counter + 1) % 2
textNode.data = String(counter)
}
isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
// Fallback to setImmediate.
// Techinically it leverages the (macro) task queue,
// but it is still a better choice than setTimeout.
timerFunc = () => {
setImmediate(flushCallbacks)
}
} else {
// Fallback to setTimeout.
timerFunc = () => {
setTimeout(flushCallbacks, 0)
}
}
 Copy code 

16, method,computed,watch The difference between

  • method: Every time the page data is re rendered, it is re executed , High performance consumption , Unless you don't want to use it when there's a cache ;
  • computed: Compute properties , Rely on other properties to calculate values , also computed The value of has cache , Only when the calculated value changes will the content be returned ;
  • watch: Listen for changes in values and execute callbacks , There are some logical operations that can be done in the callback .
  • summary : Unless you don't want to cache , I don't know how to use it , Generally speaking, when you need to rely on other attributes to obtain values dynamically, you can use computed, For listening to the change of value, you need to do asynchronous operation or expensive operation watch

17, vue Life cycle related

What is life cycle

vue The life cycle of vue From initialization to destruction ;

What is a hook function

In the course of the life cycle , We have a lot of special periods of time , I hope that in these special periods of time vue Do something , So there's the hook function , Hook function is designed by the author vue When , stay vue The special time period from initialization to destruction gives us some rights to define functions . If you define , Will execute , No definition, no execution ;

vue What are the life cycles

  • beforeCreate Before creation
  • created After creation
  • beforeMount Before mounting
  • mounted After mounting
  • beforeUpdate Before data update
  • updated After data update
  • beforeDestroy Before destruction
  • destroyed After destruction

What's the difference between these

  • beforeCreate Before creation , Just executed new The operation of , Nothing else , That is, after the instance is initialized , The data observed (data observer) Called before ;
  • created After creation , Properties and methods are attached to the instance ; In this step , Instance has completed the following configuration : The data observed (data observer), Operations on properties and methods ,watch/event Event callback , Nothing here $el;
  • beforeMount Before mounting , eureka el perhaps mount Corresponding node range , But the data hasn't been replaced yet ; dependent render The function is called for the first time ;
  • mounted After mounting ,vue All variables in the scope are replaced with data The corresponding data value inside ;
  • beforeUpdate Call before data update , It happens in the virtual DOM Before re rendering and patching ;
  • updated After data update , Virtual due to data changes DOM Re rendering and patching , The hook is called after this .
  • beforeDestroy Call before instance destruction , In this step , Instance is still fully available .
  • destroyed After destruction . After calling ,Vue Everything indicated by the instance is unbound , All event listeners will be removed , All child instances will also be destroyed . This hook is not called during server-side rendering .

When do we use

  • created: The instance has been created , Because it is the earliest trigger reason, some data resource requests can be made .
  • mounted: The instance has been mounted , There can be some DOM operation ;
  • beforeUpdate: Further change the state in this hook , This does not trigger the additional render process .
  • updated: Can be executed depending on DOM The operation of , But in most cases , You should avoid changing state during this period , Because it can lead to infinite loops . This hook is not called during server-side rendering ;
  • destroyed: You can perform some optimizations , Clear timer , Unbind event ;

18, keep-alive Function of components

It is mainly used to save the state of components when switching components , Prevent multiple rendering , It can be used keep-alive Component exposure the components that need to be saved ; about keep-alive In terms of components , He has two unique lifecycle hook functions ,activated and deactived. use keep-alive Package components will not be destroyed when switching , Instead, cache into memory and execute deactived Hook function ;

  • include - String or regular expression . Only components whose names match are cached .
  • exclude - Strings or regular expressions , Any component with a matching name will not be cached .
  • max = Numbers , How many component instances can be cached at most ;

19, Vue loader

If we use scaffolding to develop vue, Or make use of webpack Configuration development vue When the project is , Component development will definitely be removed ; There are three forms of component definition , Global components , Local components , File components ; The so-called file component is .vue Component form of , One file, one component ; But there's a problem .vue Cannot be parsed by browser ;vue loader Is to put .vue The file is parsed into something that the browser can understand html, css, js file . Of course webpack There are many more loader The effect is the same ;

When style The label has scoped Attribute , its css Only the elements in the current component ;

<style>
/* Global style */
</style>
<style scoped>
/* Local style */
</style>
 Copy code 

The two can be mixed , Use scoped after , The style of the parent component does not penetrate into the child component ;

20, Why use asynchronous components

If the component has many functions , The packaged results will be bigger , We can load components asynchronously , Mainly depends on import() This grammar , Can achieve file split load .

components: {
AddCustomerSchedulr: (resolve) => import ("../component/AddCustomerSchedulr")
}
 Copy code 

21, What are scope slots

slot

  • When creating a component virtual node , Will save the virtual node of the son of the component , When initializing a component , Sort your sons through slots {a:[vnode], b[vnode]};
  • When rendering a component, it takes out the corresponding slot Property to replace the node .( The scope of the slot is the parent component )
let ele = VueTemplateCompiler.compile(`
<my-component>
<div slot="header">node</div>
<div>react</div>
<div slot="footer">vue</div>
</my-component>
`)
console.log(ele)
/**
* with(this){
* return _c(\'my-component\',
* [_c(\'div\',{
* attrs:{
* "slot":"header"
* },
* slot:"header"
* },[_v("node")]
* ),_v(" "),_c(\'div\',[_v("react")]),_v(" "),_c(\'div\',{
* attrs:{
* "slot":"footer"
* },
* slot:"footer"
* },[_v("vue")])])
* }
*/
 Copy code 
let ele = VueTemplateCompiler.compile(`
<div>
<slot name="header"></slot>
<slot name="footer"></slot>/slot>
</div>
`)
console.log(ele)
/**
* with(this){return _c(\'div\',[_t("header"),_v(" "),_t("footer"),_v("/slot>\\n ")],2)}
*/
 Copy code 

Scope slot

  • When the scope slot is resolved , Not as a child node of a component , When subcomponents render , This function is called to render ( The scope of a slot is a child component )
let ele = VueTemplateCompiler.compile(`
<app>
<div slot-scope="msg" slot="footer">{{msg.a}}</div>
</app>
`)
console.log(ele)
/**
* with(this){
* return _c(\'app\',{
* scopedSlots:_u([{
* key:"footer",
* fn:function(msg){
* return _c(\'div\',{},[_v(_s(msg.a))])
* }
* }])
})
}
*/
 Copy code 
let ele = VueTemplateCompiler.compile(`
<div>
<slot name="footer" a="1" b="2"></slot>
</div>
`)
console.log(ele)
/**
* with(this){
* return _c(\'div\',[_t("footer",null,{
* "a":"1",
* "b":"2"
* })],2)
* }
*/
 Copy code 

22, diff The time complexity of the algorithm

The two trees are completely diff The algorithm is a time complexity of O(n^3),Vue optimized , take O(n^3) The question of accountability translates into O(n) Complexity issues ( Only compare the same level , Don't think about cross level issues ), In the front end , Rarely move across levels dom Elements , therefore Virtual DOM Only elements at the same level will be compared .

23, sketch vue in diff Principle of algorithm

  1. First compare the same level , Then compare the child nodes
  2. First, judge the situation that one side has a son and the other side has no son
  3. We all have sons
  4. Recursively compare child nodes

24, Vue Common performance optimizations in

1, Coding optimization

  1. Don't put all the data in the database data in ,data The data in will increase getter and setter, Will collect the corresponding watcher;
  2. vue stay v-for When binding an event to each element, you need to use an event proxy ;
  3. spa Page adoption keep-alive Cache components ;
  4. Split components ( Improve reusability , Increase code maintainability , Reduce unnecessary rendering )
  5. v-if: The duty of false when , Internal instructions don't execute , It has blocking function , In many cases v-if Instead of v-show;
  6. key: Guarantee uniqueness ( Default vue Will adopt in place reuse strategy );
  7. object.freeze Freezing data ;
  8. Rational use of route load , Asynchronous component ;
  9. Use as far as possible runtime Runtime version ;
  10. Data persistence issues ( Shake proof , closure )

2,vue Load performance optimization

  • Third party modules are imported on demand (babel-plugin-component);
  • Scroll to the viewable area and load dynamically ;
  • Picture lazy loading ;

3, User experience Optimization

  • app-skeleton Skeleton screen ;
  • app-shell app shell

4,seo Optimize

  • Pre rendering plug-in prerender-spa-plugin
  • Server rendering ssr

5, Package optimization

  • Use cdn To load the third-party module ;
  • Multithreading packaging ;

24, action and mutation difference

  • mutation It's a synchronous update ( Whether the data is updated asynchronously will be detected internally )
  • action Is asynchronous operation , Data can be obtained after calling. mutation Submit final data

25, vue in computed Characteristics

Default computed Also a watcher, But it has caching , The data is updated only when the dependent properties change ;

computed.png

function initComputed (vm: Component, computed: Object) {
// $flow-disable-line
const watchers = vm._computedWatchers = Object.create(null)
// computed properties are just getters during SSR
const isSSR = isServerRendering()
for (const key in computed) {
const userDef = computed[key]
const getter = typeof userDef === 'function' ? userDef : userDef.get
if (process.env.NODE_ENV !== 'production' && getter == null) {
warn(
`Getter is missing for computed property "${key}".`,
vm
)
}
if (!isSSR) {
// create internal watcher for the computed property.
watchers[key] = new Watcher(
vm,
getter || noop,
noop,
computedWatcherOptions
)
}
// component-defined computed properties are already defined on the
// component prototype. We only need to define computed properties defined
// at instantiation here.
if (!(key in vm)) {
defineComputed(vm, key, userDef)
} else if (process.env.NODE_ENV !== 'production') {
if (key in vm.$data) {
warn(`The computed property "${key}" is already defined in data.`, vm)
} else if (vm.$options.props && key in vm.$options.props) {
warn(`The computed property "${key}" is already defined as a prop.`, vm)
}
}
}
}
function createComputedGetter (key) {
return function computedGetter () { // This method is called when the value is taken
const watcher = this._computedWatchers && this._computedWatchers[key]
if (watcher) {
if (watcher.dirty) { // Made a dirty The cache mechanism is implemented
watcher.evaluate()
}
if (Dep.target) {
watcher.depend()
}
return watcher.value
}
}
}
/**
* Subscriber interface.
* Will be called when a dependency changes.
*/
update () {
/* istanbul ignore else */
if (this.lazy) { // Compute properties , Dependent data changes
this.dirty = true
} else if (this.sync) { // Sync watcher
this.run()
} else {
queueWatcher(this) // take watcher Put in queue
}
}
 Copy code 

26, Watche Medium deep: true How is it realized

When the user specifies watch Medium deep The attribute is true when , If the current monitored value is an array type , I'm going to apply for every one of them , The current watcher Save to the corresponding attribute dependency , When the objects in the array change , Data updates will also be notified ;

 /**
* Evaluate the getter, and re-collect dependencies.
*/
get () {
pushTarget(this) // Put the current dependency on Dep.target On
let value
const vm = this.vm
try {
value = this.getter.call(vm, vm)
} catch (e) {
if (this.user) {
handleError(e, vm, `getter for watcher "${this.expression}"`)
} else {
throw e
}
} finally {
// "touch" every property so they are all tracked as
// dependencies for deep watching
if (this.deep) { // If deep monitoring is needed
traverse(value) // It takes values for each item in the object , The corresponding get Method
}
popTarget()
this.cleanupDeps()
}
return value
}
 Copy code 

27, use vnode To describe a DOM structure

A virtual node is an object that describes the real dom Elements

function _c(tag, data, ...children) {
let key = data.key
delete data.key
children = children.map(child => {
if (typeof child === 'object') {
return child
} else {
return vnode(undefined, undefined, undefined, undefined, child)
}
})
return vnode(tag, data, key, children)
}
function vnode(tag, data, key, children, text) {
return {
tag, // Represents the current tag name
data, // Represents the properties on the current tag
key, // Unique means that the user may pass
children,
text
}
}
let r = _c('div', { id: 'container' }, _c('p', {}, 'hello'), 'zf')
console.log(r)
/**
* { tag: 'div',
data: { id: 'container' },
key: undefined,
children:
[ { tag: 'p',
data: {},
key: undefined,
children: [Array],
text: undefined },
{ tag: undefined,
data: undefined,
key: undefined,
children: undefined,
text: 'zf' } ],
text: undefined }
*/
 Copy code 

28, vue3.0 What are the improvements

  • Adopted TS To write the
  • Support composition API
  • The principle of responsive data is changed to proxy
  • vdom Comparison algorithm update , Update only vdom The part that binds dynamic data

29, vue The principle of template rendering

<span>{{msg}}</span> => <span> Hello </span> Regular expressions , Match to {{xxx}} Format , Read xxx Data replacement ; data: { msg: ' Hello ' } take template Turn it into render function

export const createCompiler = createCompilerCreator(function baseCompile (
template: string,
options: CompilerOptions
): CompiledResult {
const ast = parse(template.trim(), options) //1, Convert the template into est Trees
if (options.optimize !== false) {
optimize(ast, options) // 2, Optimization tree
}
const code = generate(ast, options) // Make trees
return {
ast,
render: code.render,
staticRenderFns: code.staticRenderFns
}
})
 Copy code 

30, vue-router The ginseng

The simplest is url Pass value ,URL There are two kinds of value transmission ,params and query Parameter values ,

  • params Value passing refers to dynamic routing ;
{path: '/user/:id'} // Define a routing parameter
<router-link to="/user/123"></router-link> // Pass value
this.$route.params.id // Value
 Copy code 
  • query Pass value , Finger pass ? The later splicing parameters pass values
<router-link to="/user?id=123"></router-link> // Pass value
this.$route.query.id // Value
 Copy code 

31, The principle of routing , How to achieve

  • Route definition : Display the functions of different pages or components by clicking different buttons ;
  • principle : According to different path addresses , Show different pages , Components ;
  • Realization :
  1. hash #a #b
  2. history /c /d
  • How to monitor these two changes
  1. hash: hashchange
  2. history: popstate

32, vue The principle of event binding in

vue There are two types of event binding for , One is native event binding , Another is the event binding of components ;

  1. Native dom Event binding uses addEventListener Realization ;
  2. Component binding uses $on Method

principle : Compilation of events

let r1 = VueTemplateCompiler.compile('<div @click="fn()"></div>')
let r2 = VueTemplateCompiler.compile('<my-component @click.native="fn" @click="fn1"></my-component>')
console.log(r1.render)
console.log(r2.render)
with(this){return _c('div',{on:{"click":function($event){return fn()}}})}
with(this){return _c('my-component',{on:{"click":fn1},nativeOn:{"click":function($event){return fn($event)}}})}
 Copy code 

1, Native dom The binding of

  • vue Creating reality dom Called when createElm, The default is to call invokeCreateHooks;
  • Will traverse the current platform relative property processing code , Among them updateDOMListeners Method , It's coming in from the inside add Method ;
function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
if (isUndef(oldVnode.data.on) && isUndef(vnode.data.on)) {
return
}
const on = vnode.data.on || {}
const oldOn = oldVnode.data.on || {}
target = vnode.elm
normalizeEvents(on)
updateListeners(on, oldOn, add, remove, createOnceHandler, vnode.context)
target = undefined
}
function add (
name: string,
handler: Function,
capture: boolean,
passive: boolean
) {
// async edge case #6566: inner click event triggers patch, event handler
// attached to outer element during patch, and triggered again. This
// happens because browsers fire microtask ticks between event propagation.
// the solution is simple: we save the timestamp when a handler is attached,
// and the handler would only fire if the event passed to it was fired
// AFTER it was attached.
if (useMicrotaskFix) {
const attachedTimestamp = currentFlushTimestamp
const original = handler
handler = original._wrapper = function (e) {
if (
// no bubbling, should always fire.
// this is just a safety net in case event.timeStamp is unreliable in
// certain weird environments...
e.target === e.currentTarget ||
// event is fired after handler attachment
e.timeStamp >= attachedTimestamp ||
// #9462 bail for iOS 9 bug: event.timeStamp is 0 after history.pushState
e.timeStamp === 0 ||
// #9448 bail if event is fired in another document in a multi-page
// electron/nw.js app, since event.timeStamp will be using a different
// starting reference
e.target.ownerDocument !== document
) {
return original.apply(this, arguments)
}
}
}
target.addEventListener( // To the present dom Add event
name,
handler,
supportsPassive
? { capture, passive }
: capture
)
}
 Copy code 

vue The binding event in is directly bound to the real dom Elemental

2, Binding events in components

export function updateComponentListeners (
vm: Component,
listeners: Object,
oldListeners: ?Object
) {
target = vm
updateListeners(listeners, oldListeners || {}, add, remove, createOnceHandler, vm)
target = undefined
}
function add (event, fn) {
target.$on(event, fn)
}
 Copy code 

Component binding events are generated through vue Self defined $on= Method to achieve

版权声明
本文为[Stoney_ S]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/05/20210503204934017f.html

  1. Analysis of MVC
  2. [middle stage] please stay and join me in the backstage
  3. Understanding front end garbage collection
  4. [continuous update] front end special style implementation
  5. Flutter product analysis and package reduction scheme
  6. XPath positioning
  7. 前端开发css中的flex布局的使用
  8. The use of flex layout in front end development CSS
  9. JQuery核心函数和静态方法
  10. JQuery core functions and static methods
  11. Node family - understanding of blocking and non blocking
  12. 热点微前端Microfrontend的讨论:谷歌AdWords是真实的微前端
  13. Vue source code analysis (2) initproxy initialization proxy
  14. What's TM called react diff
  15. Summary of common front end data structure
  16. Useeffect in hooks
  17. [encapsulation 02 design pattern] Command pattern, share meta pattern, combination pattern, proxy pattern, strategy pattern
  18. Front end notes: virtual Dom and diff of vue2. X
  19. The best code scanning plug-in of flutter
  20. The simplest plug-in for rights management of flutter
  21. 21. Object oriented foundation "problems and solutions of object traversal"
  22. Discussion on hot micro front end: Google AdWords is a real micro front end
  23. Usecallback and usememo for real performance optimization
  24. 【前端圭臬】十一:从规范看 JavaScript 执行上下文(下)
  25. [front end standard] 11: Javascript execution context from the perspective of specification (2)
  26. Hexagonal六角形架构ReactJS的实现方式 - Janos Pasztor
  27. Transaction of spring's reactive / imperative relational database
  28. The implementation of hexagonal hexagonal reactjs Janos pasztor
  29. HTTP状态码:402 Payment Required需要付款 - mozilla
  30. HTTP status code: 402 payment required - Mozilla
  31. Factory mode, constructor mode and prototype mode
  32. Build the scaffold of react project from scratch (Series 1: encapsulating a request method with cache function based on Axios)
  33. Cocos Quick Start Guide
  34. Comparison of three default configurations of webpack5 modes
  35. A case study of the combination of flutter WebView and Vue
  36. CSS: BFC and IFC
  37. A common error report and solution in Vue combat
  38. JS: this point
  39. JS: prototype chain
  40. JavaScript series -- promise, generator, async and await
  41. JS: event flow
  42. Front end performance optimization: rearrangement and redrawing
  43. JS - deep and shallow copy
  44. JavaScript异步编程3——Promise的链式使用
  45. JavaScript asynchronous programming 3 -- chain use of promise
  46. Vue.js组件的使用
  47. The use of vue.js component
  48. How to judge whether a linked list has links
  49. Element UI custom theme configuration
  50. Text image parallax effect HTML + CSS + JS
  51. Spring的nohttp宣言:消灭http://
  52. Vue3 intermediate guide - composition API
  53. Analysis of URL
  54. These 10 widgets that every developer must know
  55. Spring's nohttp Manifesto: eliminate http://
  56. Learn more about JS prototypes
  57. Refer to await to JS to write an await error handling
  58. A short article will directly let you understand what the event loop mechanism is
  59. Vue3 uses mitt for component communication
  60. Characteristics and thinking of ES6 symbol