react核心功能实现
2021 M02 14
前言
react核心其实挺多的,但面试能说上元素创建和基本渲染过程基本就算合格。 而在此基础上,能说清楚diff算法的三层比较策略,15.x的递归不可打断更新和 16.x以后的循环可打断更新,又是一波加分项。
本篇为源码系列核心实现第七篇,对应下图react部分。
本篇不会像之前的那些细致化的去写,因为我发现了一个写的十分优秀的库,就不献丑了。
createElement
大道至极,这个其实就是虚拟dom,一个用于描述真实dom结构的js对象。
function createElement( tag, attrs={}, ...children ) {
return {
tag,
attrs,
children,
}
}
render
render做了很多事,但最主要的是把上边创建的虚拟dom转化成真实dom。 当然,这之中还会涉及事件绑定,样式处理,diff算法什么的,这里只做一个简化展示。
function render( vnode, container ) {
// 当vnode为字符串时,渲染结果是一段文本
if ( typeof vnode === 'string' ) {
const textNode = document.createTextNode( vnode );
return container.appendChild( textNode );
}
const dom = document.createElement( vnode.tag );
if ( vnode.attrs ) {
Object.keys( vnode.attrs ).forEach( key => {
const value = vnode.attrs[ key ];
setAttribute( dom, key, value ); // 设置属性
} );
}
// 递归渲染子节点
vnode.children.forEach( child => render( child, dom ) );
// 将渲染结果挂载到真正的DOM上
return container.appendChild( dom );
}
function setAttribute( dom, name, value ) {
// 如果属性名是className,则改回class
if ( name === 'className' ) name = 'class';
// 如果属性名是onXXX,则是一个事件监听方法
if ( /on\w+/.test( name ) ) {
name = name.toLowerCase();
dom[ name ] = value || '';
// 如果属性名是style,则更新style对象
} else if ( name === 'style' ) {
if ( !value || typeof value === 'string' ) {
dom.style.cssText = value || '';
} else if ( value && typeof value === 'object' ) {
for ( let name in value ) {
// 可以通过style={ width: 20 }这种形式来设置样式,可以省略掉单位px
dom.style[ name ] = typeof value[ name ] === 'number' ?
value[ name ] + 'px' : value[ name ];
}
}
// 普通属性则直接更新属性
} else {
if ( name in dom ) {
dom[ name ] = value || '';
}
if ( value ) {
dom.setAttribute( name, value );
} else {
dom.removeAttribute( name );
}
}
}
相关链接
再会
情如风雪无常,
却是一动既殇。
感谢你这么好看还来阅读我的文章,
我是冷月心,下期再见。