• 使用js对象简单模拟虚拟dom的渲染


    vnode0数据:

    1. var vnode0 = {
    2. tag: 'ul',
    3. props: {
    4. id :'ul1',
    5. style: {color: 'red', fontSize: '14px'},
    6. 'data-index': 0,
    7. },
    8. on: {
    9. click:()=>console.log('click ul')
    10. },
    11. children: [
    12. {
    13. tag: 'li',
    14. children: 'a'
    15. },
    16. {
    17. tag: 'li',
    18. props: {
    19. className: 'list-item'
    20. },
    21. on: {
    22. click(e) {
    23. // e.stopPropagation();
    24. console.log('click li')
    25. }
    26. },
    27. children: [
    28. {
    29. tag: 'a',
    30. children: '好好学习'
    31. }
    32. ]
    33. },
    34. ]
    35. }

    一. 用js模拟dom结构:

    1. 核心方法: document.createElement + document.createDocumentFragment(推荐):

    1. let timer2 = new Date().getTime()
    2. const vDom = document.createDocumentFragment()
    3. function render2(vnode) {
    4. const dom = document.createElement(vnode.tag)
    5. const props = _.get(vnode, 'props')
    6. if(!_.isEmpty(props)) {
    7. for(let key in props) {
    8. const item = _.get(props, [key]);
    9. if(key === 'className') {
    10. dom.class = item
    11. }
    12. else {
    13. dom.setAttribute(key, item)
    14. }
    15. }
    16. }
    17. if(_.get(vnode, 'props.style')) {
    18. const styleObj = vnode.props.style
    19. let styleStr = ''
    20. for(let key in styleObj) {
    21. const item = styleObj[key]
    22. styleStr+= `${key.replace(/[A-Z]/g, str=>'-'+str.toLowerCase())}:${item};`
    23. }
    24. dom.style = styleStr
    25. }
    26. if(_.get(vnode, 'on')) {
    27. for(let key in vnode.on) {
    28. const item = vnode.on[key]
    29. dom[`on${key}`]=item
    30. }
    31. }
    32. const children = _.get(vnode, 'children');
    33. if(typeof children === 'string') {
    34. dom.innerText = children
    35. }
    36. if(Array.isArray(children) && !_.isEmpty(children)) {
    37. for(let item of children) {
    38. const dom0 = render2(item);
    39. dom.appendChild(dom0)
    40. }
    41. }
    42. vDom.appendChild(dom)
    43. console.log('render2时间', new Date().getTime()-timer2)
    44. return dom
    45. }
    46. render2(vnode0)
    47. document.getElementById('box').appendChild(vDom)

    2. 使用innerHTML

    注意事项:

    1) 不适合需要在html字符串上加onclick等事件的情况, 要加等到页面渲染完成再需要找到那些dom元素自行添加

    2) 适合那些直接把click事件加到父元素上的(比如box.addEventListener('click', e=>{...}), 通过冒泡获取子元素的属性key和属性值, 进行判断处理业务

    3) 数据量大的时候比较消耗性能

    1. let timer1 = new Date().getTime()
    2. let str = '';
    3. function render(vnode) {
    4. str += `<${vnode.tag}`;
    5. if (_.get(vnode, 'props.id')) {
    6. str += ` id="${vnode.props.id}"`
    7. }
    8. if (_.get(vnode, 'props.className')) {
    9. str += ` class="${vnode.props.className}"`
    10. }
    11. if (_.get(vnode, 'props.style')) {
    12. const styleObj = vnode.props.style
    13. let styleStr = ''
    14. for (let key in styleObj) {
    15. const item = styleObj[key]
    16. styleStr += `${key.replace(/[A-Z]/g, str => '-' + str.toLowerCase())}:${item};`
    17. }
    18. str += ` style="${styleStr}"`
    19. }
    20. if (_.get(vnode, 'on')) {
    21. for (let key in vnode.on) {
    22. const item = vnode.on[key]
    23. // onclick事件不能添加...
    24. }
    25. }
    26. const children = vnode.children;
    27. if (typeof children === 'string') {
    28. str += `>${children}`
    29. }
    30. if (Array.isArray(children) && !_.isEmpty(children)) {
    31. str += '>'
    32. children.forEach(element => {
    33. render(element)
    34. });
    35. }
    36. str += `</${vnode.tag}>`;
    37. console.log('render时间', new Date().getTime() - timer1)
    38. return str
    39. }
    40. render(vnode0);
    41. document.getElementById('box').innerHTML = str;

  • 相关阅读:
    Linux 定时删除7天前的文件
    Linux基础知识,这里有很多内容可以看看~
    浅谈基于云计算的环境智能监控系统
    Java(八)----多线程
    speexdsp库实现音频3A算法,speexdsp库编译,C/C++语言
    电脑重装系统c盘如何备份资料
    什么是外贸独立站
    MySQL数据库基本使用
    JAVA设计模式--创建型模式--抽象工厂模式
    中国BI步入增长大周期,腾讯云ChatBI加速AI+BI融合
  • 原文地址:https://blog.csdn.net/qq_42750608/article/details/133561319