jQuery:设置获取属性、遍历添加删除元素、尺寸、位置

'# jQuery:设置获取属性、遍历添加删除元素、尺寸、位置

一、背景与问题

在Web开发中,DOM操作是核心环节。jQuery作为早期的前端框架,通过封装DOM API提供了更简洁的操作方式。本文将深入探讨jQuery中属性操作、元素遍历、元素增删、尺寸位置计算等核心功能的实现原理和使用技巧。

二、基本原理

1. 属性操作机制

jQuery的.attr()和.prop()方法底层调用的是document.querySelectorAll()和document.getElementById(),通过DOM API实现属性获取和设置。其核心原理是:

// 简化版源码
jQuery.fn.attr = function(key, value) {
  return this.each(function() {
    if (arguments.length === 2) {
      this.setAttribute(key, value);
    } else {
      return this.getAttribute(key);
    }
  });
};

2. 元素遍历机制

jQuery的.each()和.filter()方法基于NodeList.prototype.forEach实现,通过遍历DOM节点树来操作元素。其核心特点包括:

  • 节点遍历顺序与DOM结构一致
  • 支持CSS选择器过滤
  • 可以访问节点的属性和方法

3. 尺寸位置计算

jQuery的.width()/.height()和.offset()方法内部调用的是getBoundingClientRect(),但做了重要改进:

// 简化版源码
jQuery.fn.offset = function() {
  const rect = this[0].getBoundingClientRect();
  return {
    top: rect.top + window.scrollY,
    left: rect.left + window.scrollX
  };
};

三、环境准备

<!-- 引入jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

四、核心实现

1. 属性设置与获取

// 示例1: 设置/获取属性
$('#myButton').attr('disabled', true); // 设置disabled属性
console.log($('#myButton').attr('disabled')); // 获取disabled属性

// 示例2: 属性与属性值的区别
$('#myInput').prop('checked', true); // 设置复选框状态
console.log($('#myInput').prop('checked')); // 获取复选框状态

关键代码解释:

  • attr()操作的是HTML属性,prop()操作的是DOM属性
  • 在事件处理中,应使用prop()获取状态
  • 对于动态生成的元素,attr()可能无法获取最新值

2. 元素遍历与增删

// 示例3: 遍历与过滤
$('#parent').find('li').filter(':even').addClass('highlight');

// 示例4: 动态添加元素
$('#container').append('<div>新元素</div>');

关键代码解释:

  • .find()使用CSS选择器进行子元素搜索
  • .filter()支持所有CSS选择器
  • .append()/.prepend()在DOM末尾/开头插入元素
  • 频繁增删元素会导致重排(reflow),需使用document.createDocumentFragment()优化

3. 尺寸与位置计算

// 示例5: 尺寸计算
const width = $('#box').width();
const height = $('#box').height();
console.log(`尺寸: ${width}x${height}`);

// 示例6: 位置计算
const position = $('#box').offset();
console.log(`位置: top=${position.top}, left=${position.left}`);

关键代码解释:

  • .width()/.height()返回视口内实际宽度/高度
  • .offset()返回相对于文档的绝对位置
  • .position()返回相对于最近定位祖先元素的相对位置
  • 在动画或布局计算时需考虑滚动位置

五、完整案例

待办事项管理系统

<!-- HTML结构 -->
<div id="app">
  <input type="text" id="taskInput" placeholder="输入任务">
  <button id="addBtn">添加</button>
  <ul id="taskList"></ul>
</div>

<!-- JavaScript逻辑 -->
<script>
  $(document).ready(function() {
    const $input = $('#taskInput');
    const $list = $('#taskList');
    
    $('#addBtn').click(function() {
      const taskText = $input.val().trim();
      if (taskText) {
        const $li = $('<li>').text(taskText);
        $list.append($li);
        $input.val('');
        
        // 添加删除按钮
        $('<button>').text('删除').click(function() {
          $li.remove();
        }).appendTo($li);
      }
    });
    
    // 动态计算尺寸
    function updateDimensions() {
      const $box = $('#app');
      const size = $box.width();
      const position = $box.offset();
      console.log(`尺寸: ${size}px, 位置: top=${position.top}px`);
    }
    
    // 初始计算
    updateDimensions();
    
    // 窗口大小变化时更新
    $(window).resize(updateDimensions);
  });
