vue3中 h()函数
先看结果//类型判断函数const isObject = (val) => val !==null && typeof val === 'object'const isString = (val) => typeof val === 'string'const isFunction = (val) => typeof val === 'function';cons
·
看结果
利用h()函数时可以传节点标签,样式,以及节点内容
//类型判断函数
const isObject = (val) => val !==null && typeof val === 'object'
const isString = (val) => typeof val === 'string'
const isFunction = (val) => typeof val === 'function';
const isArray = Array.isArray
const InternalObjectKey = `__vInternal`;
//?
function isVNode(value) {
return value ? value.__v_isVNode === true : false;
}
let vnodeArgsTransformer;
let currentRenderingInstance = null;
let currentScopeId = null;
let currentBlock = null;
let isBlockTreeEnabled = 1;
const Text = Symbol('Text');
//?
function isClassComponent(value) {
return isFunction(value) && '__vccOpts' in value;
}
const normalizeKey = ({ key }) => key != null ? key : null;
const normalizeRef = ({ ref }) => {
return (ref != null
? isString(ref) || isRef(ref) || isFunction(ref)
? { i: currentRenderingInstance, r: ref }
: ref
: null);
};
function createTextVNode(text = ' ', flag = 0) {
return createVNode(Text, null, text, flag);
}
function normalizeChildren(vnode, children) {
let type = 0;
const { shapeFlag } = vnode; //值为 1
//34 -74 类型判断 传入的 string类型数据 不执行
if (children == null) {
children = null;
}
else if (isArray(children)) {
type = 16 /* ARRAY_CHILDREN */;
}
else if (typeof children === 'object') {
if (shapeFlag & (1 /* ELEMENT */ | 64 /* 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 = 32 /* SLOTS_CHILDREN */;
const slotFlag = children._;
if (!slotFlag && !(InternalObjectKey in children)) {
children._ctx = currentRenderingInstance;
}
else if (slotFlag === 3 /* FORWARDED */ && currentRenderingInstance) {
// a child component receives forwarded slots from the parent.
// its slot type is determined by its parent's slot type.
if (currentRenderingInstance.slots._ === 1 /* STABLE */) {
children._ = 1 /* STABLE */;
}
else {
children._ = 2 /* DYNAMIC */;
vnode.patchFlag |= 1024 /* DYNAMIC_SLOTS */;
}
}
}
}
else if (isFunction(children)) {
children = { default: children, _ctx: currentRenderingInstance };
type = 32 /* SLOTS_CHILDREN */;
}
else {
children = String(children);
console.log(children,'children的值')
// force teleport children to array so it can be moved around
if (shapeFlag & 64 /* TELEPORT */) {
type = 16 /* ARRAY_CHILDREN */;
children = [createTextVNode(children)];
}
else {
type = 8 /* TEXT_CHILDREN */;
}
}
vnode.children = children;
vnode.shapeFlag |= type;
console.log(vnode,'最终返回的 vnode值')
}
//传入 type =h1 props =null children ='title' patchFlag = 0, dynamicProps = null, isBlockNode = false ,true
function createBaseVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null, shapeFlag = type === Fragment ? 0 : 1 /* ELEMENT */, isBlockNode = false, needFullChildrenNormalization = false) {
//相当于constructor构造函数 needFullChildrenNormalization默认值为 false 我们给它传入值为 true
const vnode = {
__v_isVNode: true,
__v_skip: true,
type,
props,
// key: props && normalizeKey(props), 先注释掉
// ref: props && normalizeRef(props),
scopeId: currentScopeId,
slotScopeIds: null,
children,
component: null,
suspense: null,
ssContent: null,
ssFallback: null,
dirs: null,
transition: null,
el: null,
anchor: null,
target: null,
targetAnchor: null,
staticCount: 0,
shapeFlag, // 值为1
patchFlag,
dynamicProps,
dynamicChildren: null,
appContext: null
};
console.log(vnode,'被创建的 vnode对象')
//这里值为true 进入代码块
if (needFullChildrenNormalization) {
//传入创建好的 vnode children 还是之前传入的 'title'
normalizeChildren(vnode, children); // #30
// normalize suspense children
console.log(shapeFlag & 128,'与操作结果1')
//这段代码不执行
if (shapeFlag & 128 /* SUSPENSE */) {
type.normalize(vnode);
}
}
else if (children) {
// compiled element vnode - if children is passed, only possible types are
// string or Array.
vnode.shapeFlag |= isString(children)
? 8 /* TEXT_CHILDREN */
: 16 /* ARRAY_CHILDREN */;
}
// validate key
if (vnode.key !== vnode.key) {
warn$1(`VNode created with invalid key (NaN). VNode type:`, vnode.type);
}
// track vnode for block tree
if (isBlockTreeEnabled > 0 &&
// avoid a block node from tracking itself
!isBlockNode &&
// has current parent block
currentBlock &&
// presence of a patch flag indicates this node needs patching on updates.
// component nodes also should always be patched, because even if the
// component doesn't need to update, it needs to persist the instance on to
// the next vnode so that it can be properly unmounted later.
(vnode.patchFlag > 0 || shapeFlag & 6 /* COMPONENT */) &&
// the EVENTS flag is only for hydration and if it is the only flag, the
// vnode should not be considered dynamic due to handler caching.
vnode.patchFlag !== 32 /* HYDRATE_EVENTS */) {
currentBlock.push(vnode);
}
return vnode;
}
function isReactive(value) {
if (isReadonly(value)) {
return isReactive(value["__v_raw" /* RAW */]);
}
return !!(value && value["__v_isReactive" /* IS_REACTIVE */]);
}
function isReadonly(value) {
return !!(value && value["__v_isReadonly" /* IS_READONLY */]);
}
function isProxy(value) {
return isReactive(value) || isReadonly(value);
}
function normalizeStyle(value) {
if (isArray(value)) {
const res = {};
for (let i = 0; i < value.length; i++) {
const item = value[i];
const normalized = isString(item)
? parseStringStyle(item)
: normalizeStyle(item);
if (normalized) {
for (const key in normalized) {
res[key] = normalized[key];
}
}
}
return res;
}
else if (isString(value)) {
return value;
}
else if (isObject(value)) {
return value;
}
}
//判断传入的props 是否为 proxy拦截 对象
function guardReactiveProps(props) {
if (!props)
return null;
return isProxy(props) || InternalObjectKey in props
? extend({}, props)
: props;
}
function _createVNode(type, props = null, children = null, patchFlag = 0, dynamicProps = null, isBlockNode = false) {
console.log(type,'传入type的值') //之前使用h() 函数传递 h1
console.log(props,'传入props的值') //这里默认值就为null
console.log(children,'传入children的值') // 这里为传入的值 'title'
//判断值为 false 不进入
// if (!type || type === NULL_DYNAMIC_COMPONENT) {
// if (!type) {
// warn$1(`Invalid vnode type when creating vnode: ${type}.`);
// }
// type = Comment$1;
// }
console.log(isVNode(type),'判断是否为虚拟节点')
//判断是否是否是虚拟节点,我们这里传的是h1节点,并不是虚拟节点。所以判断值为false
//并不会执行这一作用域的代码
if (isVNode(type)) {
// createVNode receiving an existing vnode. This happens in cases like
// <component :is="vnode"/>
// #2078 make sure to merge refs during the clone instead of overwriting it
const cloned = cloneVNode(type, props, true /* mergeRef: true */);
if (children) {
normalizeChildren(cloned, children);
}
return cloned;
}
console.log(isClassComponent(type),'判断是否为classComponetn') //我们传入type 为h1 控制台输出为 false
// class component normalization.
if (isClassComponent(type)) {
type = type.__vccOpts;
}
//props 值为null 下面作用域代码并不会执行
// class & style normalization.
if (props) {
// for reactive or proxy objects, we need to clone it to enable mutation.
props = guardReactiveProps(props);
console.log(props,'传入值为对象时的props')
//传入样式属性
let { class: klass, style } = props;
if (klass && !isString(klass)) {
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);
}
}
// encode the vnode type information into a bitmap
console.log(isString(type),'判断传入节点是否为string') //控制台输出为true
//shapeFlag 值为1
const shapeFlag = isString(type)
? 1 /* ELEMENT */
: isSuspense(type)
? 128 /* SUSPENSE */
: isTeleport(type)
? 64 /* TELEPORT */
: isObject(type)
? 4 /* STATEFUL_COMPONENT */
: isFunction(type)
? 2 /* FUNCTIONAL_COMPONENT */
: 0;
console.log(shapeFlag&4,'与操作结果') //控制台输出为 0
if (shapeFlag & 4 /* STATEFUL_COMPONENT */ && isProxy(type)) {
type = toRaw(type);
//百度翻译了一下,我们设置的type 为h1 是不会报这个警告
// Vue接收到一个组件,该组件被设置为反应对象。这个可以导致不必要的性能开销,
// 应通过以下方式避免使用“markRaw”或“shallowRef”标记组件+而不是“ref”`.`\n使其成为反应性的组件
warn$1(`Vue received a Component which was made a reactive object. This can ` +
`lead to unnecessary performance overhead, and should be avoided by ` +
`marking the component with \`markRaw\` or using \`shallowRef\` ` +
`instead of \`ref\`.`, `\nComponent that was made reactive: `, type);
}
//最终返回的一个被创建的baseNode节点
//传入 type =h1 props =null children ='title' patchFlag = 0, dynamicProps = null, isBlockNode = false ,true
return createBaseVNode(type, props, children, patchFlag, dynamicProps, shapeFlag, isBlockNode, true);
}
const createVNodeWithArgsTransform = (...args) => {
// vnodeArgsTransformer 值为Undefined 所以取的是后半段args的结构
console.log(...(vnodeArgsTransformer ? vnodeArgsTransformer(args, currentRenderingInstance): args),'args解构后的值')
return _createVNode(...(vnodeArgsTransformer ? vnodeArgsTransformer(args, currentRenderingInstance): args));
};
const createVNode = (createVNodeWithArgsTransform )
function h(type, propsOrChildren, children) {
const l = arguments.length;
console.log(l,'arguments.lenght')
if (l === 2) {
if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
// single vnode without props
if (isVNode(propsOrChildren)) {
return createVNode(type, null, [propsOrChildren]);
}
// props without children
return createVNode(type, propsOrChildren);
}
else {
// omit props
return createVNode(type, null, propsOrChildren);
}
}
else {
if (l > 3) {
children = Array.prototype.slice.call(arguments, 2);
}
else if (l === 3 && isVNode(children)) {
children = [children];
}
return createVNode(type, propsOrChildren, children);
}
}
var result = h('h1',{style:{color:'red'}},{title:1})
console.log(result,'最终得到的result')
// const a =(...args)=>{
// console.log(args)
// }
// const b= (a)
更多推荐
已为社区贡献5条内容
所有评论(0)