当前位置: 首页 > article >正文

开发DOM更新算法

开发DOM更新算法

  • 首先实现重新渲染视图的方法
update(data) {
    if (!data || (Array.isArray(data) && data.length === 0))
      return this.renderError();

    this._data = data;
    //调用_generateMarkup()方法生成新的HTML标记字符串
    const newMarkup = this._generateMarkup();
	
    //使用 document.createRange().createContextualFragment() 将字符串转换为文档片段(DOM)
    const newDOM = document.createRange().createContextualFragment(newMarkup);
    //使用 querySelectorAll('*') 获取新 DOM 中的所有元素
    const newElements = newDOM.querySelectorAll('*');
    console.log(newElements);
  }
  • 之后我们在更新份数的视图中进行更新一下
const controlServings = function (newServings) {
  //更新菜谱份数(在状态上)
  model.updateServings(newServings);

  //更新菜谱视图
  recipeView.update(model.state.recipe);
};

  • 之后我们看下控制台的输出,会生成所有的虚拟DOM;

在这里插入图片描述

  • 之后我们获取一下当前的DOM中的所有元素,并且都给他转换成数组,方便后续操作
    const newElements = Array.from(newDOM.querySelectorAll('*'));
    const curElements = Array.from(this._parentElement.querySelectorAll('*'));
  • 接着就是差异比较和更新一下DOM了
  update(data) {
    if (!data || (Array.isArray(data) && data.length === 0))
      return this.renderError();

    this._data = data;
    const newMarkup = this._generateMarkup();

    const newDOM = document.createRange().createContextualFragment(newMarkup);
    const newElements = Array.from(newDOM.querySelectorAll('*'));
    const curElements = Array.from(this._parentElement.querySelectorAll('*'));

    newElements.forEach((newEl, i) => {
      const curEl = curElements[i];
      if (
        !newEl.isEqualNode(curEl) &&
        newEl.firstChild?.nodeValue.trim() !== ''
      ) {
        curEl.textContent = newEl.textContent;
      }
    });
  }

上述代码的知识点回顾

  1. DocumentFragment: 轻量级的文档对象,不在主 DOM 树中,可以高效地进行 DOM 操作;
  2. createContextualFragment: 将 HTML 字符串解析为 DOM 片段的方法;
  3. isEqualNode: 比较两个节点是否相同的 DOM 方法;
  4. 虚拟 DOM 概念: 类似于 React 的虚拟 DOM 思想,先比较再局部更新;
  5. querySelectorAll(‘*’): 获取元素下的所有子元素
  • 接着我们文本的局部更新应该没有什么问题了

在这里插入图片描述

  • 接着继续更新属性
     //更新改变的属性
      if (!newEl.isEqualNode(curEl))
        Array.from(newEl.attributes).forEach(attr =>
          curEl.setAttribute(attr.name, attr.value)
        );
    });
  }

请添加图片描述

  • 我们可以同样使用上面的方法来实现当我们点击菜谱的时候,菜谱的状态是被选中的状态;
  _generateMarkupPreview(result) {
    const id = window.location.hash.slice(1);
    return `   
        <li class="preview">
            <a class="preview__link ${
              result.id === id ? 'preview__link--active' : ''
            }" href="#${result.id}">
              <figure class="preview__fig">
                <img src="${result.image}" alt="${result.title}" />
              </figure>
              <div class="preview__data">
                <h4 class="preview__title">${result.title}</h4>
                <p class="preview__publisher">${result.publisher}</p>
              </div>
            </a>
          </li>`;
  }
}

  • 之后再控制器中调用该方法
    //0当选中搜索结果时更新结果视图
    resultsView.update(model.getSearchResultsPage());

在这里插入图片描述

  • 但当我们更新的话,这个条线部分为真,所以会报错找不到食谱,我们去除掉就可以了

在这里插入图片描述

下面的文章我们就要来实现书签的功能了;


http://www.kler.cn/a/612063.html

相关文章:

  • [python]基于yolov8实现热力图可视化支持图像视频和摄像头检测
  • CentOS 7安装 mysql
  • 老是忘记package.json,备忘一下 webpack 环境下 Vue Cli 和 Vite 命令行工具对比
  • 【Pandas】pandas Series to_xarray
  • SpringBoot集成腾讯云OCR实现身份证识别
  • 【牛客网】数据分析笔试刷题
  • Charles抓HTTPS包
  • 数据结构:汉诺塔问题的递归求解和分析
  • 部分 Bash 内置命令的详解
  • 企业网站源码HTML成品网站与网页代码模板指南
  • 学习记录-Ajax-自封装axios函数
  • RAMS(区域大气建模系统)评估土地利用/覆被变化的气候与水文效应
  • 【Django】教程-3-数据库相关介绍
  • NVIDIA Megatron Core:大规模语言模型训练与部署框架详解
  • [250325] Claude AI 现已支持网络搜索功能!| ReactOS 0.4.15 发布!
  • 英语不好,可以考取Oracle OCP认证吗?
  • HO与OH差异之Navigation三
  • Android第六次面试总结(自定义 View与事件分发)
  • Unity Shader编程】之FallBack
  • CSS3:现代Web设计的魔法卷轴