如何动态生成一个新的节点及它的子节点

前言

相信许多js小白都只会在html里的body里用最普通的方式来创建标签,这种做法有一个最大的弊端就是灵活性太差及难以复用,本文将用一个具体的例子------面向对象设计的EditInPlace功能类,来讲解如何动态生成节点和它的子节点,并简单聊聊这样做的优劣。

基础概念

定义:动态生成节点是指在页面加载后,使用JavaScript代码根据用户交互或其他条件实时创建新的HTML元素,并将其添加到现有文档结构中的过程。

主要API

  • document.createElement(tagName): 创建一个新的HTML元素。
  • element.appendChild(childNode): 将一个子节点添加到指定父节点下。
  • element.insertBefore(newNode, referenceNode): 在指定参考节点之前插入新节点。
  • element.replaceChild(newChild, oldChild): 用新节点替换旧节点。

这些API提供了强大的能力,使得开发者能够轻松地改变页面内容而无需重新加载整个页面。这对于实现单页应用(SPA)或需要频繁更新数据的应用程序尤为重要。

EditInPlace类的设计与实现

EditInPlace是一个用于实现就地编辑功能的JavaScript类。它允许用户直接在网页上编辑文本内容,而不需要跳转至另一个页面或打开对话框。这个类的设计采用了面向对象的方法,封装了创建可编辑区域所需的所有逻辑。

类构造函数

先创建一个构造函数,在这个构造函数里,我们初始化了三个主要属性:唯一标识符id、目标父元素parent以及默认显示的文本value。如果没有提供parent,则默认为文档体;如果没有设置value的值,则默认打印这个家伙很懒,什么都没有留下 。紧接着调用了createElement方法来创建并配置相应的DOM元素。具体代码如下图:

javascript 复制代码
function EditInPlace(id, parent, value) {
  this.id = id; // 跨函数共享属性
  this.parent = parent || document.body;
  this.value = value || '这个家伙很懒,什么都没有留下';
  this.createElement(this.id);
}

创建容器元素

这里,createElement方法负责实际创建所需的DOM结构。首先,创建了一个<div>元素作为容器,并设置了它的id属性。然后,将该容器添加到指定的父元素下。接着,在此容器内部再创建一个<span>元素用于展示初始文本值,并将其添加到div容器中。

javascript 复制代码
EditInPlace.prototype.createElement = function(id) {
  this.containerElement = document.createElement('div');
  this.containerElement.id = this.id;
  this.parent.appendChild(this.containerElement);

  this.staticElement = document.createElement('span');
  this.staticElement.innerText = this.value;
  this.containerElement.appendChild(this.staticElement);
}

输出效果

我们可以在html里实例化两次EditInPlace类,将他们分别指定不同的id和初始值,然后我们可以在网页中添加两个可编辑的区域,并在这些区域中输入或修改内容,我们先确保<div id="app">存在于页面上,然后引入EditInPlace功能。随后,两个新的EditInPlace实例被创建出来,它们都被添加到了#app下,但各自拥有独立的ID和初始化文本

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>面向对象的editInPlace</title>
</head>
<body>
  <div id="app">
  </div>
  <script src="./editInPlace.js"></script>
  <script>
  // 流程代码, 走向面向对象封装
  new EditInPlace(
    'ep1', 
    document.getElementById('app')
  );
  new EditInPlace(
    'ep2', 
    document.getElementById('app'),
    '好嗨哟'
  );
  </script>
</body>
</html>

因为我们第一个实例化时并没有输入任何东西,所以在<div id="ep1"></div>标签里应该输出的是这个家伙很懒,什么都没有留下 ,在<div id="ep2"></div>标签输出的是好嗨哟 ,而且span标签应该是div标签的子集 ,下面一起来看看结果吧

动态生成节点的优劣

动态生成节点好处

  • 增强用户体验:允许用户直接在页面上编辑内容,减少了用户的操作步骤,提高效率。
  • 易于扩展:基于面向对象的设计使得新增功能变得相对简单,只需继承或扩展现有类即可,开发者可以更好地专注于业务逻辑
  • 更好的代码组织:将相关功能封装在一个类中有利于保持代码整洁,便于后期维护。同时,良好的封装也促进了代码的复用性。
  • 适应性强:能够根据不同的输入参数灵活调整自身行为,适用于多种场景。

动态生成节点弊端

虽然本文着重讲的是如何创建及应用动态节点,但不可否认的是它仍然有弊端。频繁的创建和删除它可能会导致性能下降,而且复杂的动态生成逻辑会导致代码难以阅读和维护。由于动态生成节点需要执行js代码来创建和插入DOM元素,所以初始加载速度可能会稍慢一些。

小结

在实际开发中,我们应根据具体需求和应用场景选择合适的方法。对于静态内容较多且不经常变动的页面,推荐使用静态方式;而对于需要频繁更新或具有复杂交互性的区域,则应考虑使用动态生成节点。

相关推荐
CharlesYu018 小时前
前端性能优化的第一性原理,是不断缩短“用户发起意图 → 获得可用结果”之间的时间
前端
平头哥技术团队8 小时前
Day 21 _ 页内锚点_给每段起个 id,目录写 href=_#id_,点一下页面就滚到那一段
前端·html·html5
子兮曰9 小时前
Bun v1.4.1 深度解析:从 Zig 到 Rust,一场 11 天、64 个 AI 代理的语言迁徙
前端·后端·bun
人民广场吃泡面10 小时前
什么是AI Agent?它又能给前端带来哪些效率提升?
前端·人工智能
中科三方10 小时前
两家域名注册商资质被ICANN终止:企业域名资产安全再受关注
前端·网络·安全·域名
bug总结10 小时前
uniapp vue3全局方法注册使用
前端·javascript·uni-app
华无丽言11 小时前
如何在宜搭中实现获取子表中的字段值赋值到父表中?
前端·javascript·低代码
IT_陈寒11 小时前
Vue的computed属性竟然坑了我一把
前端·人工智能·后端
威斯软科的老司机11 小时前
通俗讲解 CNN 图像识别、向量 Embedding、Softmax 概率计算这三块的简化原理
前端·人工智能·ui·数字孪生
2601_9623824312 小时前
剑指大前端全栈工程师(全2册)主要情节
javascript·实战案例·全栈工程师·剑指大前端·html5+css3