current position:Home>Chapter 7 'vue3 runtimecore' - high level API`
Chapter 7 'vue3 runtimecore' - high level API`
2022-01-27 04:15:28 【Jian Darui】
Chapter 7 Vue3 RunTimeCore
—— Higher order API
This article , From h
Function introduced , Gradually understand h
、createVNode
、 cloneVNode
、 mergeProps
、isVNode
Equal higher order API Usage and principle of .
Rendering function h()
stay Vue2
in , There's a big picture API:render
function .Vue
The internal returns a to this function h
function , Used to create Vnode
Description object of .
This time, , stay Vue3
in . take h
Functions are independent , As a separate API
, Its function remains the same : Used to create a description of the rendered node Vnode
Describe objects .
Three parameters are acceptable : type
、props
、children
.
-
type
Used to representVnode
Node type , It can beHTML
Tag name 、 Components 、 Asynchronous components or functional components . Use returnnull
Functions that render a comment , This parameter must be passed . -
props
It's an object , With theattribute
、prop
Corresponding to events . Optional . -
children
Is a child nodeVNode
, Useh()
Generate , Or use a string to get the “ TextVNode
”, Or objects with slots . Optional .
At the beginning of learning Vue
When , I always don't understand render
Function h
How to use . If you have been through HTML
Template syntax to build page structure , It might be right h
Functions are not particularly familiar , Now we can learn together .
When we create a component , It's usually passed HTML
Template to describe UI
part , such as :
-
Use HTML
label :
<template>
<input
type="radio"
:id="branch"
:value="branch"
name="branch"
v-model="currentBranch">
<label :for="branch">{{ branch }}</label>
</template>
-
Use custom component labels :
<template>
<tree-item class="item" :model="treeData" @chang="changeHandler"></tree-item>
</template>
In fact, these can be passed JS
Abstract into three parts , And describe... With objects :
-
Used to represent the template label type type
-
To the template attribute
、prop
And events -
Label the child nodes of the package children
And the child nodes can also be abstracted into the same structure .