</script>

关键代码解释:

  • 使用.append()动态创建元素
  • 使用.text()安全插入内容
  • 使用.offset()进行位置计算
  • 使用.resize()事件处理窗口变化
  • 通过.width()获取容器尺寸

六、源码解析

以.attr()方法为例,其核心实现如下:

jQuery.fn.attr = function( name, value ) {
  var i, len, key, nodeName;

  if (arguments.length === 1) {
    nodeName = this[0] && this[0].nodeName;
    if (nodeName && nodeName !== 'SCRIPT' && !/^(select|textarea)/i.test(nodeName) && 
        !/^(xml|xmldom)/i.test(nodeName)) {
      return this[0].getAttribute(name);
    }
    return this.map(function() {
      return this.getAttribute && this.getAttribute(name);
    });
  }

  // 设置属性
  if (arguments.length === 2) {
    return this.each(function() {
      if (this.setAttribute) {
        this.setAttribute(name, value);
      }
    });
  }
};

关键点分析:

  • 区分不同元素类型处理
  • 处理SCRIPT标签的特殊性
  • 使用map()确保返回数组
  • 处理null和undefined值

七、进阶使用

1. 延迟执行优化

// 使用deferred对象
$.when($.get('data.json')).done(function(data) {
  $('#container').html(data);
});

2. 文档碎片优化

const frag = document.createDocumentFragment();
const $items = $('<div>').append(
  $('<p>').text('项目1'),
  $('<p>').text('项目2')
);
frag.appendChild($items[0]);
$('#container').append(frag);

3. 动态属性绑定

$('#dynamic').on('click', function() {
  $(this).attr('data-state', 'active');
});

八、性能与工程实践

1. 性能优化策略

  • 避免频繁DOM操作
  • 使用document.createDocumentFragment()
  • 避免使用eval()或innerHTML
  • 使用requestAnimationFrame处理动画

2. 安全风险防范

  • 使用.text()而非.html()插入内容
  • 对用户输入进行过滤和转义
  • 避免直接使用eval()执行动态代码
  • 使用encodeURIComponent()处理URL参数

3. 异常处理机制

try {
  $('#nonExistent').attr('nonExistent');
} catch (e) {
  console.error('属性获取失败:', e);
}

九、常见问题与踩坑

1. 常见错误示例

// 错误示例:使用attr获取动态属性
$('#dynamic').attr('data-state'); // 可能返回null

问题分析:

  • attr()获取的是HTML属性,不是当前状态
  • 对于动态变化的属性值,应使用prop()获取最新值

2. 常见陷阱

  • 遍历时修改数组导致索引错位
  • 使用attr()设置checked属性时的不一致性
  • 事件委托时选择器错误导致事件丢失

3. 解决方案

// 正确使用prop获取状态
$('#checkbox').prop('checked');

// 正确使用事件委托
$('#container').on('click', 'li', function() {
  // 处理逻辑
});

十、最佳实践

1. 推荐方案

  • 使用prop()获取状态属性
  • 使用data()方法存储数据
  • 使用find()/filter()进行精准选择
  • 使用offset()计算位置时考虑滚动位置
  • 使用on()进行事件委托

2. 使用建议

  • 在需要高性能的场景使用原生JS
  • 在复杂的DOM操作中使用jQuery
  • 在需要跨浏览器兼容的场景中使用jQuery
  • 在处理大量DOM节点时使用文档碎片

3. 优化建议

  • 将DOM操作集中处理
  • 使用$.Deferred处理异步操作
  • 使用$.each()替代for循环
  • 使用$.map()处理数组转换

十一、总结

jQuery的属性操作、元素遍历、尺寸位置计算等功能,是前端开发中不可或缺的工具。本文深入探讨了这些功能的实现原理、使用技巧和注意事项,通过多个代码示例展示了其在实际项目中的应用。在使用过程中,需要根据具体场景选择合适的方法,避免常见的性能陷阱和安全风险。对于现代前端开发,虽然原生JS和框架(如React/Vue)越来越流行,但理解jQuery的核心机制,仍然对掌握前端开发本质具有重要价值。在需要快速开发和跨浏览器兼容的场景中,jQuery仍然是一个值得信赖的工具。

最后修改于:2026年10月05日 07:16

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日