vnode0数据:
- var vnode0 = {
- tag: 'ul',
- props: {
- id :'ul1',
- style: {color: 'red', fontSize: '14px'},
- 'data-index': 0,
- },
- on: {
- click:()=>console.log('click ul')
- },
- children: [
- {
- tag: 'li',
- children: 'a'
- },
- {
- tag: 'li',
- props: {
- className: 'list-item'
- },
- on: {
- click(e) {
- // e.stopPropagation();
- console.log('click li')
- }
- },
- children: [
- {
- tag: 'a',
- children: '好好学习'
- }
- ]
- },
- ]
- }
1. 核心方法: document.createElement + document.createDocumentFragment(推荐):
- let timer2 = new Date().getTime()
- const vDom = document.createDocumentFragment()
- function render2(vnode) {
- const dom = document.createElement(vnode.tag)
- const props = _.get(vnode, 'props')
- if(!_.isEmpty(props)) {
- for(let key in props) {
- const item = _.get(props, [key]);
- if(key === 'className') {
- dom.class = item
- }
- else {
- dom.setAttribute(key, item)
- }
- }
- }
-
- if(_.get(vnode, 'props.style')) {
- const styleObj = vnode.props.style
- let styleStr = ''
- for(let key in styleObj) {
- const item = styleObj[key]
- styleStr+= `${key.replace(/[A-Z]/g, str=>'-'+str.toLowerCase())}:${item};`
- }
- dom.style = styleStr
- }
- if(_.get(vnode, 'on')) {
- for(let key in vnode.on) {
- const item = vnode.on[key]
- dom[`on${key}`]=item
- }
- }
- const children = _.get(vnode, 'children');
-
- if(typeof children === 'string') {
- dom.innerText = children
- }
-
- if(Array.isArray(children) && !_.isEmpty(children)) {
- for(let item of children) {
- const dom0 = render2(item);
- dom.appendChild(dom0)
- }
- }
- vDom.appendChild(dom)
- console.log('render2时间', new Date().getTime()-timer2)
- return dom
- }
-
- render2(vnode0)
- document.getElementById('box').appendChild(vDom)
2. 使用innerHTML
注意事项:
1) 不适合需要在html字符串上加onclick等事件的情况, 要加等到页面渲染完成再需要找到那些dom元素自行添加
2) 适合那些直接把click事件加到父元素上的(比如box.addEventListener('click', e=>{...}), 通过冒泡获取子元素的属性key和属性值, 进行判断处理业务
3) 数据量大的时候比较消耗性能
- let timer1 = new Date().getTime()
- let str = '';
- function render(vnode) {
- str += `<${vnode.tag}`;
- if (_.get(vnode, 'props.id')) {
- str += ` id="${vnode.props.id}"`
- }
- if (_.get(vnode, 'props.className')) {
- str += ` class="${vnode.props.className}"`
- }
- if (_.get(vnode, 'props.style')) {
- const styleObj = vnode.props.style
- let styleStr = ''
- for (let key in styleObj) {
- const item = styleObj[key]
- styleStr += `${key.replace(/[A-Z]/g, str => '-' + str.toLowerCase())}:${item};`
- }
- str += ` style="${styleStr}"`
- }
- if (_.get(vnode, 'on')) {
- for (let key in vnode.on) {
- const item = vnode.on[key]
- // onclick事件不能添加...
- }
- }
- const children = vnode.children;
-
- if (typeof children === 'string') {
- str += `>${children}`
- }
-
- if (Array.isArray(children) && !_.isEmpty(children)) {
- str += '>'
- children.forEach(element => {
- render(element)
- });
- }
- str += `</${vnode.tag}>`;
- console.log('render时间', new Date().getTime() - timer1)
- return str
- }
-
- render(vnode0);
- document.getElementById('box').innerHTML = str;