and h
Function does just one thing . Pass it on to him type
、props
、children
. It returns the corresponding Vnode
Describe objects .
「 Can you directly create a Vnode
Describe objects 」
Certainly. , But if it involves Vnode
The description of all their own words , A little too tired , And it's easy to make mistakes .
Let's take a look first Vue
Internally defined Vnode
Object contains properties :
-
__v_isVNode: *true*
, Internal attributes , The attribute is expressed asVnode
-
__v_skip: true
, Internal attributes , Indicates skipping the responsive conversion ,reactive
This attribute will be used for judgment during conversion -
isCompatRoot?: *true*
, Used to judge whether compatibility processing has been done -
type: VNodeTypes
, Type of virtual node -
props: (VNodeProps & ExtraProps) | *null*
, Virtual nodeprops
-
key: *string* | *number* | *null*
, Virtual phasekey
, Can be used fordiff
-
ref: VNodeNormalizedRef | *null*
, Reference to virtual phase -
scopeId: *string* | *null*
, Is limited toSFC
( Single file component ), Set upcurrentRenderingInstance
When the current instance is rendered , Phase I setup -
slotScopeIds: *string*[] | *null*
, Single file components only , Related to the slot of single file component -
children: VNodeNormalizedChildren
, Child node -
component: ComponentInternalInstance | null
, Component instance -
dirs: DirectiveBinding[] | null
, At presentVnode
Bound instructions -
transition: TransitionHooks<HostElement> | null
,TransitionHooks
-
DOM
Related properties-
el: HostNode | *null*
, Host stage -
anchor: HostNode | *null* // fragment anchor
-
target: HostElement | *null*
,teleport target
The target of transmission -
targetAnchor: HostNode | *null* // teleport target anchor
-
staticCount: *number*
, Number of static nodes included
-
-
suspense
Hang related properties-
suspense: SuspenseBoundary | *null*
-
ssContent: VNode | *null*
-
ssFallback: VNode | *null*
-
-
optimization only
Properties for optimization-
shapeFlag: *number*
-
patchFlag: *number*
-
dynamicProps: *string*[] | *null*
-
dynamicChildren: VNode[] | *null*
-
-
The properties of the root node -
appContext: AppContext | *null*
, Instance context
-
You can see in the Vue
Inside , For one Vnode
There are about twenty attributes that describe an object , Some attributes must also be standardized .
Vue
In order to reduce a certain burden , But not too closed , The rendering is created h
. When users need it , adopt h
Function to create the corresponding Vnode
that will do .
This gives some high-level players a free play space .
「 Then why use h
Function? ?」
In fact, the official documents have given a very appropriate and simple example , Portal : Rendering function
Through official examples , You can know .
javascript
Compared to template syntax , There's a higher degree of freedom . When using templates is too cumbersome , Like multiple if/else, You can use the rendering function h
.
How to use
v-if
<span v-if="user">
{{user.name}}
</span>
<p v-else>Plase login.</p>
send h
The function is expressed as follows :
render() {
return this.user ? h('span', null, user.name) : h('p', 'Plase login.')
}
You can know from the above code :
-
You can replace... With a ternary operator v-if/v-else
Instructions -
Or by if/else
Instead ofv-if/v-else
Instructions
v-show
<div v-show="isActive">Content</div>
send h
The function is expressed as follows :
render() {
return h("div", {
"directives": [{
name: "show",
value: isActive
}],
}, "Content");
}
v-for
<ul>
<li v-for="item in items">{{ item.name }}</li>
</ul>
send h
The function is expressed as follows :
render() {
return h('ul', this.items.map((item) => {
return h('li', item.name)
}))
}
-
Can pass map Function instead of v-for Instructions -
adopt map Back to Vnode, Each is a different object
v-on
<button @click="onClick">Button</button>
send h
The function is expressed as follows :
render() {
return h('button', {
onClick: onClick
})
}
about input The label can go through
-
onBlur
Listening for out of focus events -
onFocus
Listen for Focus Events -
onInput
Listen for input events -
onClick
Monitor click events -
onKeypress
Listening to keyboard events
v-model
stay Vue
in , We can go through v-bind
Transfer value from up to down .
It can also be done through v-model
Transfer value from up to down .
When using v-model
when , Its essence is v-bind
And v-on
The grammar sugar of ;
stay h Function , How to say v-model
? Let's look at the code :
props: ['modelValue'],
emits: ['update:modelValue'],
render() {
return h(Component, {
modelValue: this.modelValue,
'onUpdate:modelValue': value => this.$emit('update:modelValue', value)
})
}
The above code is an official example . This means :
-
But use v-model
bindingvalue
when . Must be given to sub componentsprops
Binding one invalue
, And a function to listen for updates , Instead ofv-bind
Andv-on
.
attrs
In English props
And attrs
All represent the meaning of attributes , But in Vue
These two attributes have different meanings :
-
props
Represents the attribute of the element object -
attrs
Represents the attribute of the element tag
For example, when we call h Function creation Vnode
when , The second parameter passed , Namely Vnode
Object properties .
And when we need to set the element label attrs
What should I do when I'm in a hurry ?
<input type="button" disabled="true"/>
send h
The function is expressed as follows :
render() {
return h(input, {
"attrs": {
type: button,
disabled: true
}
})
}
Therefore, in h
You can see in the function props
contain attrs
.
v-slot
stay Vue
in slot
Provides content distribution capabilities for templates .
When use , Just use slot
The tag can be occupied .
Let's see how to use h Function to create a slot .
<div><slot></slot></div>
send h
The function is expressed as follows :
「 Normal slot 」
Can pass this.$slots
Access the contents of the static slot , Each slot is one VNode Array :
render() {
return h('div', {}, this.$slots.default())
}
「 Scope slot :」
<!-- Define slot components child-->
<div><slot :text="message"></slot></div>
<!-- Use components child-->
<div><child v-slot:default="slotProps">{{ slotProps.text }}</child></div>
render() {
return h('div', {}, this.$slots.default({
text: this.message
}))
}
-
Can pass this.$slot
Access the contents of the static slot -
If you need to pass the status , You can give this.$slots.default()
Function passes an object parameter
「 Custom components 」
<div><child v-slot:default="slotProps"><span>{{ slotProps.text }}</span></child></div>
const { h, resolveComponent } = Vue
render() {
return h('div', [
h(
resolveComponent('child'),
{},
// take `slots` With { name: props => VNode | Array<VNode> } Passed to child objects in the form of .
{
default: (props) => Vue.h('span', props.text)
}
)
])
}
resolveComponent API
Returns the child
Component's Vnode
.
Dynamic components
<component :is="name"></component>
send h
The function is expressed as follows :
const { h, resolveDynamicComponent } = Vue
render() {
const Component = resolveDynamicComponent(this.name)
return h(Component)
}
When using dynamic components , have access to resolveDynamicComponent
Instead of is
attribute,resolveDynamicComponent
Support passing a component name 、 One HTML Element name or a component option object .
Can give is Pass anything to resolveDynamicComponent
What to pass on .
Built in components
stay Vue
in , KeepAlive
, Teleport
, Transition
, TransitionGroup
Etc. is called Vue
Built in components , The difference between built-in components and user-defined components is , Built in components are not registered locally or globally , So I can't get through resolveComponent
Go visit them . In the use of h
Function time , You need to be confident :
const { h, KeepAlive, Teleport, Transition, TransitionGroup } = Vue
// ...
render () {
return h(Transition, { mode: 'out-in' }, /* ... */)
}
ref
<someComponent ref="someComponent"></someComponent>
send h
The function is expressed as follows :
render() {
return h(someComponent, {"ref": "someComponent"}))
}
Custom instruction
have access to withDirectives
Apply custom directives to VNode
:
const { h, resolveDirective, withDirectives } = Vue
// <div v-pin:top.animate="200"></div>
render () {
const pin = resolveDirective('pin')
return withDirectives(h('div'), [
[pin, 200, 'top', { animate: true }]
])
}
resolveDirective API
Is the same function used to resolve the instruction name inside the template . Only if you have not directly accessed the definition object of the instruction , That's what we need to do .
Later, we'll talk about withDirectives API
Analyze .
**
resolveComponent API
AndresolveDirective API
The principle is the same . When we create a component , Configure this componentcompontes
attribute 、directives
attribute . These properties will eventually be bound to the instance ,resolve
Components / Instruction process , By accessing the current instancecompontes/directives
The process of attributes .
Rendering function h()
Source code analysis
*This part may be boring , Mainly analysis
*h
How functions are createdVnode
, What will be done during the creation process .
Vnode
It's an ordinary of a virtual node JS
object ,Vue
According to the object information , Render the corresponding node .
Vnode
type
You can give h
Function transitive Vnode
Node type :
-
string
-
VNode
-
Component
-
Text
-
Static
-
Comment
-
Fragment
-
TeleportImpl
-
SuspenseImpl
Look directly at the source code :
function h(type, propsOrChildren, children) {
// Judge whether there are child nodes according to the parameter length
const l = arguments.length
if (l === 2) {
// Pass two parameters
if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
// propsOrChildren Is an object and not an array
if (isVNode(propsOrChildren)) {
//props yes Vnode type , be propsOrChildren Is a child node
return createVNode(type, null, [propsOrChildren])
}
// props Does not contain child nodes
return createVNode(type, propsOrChildren)
} else {
// Omit props
return createVNode(type, null, propsOrChildren)
}
} else {
// When it exists 2 When a parameter has been added
// Put the child nodes into children Array
if (l > 3) {
children = Array.prototype.slice.call(arguments, 2)
} else if (l === 3 && isVNode(children)) {
children = [children]
}
return createVNode(type, propsOrChildren, children)
}
}
Through the above code , Rendering function h
It's just createVnode
Grammatical sugar of function .
Rendering h()
The main responsibility of function is to judge the length and type of parameters , To call createVnode
Function creation Vnode
.
Look at the below createVnode
function .
createVNode
createVnode
Function in Vue
Source code runtime-core
in vnode.ts
Folder .
createVNode
In fact, it's called _createVNode
.
*There is no need to pay attention to
*vnodeArgsTransformer
.
export const createVNode = (__DEV__ ? createVNodeWithArgsTransform : _createVNode)
const createVNodeWithArgsTransform = (...args) => {
return _createVNode(
...(vnodeArgsTransformer
? vnodeArgsTransformer(args, currentRenderingInstance)
: args)
)
}
_createVNode
-
First, check the type , If not as expected , stay dev
The environment will warn ,prod
The environment will be used as the annotation node type . -
In judging whether it is already Vnode
, If yes, clone the node directly , And sort out their own points . -
If it's a class component , Will get __vccOpts
-
do Vue2 Asynchronous or functional component compatibility -
If props
There is , Would be rightprops
Judge , And regulate what we pass to the nodeclass
、style
, Willclass
Process as string , takestyle
Processing as an object -
establish Vnode
-
Standardize and sort out sub nodes -
If you need to do compatibility processing during construction , Then do Vue2
Compatible processing of , Finally, return to the virtual node
function _createVNode(
type,
props,
children,
patchFlag,
dynamicProps,
isBlockNode = false
){
if (!type || type === NULL_DYNAMIC_COMPONENT) {
if (__DEV__ && !type) {
warn(`Invalid vnode type when creating vnode: ${type}.`)
}
type = Comment
}
// If type yes Vnode type , Then clone this type of node , Standardize and sort out sub nodes , Returns the cloned node
if (isVNode(type)) {
const cloned = cloneVNode(type, props, true /* mergeRef: true */)
if (children) {
normalizeChildren(cloned, children)
}
return cloned
}
// If the class component type
if (isClassComponent(type)) {
type = type.__vccOpts
}
// compatible Vue2 To deal with
if (__COMPAT__) {
type = convertLegacyComponent(type, currentRenderingInstance)
}
// if Block mainly deals with class & style attribute
if (props) {
// for reactive or proxy objects, we need to clone it to enable mutation.
// If props It's a reactive object , Need to pass through Object.assign Copy
if (isProxy(props) || InternalObjectKey in props) {
props = extend({}, props)
}
let { class: klass, style } = props
if (klass && !isString(klass)) {
// class It's not a string , It needs to be a string
props.class = normalizeClass(klass)
}
if (isObject(style)) {
// reactive state objects need to be cloned since they are likely to be
// mutated
if (isProxy(style) && !isArray(style)) {
style = extend({}, style)
}
props.style = normalizeStyle(style)
}
}
// take vnode The type information is changed to bitmap
const shapeFlag = isString(type)
? ShapeFlags.ELEMENT
: __FEATURE_SUSPENSE__ && isSuspense(type)
? ShapeFlags.SUSPENSE
: isTeleport(type)
? ShapeFlags.TELEPORT
: isObject(type)
? ShapeFlags.STATEFUL_COMPONENT
: isFunction(type)
? ShapeFlags.FUNCTIONAL_COMPONENT
: 0
if (__DEV__ && shapeFlag & ShapeFlags.STATEFUL_COMPONENT && isProxy(type)) {
// Omit ...
)
}
// establish VNode Description object of
const vnode: VNode = {
__v_isVNode: true, // identification The object is a virtual node
__v_skip: true, // identification This object skips proxy
type, // type
props,
key: props && normalizeKey(props), // carding props
ref: props && normalizeRef(props),// carding ref
scopeId: currentScopeId,
slotScopeIds: null,
children: null,
component: null,
suspense: null,
ssContent: null,
ssFallback: null,
dirs: null,
transition: null,
el: null,
anchor: null,
target: null,
targetAnchor: null,
staticCount: 0,
shapeFlag,
patchFlag,
dynamicProps,
dynamicChildren: null, // Dynamic child nodes
appContext: null // Instance context
}
// validate key
if (__DEV__ && vnode.key !== vnode.key) {
warn(`VNode created with invalid key (NaN). VNode type:`, vnode.type)
}
// Canonical child nodes
normalizeChildren(vnode, children)
// If the time is suspense Type virtual DOM, standard suspense Child node
if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
;(type).normalize(vnode)
}
// I don't care about
if (
isBlockTreeEnabled > 0 &&
!isBlockNode &&
currentBlock &&
(patchFlag > 0 || shapeFlag & ShapeFlags.COMPONENT) &&
patchFlag !== PatchFlags.HYDRATE_EVENTS
) {
currentBlock.push(vnode)
}
// Compatible processing
if (__COMPAT__) {
convertLegacyVModelProps(vnode)
convertLegacyRefInFor(vnode)
defineLegacyVNodeProperties(vnode)
}
// Return to the virtual node
return vnode
}
You can see from the above code that ,_createVNode
The main responsibilities of the function :
-
Carding specification props
Mediumclass
、style
、child
-
establish Vnode
Description object of , And back to -
Yes Vue2
Do compatible processing
**
Object.assign
AndProxy
:https://stackoverflow.com/questions/43185453/object-assign-and-proxies
In the above code , If type
yes Vnode
type , Would call cloneVNode
Create a cloned node , Let's take a look cloneVNode
function .
cloneVNode
In fact, we can think about it first , Clone a Vnode
, In fact, it can be simplified to clone a tree tree
, Is a recursive cloning process .
export function cloneVNode(
vnode,
extraProps,
mergeRef = false
){
// This is intentionally NOT using spread or extend to avoid the runtime
// key enumeration cost.
const { props, ref, patchFlag, children } = vnode
// Merge props
const mergedProps = extraProps ? mergeProps(props || {}, extraProps) : props
// establish Vnode Clone objects
const cloned = {
__v_isVNode: true,
__v_skip: true,
type: vnode.type,
props: mergedProps,
key: mergedProps && normalizeKey(mergedProps),
ref:
extraProps && extraProps.ref
mergeRef && ref
? isArray(ref)
? ref.concat(normalizeRef(extraProps)!)
: [ref, normalizeRef(extraProps)!]
: normalizeRef(extraProps)
: ref,
scopeId: vnode.scopeId,
slotScopeIds: vnode.slotScopeIds,
children:
__DEV__ && patchFlag === PatchFlags.HOISTED && isArray(children)
? children.map(deepCloneVNode) // Deep clone the child nodes
: children,
target: vnode.target,
targetAnchor: vnode.targetAnchor,
staticCount: vnode.staticCount,
shapeFlag: vnode.shapeFlag,
patchFlag:
extraProps && vnode.type !== Fragment
? patchFlag === -1 // hoisted node
? PatchFlags.FULL_PROPS
: patchFlag | PatchFlags.FULL_PROPS
: patchFlag,
dynamicProps: vnode.dynamicProps,
dynamicChildren: vnode.dynamicChildren,
appContext: vnode.appContext,
dirs: vnode.dirs,
transition: vnode.transition,
component: vnode.component,
suspense: vnode.suspense,
ssContent: vnode.ssContent && cloneVNode(vnode.ssContent),
ssFallback: vnode.ssFallback && cloneVNode(vnode.ssFallback),
el: vnode.el,
anchor: vnode.anchor
}
// Compatible processing
if (__COMPAT__) {
defineLegacyVNodeProperties(cloned)
}
return cloned
}
cloneVNode I have done so many things :
-
Merge props -
Create clone object -
Yes Vnode Deep cloning of child nodes
deepClone
Deep cloning , If the child node is an array type, recursive cloning will be performed .
function deepCloneVNode(vnode) {
const cloned = cloneVNode(vnode)
if (isArray(vnode.children)) {
cloned.children = vnode.children.map(deepCloneVNode)
}
return cloned
}
isVNode
It's simple , According to create Vnode Private attribute judgment when describing objects .
export function isVNode(value) {
return value ? value.__v_isVNode === true : false
}
normalizeChildren
stay _createVNode
in , We know , If Vnode
Purely at child nodes , Will execute normalizeChildren
Standardize and sort out sub nodes . Look at the below normalizeChildren
how :
export function normalizeChildren(vnode, children) {
let type = 0
const { shapeFlag } = vnode
// The following will be true of children Judge by type , Different types of , Different operating
if (children == null) {
// children yes null
children = null
} else if (isArray(children)) {
// children It's an array , Mark type by ARRAY_CHILDREN
type = ShapeFlags.ARRAY_CHILDREN
} else if (typeof children === 'object') {
// children It's the object
if (shapeFlag & ShapeFlags.ELEMENT || shapeFlag & ShapeFlags.TELEPORT) {
// Normalize slot to plain children for plain element and Teleport
const slot = (children).default
if (slot) {
// _c marker is added by withCtx() indicating this is a compiled slot
slot._c && (slot._d = false)
normalizeChildren(vnode, slot())
slot._c && (slot._d = true)
}
return
} else {
type = ShapeFlags.SLOTS_CHILDREN
const slotFlag = (children)._
if (!slotFlag && !(InternalObjectKey in children!)) {
;(children)._ctx = currentRenderingInstance
} else if (slotFlag === SlotFlags.FORWARDED && currentRenderingInstance) {
if (
(currentRenderingInstance.slots)._ === SlotFlags.STABLE
) {
;(children)._ = SlotFlags.STABLE
} else {
;(children)._ = SlotFlags.DYNAMIC
vnode.patchFlag |= PatchFlags.DYNAMIC_SLOTS
}
}
}
} else if (isFunction(children)) {
// children Is the function
children = { default: children, _ctx: currentRenderingInstance }
type = ShapeFlags.SLOTS_CHILDREN
} else {
children = String(children)
// force teleport children to array so it can be moved around
if (shapeFlag & ShapeFlags.TELEPORT) {
type = ShapeFlags.ARRAY_CHILDREN
children = [createTextVNode(children)]
} else {
type = ShapeFlags.TEXT_CHILDREN
}
}
vnode.children = children
vnode.shapeFlag |= type
}
As you can see from the code above ,normalizeChildren
Mainly for Vnode.children
And type
Made a normative comb .
isClassComponent
export function isClassComponent(value) {
return isFunction(value) && '__vccOpts' in value
}
normalizeStyle
When we bind components style
When , Maybe it's like this :
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data() {
return {
activeColor: 'red',
fontSize: 30
}
}
Dynamically bind through object syntax style
.
It may also be written like this :
<div :style="[baseStyles, overridingStyles]"></div>
data() {
return {
baseStyles: {
activeColor: 'red',
fontSize: 30
},
overridingStyles: {
display: flex
},
}
}
Bind multiple elements through an array style
object .
But these two ways of writing . In the end, it will pass normalizeStyle
Function to sort out the specification .
Look at the below normalizeStyle
function :
export function normalizeStyle(value) {
if (isArray(value)) {
const res = {}
for (let i = 0; i < value.length; i++) {
const item = value[i]
const normalized = normalizeStyle(
isString(item) ? parseStringStyle(item) : item
)
if (normalized) {
for (const key in normalized) {
res[key] = normalized[key]
}
}
}
return res
} else if (isObject(value)) {
return value
}
}
normalizeStyle
The function is very simple , By traversing recursively, the array type value
, The specification is the object type and returns .
normalizeClass
When we bind classes to nodes , There are basically three forms :
-
Bind as a string -
Bind as an object -
Bind as an array
But eventually bound to the node class
, with string
Handle ,normalizeClass
That's what I did .
Will all not string
The form of link is string
.
export function normalizeClass(value) {
let res = ''
if (isString(value)) {
res = value
} else if (isArray(value)) {
// Traversal recursive processing
for (let i = 0; i < value.length; i++) {
const normalized = normalizeClass(value[i])
if (normalized) {
res += normalized + ' '
}
}
} else if (isObject(value)) {
// Convert objects to string
for (const name in value) {
if (value[name]) {
res += name + ' '
}
}
}
return res.trim()
}
normalizeClass
The idea of function is actually the same as normalizeStyle
identical .
*Tip: This kind of traversal recursion often appears in interview questions .
*
mergeProps
In the previous analysis , We know , clone Vnode
In the process of , Call back mergeProps
Yes vnode.props
A merger . And will merge the mergedProps
Pass to cloned Vnode
.
Look at the below mergedProps
How to merge ?
export function mergeProps(...args) {
const ret = extend({}, args[0])
for (let i = 1; i < args.length; i++) {
const toMerge = args[i]
for (const key in toMerge) {
if (key === 'class') {
// merge Class
if (ret.class !== toMerge.class) {
ret.class = normalizeClass([ret.class, toMerge.class])
}
} else if (key === 'style') {
// merge Style
ret.style = normalizeStyle([ret.style, toMerge.style])
} else if (isOn(key)) {
// merge Listening events
const existing = ret[key]
const incoming = toMerge[key]
if (existing !== incoming) {
ret[key] = existing
? [].concat(existing, incoming)
: incoming
}
} else if (key !== '') {
ret[key] = toMerge[key]
}
}
}
return ret
}
-
It will be for the nodes class
、style
、 Combine bound events and non empty attributes -
The process of merging will affect class
、style
donormalize
Handle -
If you bind multiple events , All events will be stored in the array
withDirectives
function withDirectives(vnode, directives) {
const internalInstance = currentRenderingInstance
if (internalInstance === null) {
__DEV__ && warn(`withDirectives can only be used inside render functions.`)
return vnode
}
const instance = internalInstance.proxy
const bindings = vnode.dirs || (vnode.dirs = [])
for (let i = 0; i < directives.length; i++) {
let [dir, value, arg, modifiers] = directives[i]
if (isFunction(dir)) {
dir = {
mounted: dir,
updated: dir
}
}
bindings.push({
dir,
instance,
value,
oldValue,
arg,
modifiers
})
}
return vnode
}
From the above code, we can see ,withDirectives API
It's a simple idea , Is to configure objects by traversing instructions , Instructions to be configured push
to binding
Collection .
summary
h
The function is actually createVNode
The grammar sugar of , What's back is a Js
Common object . stay createVNode
API Creating Vnode
When , Would be right Vnode
Of props、children
、ref
、class
、style
And other attributes . If Type
Is directly Vnode
type , The of deep cloning will be returned Vnode
object . Compare with HTML
Template syntax , Use h
Function to create components Vnode
, More flexible , And more abstract .
Reference resources :
[ Official documents ](
copyright notice
author[Jian Darui],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/01/202201270415127114.html
The sidebar is recommended
- Spring IOC container loading process
- [thinking] the difference between singleton mode and static method - object-oriented programming
- Hadoop environment setup (MySQL environment configuration)
- 10 minutes, using node JS creates a real-time early warning system for bad weather!
- Git tool
- Force deduction algorithm - 92 Reverse linked list II
- What is the sub problem of dynamic programming?
- C / C + +: static keyword summary
- Idea does not have the artifacts option when configuring Tomcat
- Anaconda can't open it
guess what you like
-
I don't know how to start this
-
Matlab simulation of transportation optimization algorithm based on PSO
-
MySQL slow log optimization
-
[Vue] as the window is stretched (larger, smaller, wider and higher), the text will not be displayed
-
Popular Linux distributions for embedded computing
-
Suzhou computer research
-
After installing SSL Certificate in Windows + tomcat, the domain name request is not successful. Please answer!!
-
Implementation time output and greetings of jQuery instance
-
The 72 year old uncle became popular. Wu Jing and Guo fan made his story into a film, which made countless dreamers blush
-
How to save computer research
Random recommended
- Springboot implements excel import and export, which is easy to use, and poi can be thrown away
- The final examination subjects of a class are mathematical programming, and the scores are sorted and output from high to low
- Two pronged approach, Tsinghua Professor Pro code JDK and hotspot source code notes, one-time learning to understand
- C + + recursive knapsack problem
- The use of GIT and GitHub and the latest git tutorial are easy to understand -- Video notes of crazy God speaking
- PostgreSQL statement query
- Ignition database test
- Context didn't understand why he got a high salary?, Nginxfair principle
- Bootstrap switch switch control user's guide, springcloud actual combat video
- A list that contains only strings. What other search methods can be used except sequential search
- [matlab path planning] multi ant colony algorithm grid map path planning [including GUI source code 650]
- [matlab path planning] improved genetic algorithm grid map path planning [including source code phase 525]
- Iinternet network path management system
- Appium settings app is not running after 5000ms
- Reactnative foundation - 07 (background image, status bar, statusbar)
- Reactnative foundation - 04 (custom rpx)
- If you want an embedded database (H2, hsql or Derby), please put it on the classpath
- When using stm32g070 Hal library, if you want to write to flash, you must perform an erase. If you don't let it, you can't write continuously.
- Linux checks where the software is installed and what files are installed
- SQL statement fuzzy query and time interval filtering
- 69. Sqrt (x) (c + + problem solving version with vs runnable source program)
- Fresh students are about to graduate. Do you choose Java development or big data?
- Java project: OA management system (java + SSM + bootstrap + MySQL + JSP)
- Titanic passenger survival prediction
- Vectorization of deep learning formula
- Configuration and use of private image warehouse of microservice architect docker
- Relearn JavaScript events
- For someone, delete return 1 and return 0
- How does Java dynamically obtain what type of data is passed? It is used to judge whether the data is the same, dynamic data type
- How does the database cow optimize SQL?
- [data structure] chain structure of binary tree (pre order traversal) (middle order traversal) (post order traversal) (sequence traversal)
- Webpack packaging optimization solution
- 5. Operation element
- Detailed explanation of red and black trees
- redhat7. 9 install database 19C
- Blue Bridge Cup notes: (the given elements are not repeated) complete arrangement (arrangement cannot be repeated, arrangement can be repeated)
- Detailed explanation of springboot default package scanning mechanism and @ componentscan specified scanning path
- How to solve the run-time exception of test times
- Detailed explanation of k8s management tool kubectl
- Android system view memory command