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

开发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());

在这里插入图片描述

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

在这里插入图片描述

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

相关文章:

  • 经典算法 整数因子分解问题
  • 二分算法-day2
  • 【C#】关键字 volatile
  • 【驱动智能交通的关键引擎 解析C-V2X发展挑战】
  • (面试常问)C++中的static关键字——静态局部、静态全局、静态函数、静态与单例线程安全性(C++11之后)等
  • ​Android Gradle 插件(AGP)版本与 ​Gradle 版本需要严格对应
  • 体育赛事即时比分 分析页面的开发技术架构与实现细节
  • Python----计算机视觉处理(Opencv:图像噪点消除:滤波算法,噪点消除)
  • 「查缺补漏」巩固你的 RabbitMQ 知识体系
  • CNG汽车加气站操作工备考真题及答案解析【判断题】
  • Java-智能家居系统小案例
  • Linux: 网络,arp的数量为什么会对交换机/路由器有性能的影响
  • async/defer/preload性能优化
  • 基于SpringBoot和Vue的SQL TO API平台的设计与实现
  • SQL语言分类及命令详解(一)
  • Java面试黄金宝典20
  • Java 实现将Word 转换成markdown
  • 便携版:随时随地,高效处理 PDF 文件
  • 数据驱动的教育革命:让学习更智能、更个性化
  • BNB Chain 何以打造 AI 驱动链上应用新世界?
  • 空间站第八批科学实验样品返抵地球并交付科学家
  • “非思”的思想——探索失语者的思想史
  • 解放日报:让算力像“水电煤”赋能千行百业
  • 光明日报社论:用你我的匠心,托举起繁盛的中国
  • 中国空间站多项太空实验已取得成果,未来将陆续开展千余项研究
  • 海南机场拟超23亿元收购美兰空港控股权,进一步聚焦机场主业