是什么
描述真实DOM的javaScript对象
//虚拟dom描述的对象const vdom = {tag: 'div',props: {onclick: () => alert('clicked'),},children: ["click me"]}
渲染器
将虚拟dom渲染成真实dom
实现思路
- 创建元素
将vnode.tag作为标签名来创建元素 - 给元素添加属性与事件
遍历vnode.props对象 - 处理children
如果children是一个数组就递归的调用render继续渲染
代码
// 定义渲染器将上列虚拟DOM描述为真实的DOMfunction render(vdom,container) {// 创建真实的DOM元素const el = document.createElement(vdom.tag)// 设置属性for (let key in vdom.props) {//是事件if (key.startsWith('on')) {el.addEventListener(key.slice(2).toLowerCase(), vdom.props[key])}else{//不是事件el.setAttribute(key, vdom.props[key])}}// 处理childenif (Array.isArray(vdom.children)) {vdom.children.forEach(child => {// 如果是字符串,则创建文本节点if (typeof child === 'string') {el.appendChild(document.createTextNode(child))} else if (typeof child === 'object' && child.tag) {// 如果是对象,则递归调用render函数el.appendChild(render(child))}});}// 将创建的DOM元素添加到挂载点container.appendChild(el)}
代码–渲染组件
//定义一个函数表示组件,函数的返回值就代表组件要渲染的内容,(返回值使用虚拟dom表示)const MyComponent = () => {return {tag: 'div',props: {onclick: ()=>{alert('hello')}},children:'click me'}}// 虚拟dom来描述组件const vdom = {tag:MyComponent,}//渲染函数const render =(vdom,container)=>{//判断vdom的类型if(typeof vdom.tag === 'string'){//如果是字符串,就创建一个元素const el = document.createElement(vdom.tag)//如果是事件if(vdom.props){for(let key in vdom.props){if(key.startsWith('on')){//如果是事件,就添加事件监听器el.addEventListener(key.slice(2).toLowerCase(),vdom.props[key])}else{//如果是属性,就添加属性el.setAttribute(key,vdom.props[key])}}}//如果有子元素,就递归调用render函数if(vdom.children){//如果是字符串if(typeof vdom.children === 'string'){el.textContent = vdom.children}//如果是数组else if(Array.isArray(vdom.children)){vdom.children.forEach(child => render(child,el))}}//将元素添加到容器中container.appendChild(el)}else{//如果是函数,就调用函数,得到虚拟domconst componentVdom = vdom.tag()//递归调用render函数render(componentVdom,container)}}