vue3中h()函数renderSlot和createVNode(),openBlock与createBlock函数,withCtx与withDirectives,toDisplayString的使用
renderSlotexport declare function renderSlot(slots: Slots,name: string,props?: Data,fallback?: () => VNodeArrayChildren,noSlotted?: boolean): VNode;hexport declare function h(type: string,props?: R
·
createTextVNode
export declare function createTextVNode(
text?: string,
flag?: number
): VNode;
function createTextVNode(text = ' ', flag = 0) {
return createVNode(Text, null, text, flag);
}
toDisplayString
展示插值 {{ }}模板里边的内容
//shared
/**
* For converting {{ interpolation }} values to displayed strings.
* @private
*/
export declare const toDisplayString: (val: unknown) => string;
renderSlot
Compiler runtime helper for rendering <slot/>
渲染父组件的 v-slot
export declare function renderSlot(
slots: Slots,
name: string,
props?: Data,
fallback?: () => VNodeArrayChildren,
noSlotted?: boolean
): VNode;
createBlock
/**
* Create a block root vnode. Takes the same exact arguments as `createVNode`.
* A block root keeps track of dynamic nodes within the block in the
* `dynamicChildren` array.
*
* @private
*/
export declare function createBlock(
type: VNodeTypes | ClassComponent,
props?: Record<string, any> | null,
children?: any,
patchFlag?: number,
dynamicProps?: string[]
): VNode;
withCtx与withDirectives
/**
* Wrap a slot function to memoize current rendering instance
* @private compiler helper
*/
export declare function withCtx(fn: Function, ctx?: ComponentInternalInstance | null): Function;
/**
Runtime helper for applying directives to a vnode. Example usage:
const comp = resolveComponent('comp')
const foo = resolveDirective('foo')
const bar = resolveDirective('bar')
return withDirectives(h(comp), [
[foo, this.x],
[bar, this.y]
])
*/
/**
* Adds directives to a VNode.
*/
export declare function withDirectives<T extends VNode>(
vnode: T,
directives: DirectiveArguments
): T;
function withDirectives(vnode, directives) {
const internalInstance = currentRenderingInstance;
if (internalInstance === null) {
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 = shared.EMPTY_OBJ] = directives[i];
if (shared.isFunction(dir)) {
dir = {
mounted: dir,
updated: dir
};
}
bindings.push({
dir,
instance,
value,
oldValue: void 0,
arg,
modifiers
});
}
return vnode;
}
openBlock与createBlock
/**
* Open a block.
* This must be called before `createBlock`. It cannot be part of `createBlock`
* because the children of the block are evaluated before `createBlock` itself
* is called. The generated code typically looks like this:
*
* ```js
* function render() {
* return (openBlock(),createBlock('div', null, [...]))
* }
* ```
* disableTracking is true when creating a v-for fragment block, since a v-for
* fragment always diffs its children.
*
* @private
*/
export declare function openBlock(disableTracking?: boolean): void;
组合使用
export function renderBlock(
node: VNodeTypes,
props: any,
children?: Children,
patchFlag?: number,
patchProps?: string[],
) {
return (openBlock(), createBlock(node, props, children, patchFlag, patchProps))
}
/**
* Create a block root vnode. Takes the same exact arguments as `createVNode`.
* A block root keeps track of dynamic nodes within the block in the
* `dynamicChildren` array.
*
* @private
*/
export declare function createBlock(
type: VNodeTypes | ClassComponent,
props?: Record<string, any> | null,
children?: any,
patchFlag?: number,
dynamicProps?: string[]
): VNode;
function createBlock(type, props, children, patchFlag, dynamicProps) {
const vnode = createVNode(type, props, children, patchFlag, dynamicProps, true /* isBlock: prevent a block from tracking itself */);
// save current block children on the block vnode
vnode.dynamicChildren = currentBlock || shared.EMPTY_ARR;
// close block
closeBlock();
// a block is always going to be patched, so track it as a child of its
// parent block
if (shouldTrack > 0 && currentBlock) {
currentBlock.push(vnode);
}
return vnode;
}
h
export declare function h(
type: string,
props?: RawProps | null,
children?: RawChildren | RawSlots
): VNode;
createVNode
export const createVNode = (__DEV__
? createVNodeWithArgsTransform
: _createVNode) as typeof _createVNode
function _createVNode(
type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
props: (Data & VNodeProps) | null = null,
children: unknown = null,
patchFlag: number = 0,
dynamicProps: string[] | null = null,
isBlockNode = false
)
详尽参考
return props.mask
? createVNode(
'div',
{
class: ['el-overlay', props.overlayClass],
style: {
zIndex: props.zIndex,
},
onClick: onMaskClick,
onMousedown: (e: MouseEvent) => {
// marking current mousedown target.
if (props.mask) {
mousedownTarget = e.target === e.currentTarget
}
},
onMouseup: (e: MouseEvent) => {
if (props.mask) {
mouseupTarget = e.target === e.currentTarget
}
},
},
[renderSlot(slots, 'default')],
PatchFlags.STYLE | PatchFlags.CLASS | PatchFlags.PROPS,
['onClick', 'onMouseup', 'onMousedown'],
)
: h(
'div',
{
style: {
zIndex: props.zIndex,
position: 'fixed',
top: '0px',
right: '0px',
bottom: '0px',
left: '0px',
},
},
[renderSlot(slots, 'default')],
)
}
```
### PatchFlag
```js
/**
* Patch flags are optimization hints generated by the compiler.
* when a block with dynamicChildren is encountered during diff, the algorithm
* enters "optimized mode". In this mode, we know that the vdom is produced by
* a render function generated by the compiler, so the algorithm only needs to
* handle updates explicitly marked by these patch flags.
*
* Patch flags can be combined using the | bitwise operator and can be checked
* using the & operator, e.g.
*
* ```js
* const flag = TEXT | CLASS
* if (flag & TEXT) { ... }
* ```
*
* Check the `patchElement` function in '../../runtime-core/src/renderer.ts' to see how the
* flags are handled during diff.
*/
export declare const enum PatchFlags {
/**
* Indicates an element with dynamic textContent (children fast path)
*/
TEXT = 1,
/**
* Indicates an element with dynamic class binding.
*/
CLASS = 2,
/**
* Indicates an element with dynamic style
* The compiler pre-compiles static string styles into static objects
* + detects and hoists inline static objects
* e.g. style="color: red" and :style="{ color: 'red' }" both get hoisted as
* const style = { color: 'red' }
* render() { return e('div', { style }) }
*/
STYLE = 4,
/**
* Indicates an element that has non-class/style dynamic props.
* Can also be on a component that has any dynamic props (includes
* class/style). when this flag is present, the vnode also has a dynamicProps
* array that contains the keys of the props that may change so the runtime
* can diff them faster (without having to worry about removed props)
*/
PROPS = 8,
/**
* Indicates an element with props with dynamic keys. When keys change, a full
* diff is always needed to remove the old key. This flag is mutually
* exclusive with CLASS, STYLE and PROPS.
*/
FULL_PROPS = 16,
/**
* Indicates an element with event listeners (which need to be attached
* during hydration)
*/
HYDRATE_EVENTS = 32,
/**
* Indicates a fragment whose children order doesn't change.
*/
STABLE_FRAGMENT = 64,
/**
* Indicates a fragment with keyed or partially keyed children
*/
KEYED_FRAGMENT = 128,
/**
* Indicates a fragment with unkeyed children.
*/
UNKEYED_FRAGMENT = 256,
/**
* Indicates an element that only needs non-props patching, e.g. ref or
* directives (onVnodeXXX hooks). since every patched vnode checks for refs
* and onVnodeXXX hooks, it simply marks the vnode so that a parent block
* will track it.
*/
NEED_PATCH = 512,
/**
* Indicates a component with dynamic slots (e.g. slot that references a v-for
* iterated value, or dynamic slot names).
* Components with this flag are always force updated.
*/
DYNAMIC_SLOTS = 1024,
/**
* Indicates a fragment that was created only because the user has placed
* comments at the root level of a template. This is a dev-only flag since
* comments are stripped in production.
*/
DEV_ROOT_FRAGMENT = 2048,
/**
* SPECIAL FLAGS -------------------------------------------------------------
* Special flags are negative integers. They are never matched against using
* bitwise operators (bitwise matching should only happen in branches where
* patchFlag > 0), and are mutually exclusive. When checking for a special
* flag, simply check patchFlag === FLAG.
*/
/**
* Indicates a hoisted static vnode. This is a hint for hydration to skip
* the entire sub tree since static content never needs to be updated.
*/
HOISTED = -1,
/**
* A special flag that indicates that the diffing algorithm should bail out
* of optimized mode. For example, on block fragments created by renderSlot()
* when encountering non-compiler generated slots (i.e. manually written
* render functions, which should always be fully diffed)
* OR manually cloneVNodes
*/
BAIL = -2
}
更多推荐
已为社区贡献1条内容
所有评论(0)