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

34、web前端开发之JavaScript(三)

十. DOM操作详解

1、DOM简介

文档对象模型(DOM,Document Object Model)是JavaScript与网页内容交互的接口。它将HTML文档表示为一种树状结构(DOM树),其中每个节点代表文档的一部分(例如元素、文本、注释等)。通过DOM,JavaScript可以动态地访问和操作网页的内容、样式和结构。

DOM的作用:

  • 动态修改网页内容(文本、图片等)。
  • 更改元素的样式(颜色、布局等)。
  • 添加或删除页面元素。
  • 响应用户事件(点击、悬停、输入等)。

DOM结构示例:

<html>  
<head>  <title>DOM示例</title>  
</head>  
<body>  <h1>标题</h1>  <p>这是一个段落。</p>  
</body>  
</html>  

DOM树结构如下:

- html  - head  - title  - body  - h1  - p  

2、 DOM节点

在DOM中,所有内容都被表示为节点。常见的节点类型包括:

  1. 元素节点

    • 对应HTML标签,如<div><p>等。

    • 例如:

      const div = document.querySelector('div'); // 获取一个<div>元素节点  
      
  2. 文本节点

    • 元素中的文本内容。

    • 例如:

      <p>这是一个段落。</p>  
      

      上述段落的文本节点是“这是一个段落。”。

  3. 属性节点

    • 元素的属性,如idclasshref等。

    • 例如:

      <a href="https://www.example.com">链接</a>  
      

      href是元素的属性节点。

  4. 注释节点

    • HTML注释内容。

    • 例如:

      <!-- 这是一个注释 -->  
      
  5. 文档节点

    • 整个文档的根节点。

    • 例如:

      const documentNode = document; // 获取文档节点  
      

3、 DOM操作方法

DOM提供了多种方法来操作节点和元素。以下是一些常用的操作方法:

1. 选择元素
  • document.getElementById(id)
    通过元素的id属性获取单个元素。

    <div id="container">内容</div>  
    
    const container = document.getElementById('container');  
    
  • document.querySelector(selector)
    根据CSS选择器获取第一个匹配的元素。

    <div class="box">内容</div>  
    
    const box = document.querySelector('.box'); // 选择class为"box"的元素  
    
  • document.querySelectorAll(selector)
    根据CSS选择器获取所有匹配的元素,返回一个NodeList集合。

    const boxes = document.querySelectorAll('.box');  
    boxes.forEach(box => {  console.log(box);  
    });  
    
2. 创建和添加元素
  • document.createElement(tagName)
    创建一个新的HTML元素。

    const newDiv = document.createElement('div');  
    newDiv.textContent = '这是一个新创建的div元素';  
    
  • element.appendChild(child)
    将一个节点添加到指定元素的末尾。

    const container = document.getElementById('container');  
    container.appendChild(newDiv);  
    
  • element.insertBefore(newNode, referenceNode)
    在指定的子节点前插入新的节点。

    const referenceNode = document.getElementById('reference');  
    container.insertBefore(newDiv, referenceNode);  
    
3. 删除元素
  • element.removeChild(child)
    删除指定元素的子节点。

    const container = document.getElementById('container');  
    container.removeChild(container.firstChild);  
    
  • element.remove()
    删除元素本身及其所有子节点。

    const elementToRemove = document.getElementById('remove');  
    elementToRemove.remove();  
    
4. 修改内容
  • element.textContent
    获取或设置元素的纯文本内容,不包含HTML标签。

    const paragraph = document.querySelector('p');  
    paragraph.textContent = '这是新的段落内容';  
    
  • element.innerHTML
    获取或设置元素的HTML内容,包括标签。

    const container = document.getElementById('container');  
    container.innerHTML = '<strong>这是<strong>新的<strong>内容</strong></strong>';  
    
5. 修改样式
  • element.style.property
    修改元素的内联样式属性。

    const box = document.querySelector('.box');  
    box.style.backgroundColor = 'blue';  
    box.style.width = '200px';  
    
  • element.classList
    添加、移除或切换类名。

    const box = document.querySelector('.box');  
    box.classList.add('active'); // 添加类  
    box.classList.remove('box'); // 移除类  
    box.classList.toggle('visible'); // 切换类  
    
  • element.style.cssText
    一次性修改多个样式属性。

    const box = document.querySelector('.box');  
    box.style.cssText = 'background-color: blue; width: 200px; height: 100px;';  
    
6. 属性操作
  • element.getAttribute(attributeName)
    获取元素的某个属性值。

    const link = document.querySelector('a');  
    const href = link.getAttribute('href');  
    console.log(href); // 输出链接地址  
    
  • element.setAttribute(attributeName, value)
    设置元素的某个属性值。

    const link = document.querySelector('a');  
    link.setAttribute('href', 'https://www.example.com');  
    
  • element.hasAttribute(attributeName)
    检查元素是否具有某个属性。

    const link = document.querySelector('a');  
    if (link.hasAttribute('href')) {  console.log('该链接具有href属性');  
    }  
    
  • element.removeAttribute(attributeName)
    删除元素的某个属性。

    const link = document.querySelector('a');  
    link.removeAttribute('href');  
    
7. 遍历节点
  • element.childNodes
    返回元素的所有子节点(包括元素节点、文本节点和注释节点)。

    const container = document.getElementById('container');  
    const childNodes = container.childNodes;  
    childNodes.forEach(node => {  console.log(node);  
    });  
    
  • element.children
    返回元素的所有子元素节点(只包括元素节点)。

    const container = document.getElementById('container');  
    const children = container.children;  
    children.forEach(child => {  console.log(child);  
    });  
    
  • element.firstChild 和 element.lastChild
    获取元素的第一个子节点或最后一个子节点。

    const container = document.getElementById('container');  
    const firstChild = container.firstChild;  
    const lastChild = container.lastChild;  
    
  • element.nextElementSibling 和 element.previousElementSibling
    获取元素的下一个兄弟元素节点或上一个兄弟元素节点。

    const element = document.querySelector('div');  
    const nextSibling = element.nextElementSibling;  
    const previousSibling = element.previousElementSibling;  
    
  • element.parentElement
    获取元素的父元素节点。

    onst element = document.querySelector('div');  
    const parent = element.parentElement;  
    

4、 DOM事件

1. 添加事件监听器
  • element.addEventListener(eventType, callback)
    添加事件监听器,监听特定事件类型。

    const button = document.querySelector('button');  
    button.addEventListener('click', function() {  console.log('按钮被点击了!');  
    });  
    
  • element.on[eventType]
    通过on属性添加事件监听器。

    const button = document.querySelector('button');  
    button.onclick = function() {  console.log('按钮被点击了!');  
    };  
    
2. 事件类型

常见的事件类型包括:

  • 鼠标事件
    • click:鼠标点击。
    • dblclick:鼠标双击。
    • mousedown:鼠标按下。
    • mouseup:鼠标释放。
    • mousemove:鼠标移动。
    • mouseover:鼠标悬停。
    • mouseout:鼠标移出。
  • 键盘事件
    • keydown:键盘按下。
    • keyup:键盘释放。
    • keypress:键盘按下并释放(已废弃)。
  • 表单事件
    • submit:表单提交。
    • reset:表单重置。
    • change:表单元素值改变。
    • input:输入字段内容变化。
  • 文档和窗口事件
    • load:页面加载完成。
    • unload:页面卸载。
    • resize:窗口大小调整。
    • scroll:页面滚动。
3. 事件对象

当事件发生时,事件监听器会接收到一个事件对象(event object),该对象包含事件相关的信息。

  • event.type:事件的类型。
  • event.target:触发事件的目标元素。
  • event.currentTarget:事件的当前目标(考虑事件代理)。
  • event.preventDefault():阻止事件的默认行为。
  • event.stopPropagation():停止事件的冒泡传播。
const link = document.querySelector('a');  
link.addEventListener('click', function(event) {  event.preventDefault(); // 阻止链接跳转  console.log('点击了链接:', event.target.getAttribute('href'));  
});  

5、添加和删除元素

1. 创建元素
// 创建一个新的<div>元素  
const newDiv = document.createElement('div');  
newDiv.textContent = '这是一个新创建的div元素';  
newDiv.style.backgroundColor = 'lightblue';  
newDiv.style.padding = '10px';  
2. 添加元素
// 获取容器元素  
const container = document.getElementById('container');  
// 将新创建的div元素添加到容器中  
container.appendChild(newDiv);  
3. 删除元素
// 获取要删除的元素  
const elementToRemove = document.getElementById('remove');  
// 删除该元素  
elementToRemove.remove();  

6、样式操作

1. 修改内联样式
const box = document.querySelector('.box');  
box.style.width = '300px';  
box.style.height = '200px';  
box.style.backgroundColor = 'lightblue';  
2. 切换类名
const box = document.querySelector('.box');  
box.classList.add('active'); // 添加类  
box.classList.remove('box'); // 移除类  
box.classList.toggle('visible'); // 切换类  
3. 动态修改样式表
const styleSheet = document.createElement('style');  
styleSheet.textContent = `  .box {  background-color: yellow;  }  .box.active {  background-color: green;  }  
`;  
document.head.appendChild(styleSheet);  

7、 示例:动态更新网页内容

以下是一个综合示例,展示了如何通过DOM操作动态修改网页内容。

<!DOCTYPE html>  
<html>  
<head>  <title>DOM操作示例</title>  <style>  .container {  width: 80%;  margin: 0 auto;  padding: 20px;  }  .box {  border: 1px solid #ccc;  padding: 10px;  margin: 10px 0;  }  .box.active {  background-color: lightblue;  }  </style>  
</head>  
<body>  <div class="container">  <h1 id="title">DOM操作示例</h1>  <button onclick="addNewBox()">添加新框</button>  <div id="content"></div>  </div>  <script>  function addNewBox() {  // 创建一个新的<div>元素  const newBox = document.createElement('div');  newBox.className = 'box';  newBox.textContent = `这是第${getBoxCount()}个新增的框`;  // 获取容器元素  const container = document.getElementById('content');  // 将新元素添加到容器中  container.appendChild(newBox);  // 更新标题  const title = document.getElementById('title');  title.textContent = `DOM操作示例(共${getBoxCount()}个框)`;  // 为新添加的框添加点击事件  newBox.addEventListener('click', function() {  this.classList.toggle('active');  console.log('点击了第', this.textContent, '个框');  });  }  function getBoxCount() {  const container = document.getElementById('content');  return container.children.length;  }  </script>  
</body>  
</html>  
示例功能:
  1. 点击“添加新框”按钮时,会动态创建一个新的<div>元素,并添加到页面中。
  2. 新增的<div>元素会显示其序号(例如:“这是第1个新增的框”)。
  3. 点击每个<div>框时,会切换其“active”类名,改变背景颜色。
  4. 标题会动态更新,显示当前页面中新增的框的数量。

8、总结

DOM操作是JavaScript与网页内容交互的核心。通过DOM,我们可以动态地添加、删除和修改页面元素、样式和内容,同时可以响应用户事件。掌握DOM操作方法(如选择元素、创建节点、修改样式和属性等)是前端开发的基础技能。随着对DOM的深入理解和实践,开发者可以创建更动态、交互性更强的Web页面。

十一、JavaScript事件处理详解

JavaScript的事件处理是前端开发的核心部分之一。事件是用户与网页交互的方式,例如点击按钮、输入文本、滚动页面等。通过事件处理,我们可以响应这些交互,并执行相应的操作。本节将详细讲解JavaScript事件处理的各个方面。


1. 事件的基本概念

1.1 什么是事件?

事件是指用户与网页之间发生的某种互动行为,例如:

  • 鼠标事件:点击(click)、双击(dblclick)、悬停(mouseover)等。
  • 键盘事件:按下键(keydown)、释放键(keyup)等。
  • 表单事件:提交表单(submit)、改变内容(change)等。
  • 文档事件:加载完成(load)、卸载(unload)等。
1.2 事件驱动模型

JavaScript是事件驱动的语言。事件驱动模型的核心思想是:当某个事件发生时,执行特定的代码。

示例:

<button onclick="alert('按钮被点击了!')">点击我</button>  
1.3 事件的三个阶段

事件在传播过程中会经历三个阶段:

  1. 捕获阶段(Capturing Phase):事件从document开始,向目标元素的祖先节点传播。
  2. 目标阶段(Target Phase):事件到达目标元素。
  3. 冒泡阶段(Bubbling Phase):事件从目标元素向上传播,回到document

2. 事件处理方法

2.1 内联事件处理

通过HTML标签的on-属性直接定义事件处理函数。

示例:

<button onclick="alert('按钮被点击了!')">点击我</button>  

缺点:

  • 嵌入HTML中,代码不易维护。
  • 只能绑定一个事件处理函数。
2.2 传统事件绑定方法

通过JavaScript方法绑定事件处理函数。

语法:

element.addEventListener(eventType, callback[, useCapture])  
  • eventType:事件类型(如'click')。
  • callback:事件处理函数。
  • useCapture:布尔值,表示是否在捕获阶段触发事件(默认为false,即冒泡阶段)。

示例:

const button = document.querySelector('button');  
button.addEventListener('click', function() {  console.log('按钮被点击了!');  
});  
2.3 事件处理的不同写法
  • DOM Level 0(传统方式)

    button.onclick = function() {  console.log('按钮被点击了!');  
    };  
    
  • DOM Level 2(推荐方式)

    button.addEventListener('click', function() {  console.log('按钮被点击了!');  
    }, false);  
    
  • 箭头函数

    button.addEventListener('click', () => {  console.log('按钮被点击了!');  
    });  
    

3. 常见的事件类型

3.1 鼠标事件
事件类型描述示例
click鼠标点击元素<button onclick="alert('点击了!')">
dblclick鼠标双击元素
mousedown鼠标按下
mouseup鼠标释放
mousemove鼠标移动
mouseover鼠标悬停在元素上
mouseout鼠标离开元素
3.2 键盘事件
事件类型描述示例
keydown键盘按下
keyup键盘释放
keypress键盘按下并释放(已废弃)
3.3 表单事件
事件类型描述示例
submit表单提交<form onsubmit="alert('表单提交!')">
reset表单重置
change表单元素值改变
input输入字段内容变化
3.4 文档和窗口事件
事件类型描述示例
load页面加载完成<body onload="alert('页面加载完成!')">
unload页面卸载
resize窗口大小调整
scroll页面滚动
3.5 其他事件
事件类型描述示例
focus元素获取焦点
blur元素失去焦点
contextmenu右键点击

4. 事件对象

当事件发生时,事件处理函数会接收到一个event对象,该对象包含了事件相关的信息。

4.1 常见的事件对象属性和方法
属性/方法描述示例用法
type事件类型console.log(event.type);
target事件的目标元素console.log(event.target);
currentTarget事件的当前目标元素console.log(event.currentTarget);
preventDefault()阻止事件的默认行为event.preventDefault();
stopPropagation()停止事件的进一步传播event.stopPropagation();
stopImmediatePropagation()立即停止事件的传播event.stopImmediatePropagation();

示例:

document.querySelector('a').addEventListener('click', function(event) {  event.preventDefault(); // 阻止链接跳转  console.log('点击了链接:', event.target.getAttribute('href'));  
});  

5. 事件流(Event Propagation)

5.1 事件流的三个阶段
  1. 捕获阶段(Capturing Phase)
    • 事件从document开始,向目标元素的祖先节点传播。
  2. 目标阶段(Target Phase)
    • 事件到达目标元素。
  3. 冒泡阶段(Bubbling Phase)
    • 事件从目标元素向上传播,回到document
5.2 控制事件传播
  • event.stopPropagation():防止事件在DOM树中继续传播。
  • event.stopImmediatePropagation():立即停止事件的传播,并阻止其他事件处理函数执行。

示例:

<div id="container">  <button>点击我</button>  
</div>  
<script>
const container = document.getElementById('container');  
const button = document.querySelector('button');  button.addEventListener('click', function(event) {  console.log('按钮的click事件触发');  event.stopPropagation(); // 防止事件冒泡到container  
});  container.addEventListener('click', function(event) {  console.log('container的click事件触发');  
}); 
</script>

6. 事件委托(Event Delegation)

6.1 什么是事件委托?

事件委托是一种通过将事件监听器绑定到父元素,而不是每个子元素来提高效率的技术。其核心思想是利用事件冒泡的特性。

6.2 事件委托的好处
  • 减少事件监听器的数量:只绑定一次事件监听器,即可处理多个子元素的事件。
  • 提升性能:减少内存的占用,尤其是在处理大量动态元素时。
  • 方便管理:便于动态添加或删除子元素, 无需频繁添加或移除事件监听器。
6.3 示例:通过事件委托实现动态添加的子元素也能响应事件
<ul id="list">  <li>Item 1</li>  <li>Item 2</li>  <li>Item 3</li>  
</ul>  
<script>
const list = document.getElementById('list');  list.addEventListener('click', function(event) {  if (event.target.tagName === 'LI') {  console.log('点击了列表项:', event.target.textContent);  // 可以执行其他操作,例如删除该列表项  event.target.remove();  }  
});  // 动态添加新列表项  
const newItem = document.createElement('li');  
newItem.textContent = 'Item 4';  
list.appendChild(newItem);  
</script>

7. 自定义事件(Custom Events)

7.1 什么是自定义事件?

自定义事件是开发者创建的、不属于原生事件的事件类型。通过自定义事件,可以实现更复杂的应用逻辑。

7.2 创建和触发自定义事件
  • new CustomEvent(type[, options])
    • type:事件类型(字符串)。
    • options:可选参数,包括detail属性,可以附带自定义数据。
  • dispatchEvent(event)
    • 触发自定义事件。

示例:

// 创建自定义事件  
const customEvent = new CustomEvent('userLogin', {  detail: {  username: 'Alice',  loginTime: new Date()  }  
});  // 绑定事件监听器  
document.addEventListener('userLogin', function(event) {  console.log('用户登录事件触发:', event.detail);  
});  // 触发自定义事件  
document.dispatchEvent(customEvent);  

8. 跨浏览器兼容性问题

8.1 事件绑定方法
  • IE8及以下版本:使用attachEvent()方法。
  • 现代浏览器:使用addEventListener()方法。

示例:

function addEvent(element, eventType, callback) {  if (element.addEventListener) {  element.addEventListener(eventType, callback, false);  } else {  element.attachEvent('on' + eventType, callback);  }  
}  
8.2 事件对象的差异
  • 现代浏览器:事件目标是event.target
  • IE8及以下版本:事件目标是event.srcElement

示例:

function getEventTarget(event) {  return event.target || event.srcElement;  
}  

9. 实际应用场景

9.1 表单验证
const form = document.getElementById('myForm');  
const usernameInput = document.getElementById('username');  usernameInput.addEventListener('input', function(event) {  const value = this.value;  if (value.length < 6) {  console.log('用户名长度必须至少为6个字符!');  this.style.backgroundColor = 'pink';  } else {  this.style.backgroundColor = 'white';  }  
});  form.addEventListener('submit', function(event) {  event.preventDefault();  const username = usernameInput.value.trim();  if (username === '') {  alert('请输入用户名!');  return;  }  // 提交表单  console.log('表单提交:', username);  
});  
9.2 无限加载(Infinite Scroll)
const container = document.getElementById('container');  
const threshold = 100; // 距离底部的阈值(像素)  window.addEventListener('scroll', function(event) {  const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;  const windowHeight = document.documentElement.clientHeight || document.body.clientHeight;  const contentHeight = container.offsetHeight;  if (contentHeight - (scrollTop + windowHeight) < threshold) {  // 加载更多内容  console.log('加载更多内容...');  // Simulate loading data  setTimeout(function() {  const newItem = document.createElement('div');  newItem.textContent = `加载项${Math.random()}`;  container.appendChild(newItem);  }, 1000);  }  
});  

10. 总结

JavaScript事件处理是实现交互式Web页面的核心技术。通过事件处理,我们可以响应用户的行为,动态更新页面内容,并实现复杂的交互逻辑。掌握事件的基础知识(如事件类型、事件对象、事件流、事件委托等)是前端开发的基础技能。在实际开发中,结合事件处理和DOM操作,可以创建出更动态、更用户友好的Web应用程序。

十二. 异步编程与Promise详解

JavaScript中的异步编程是处理I/O操作(如网络请求、定时器等)的一种方式,避免了阻塞主线程,提升用户体验。本节将详细介绍回调函数、Promise、async/await以及AJAX与Fetch API的使用。


1、回调函数(Callback Functions)

回调函数是一种将函数作为参数传递给另一个函数,并在某些操作完成后由另一个函数调用(“回调”)的技术。它是JavaScript中最早用于处理异步操作的方式。

1.1 回调函数的基本用法
setTimeout(function() {  console.log('3秒后执行');  
}, 3000);  
  • setTimeout是接受一个回调函数和时间参数的函数。
  • 当设定的时间过去后,JavaScript引擎会执行回调函数。
1.2 回调函数的缺点
  • 嵌套地狱:多个异步操作需要嵌套使用多个回调函数,导致代码难以阅读和维护。

    setTimeout(function() {  console.log('3秒后执行');  setTimeout(function() {  console.log('再3秒后执行');  setTimeout(function() {  console.log('再再3秒后执行');  }, 3000);  }, 3000);  
    }, 3000);  
    
  • 错误处理困难:在嵌套多层回调时,处理错误和异常变得复杂,容易导致memory leak或其他问题。


2、 Promise

Promise是ES6引入的用于处理异步操作的新方式。它通过封装异步操作的结果,使得代码更易于编写和维护。

2.1 Promise的基本概念

Promise代表一个未来才会知道结果的值。它有三种状态:

  1. Pending(等待):初始状态,既没有成功也没有失败。
  2. Fulfilled(已完成):操作成功,resolve函数被调用。
  3. Rejected(已失败):操作失败,reject函数被调用。
2.2 创建和使用Promise

创建Promise:

const promise = new Promise(function(resolve, reject) {  // 异步操作  if (/* 判断是否成功 */ ) {  resolve(/* 成功的结果 */);  } else {  reject(/* 失败的原因 */);  }  
});  

使用Promise:

promise.then(function(result) {  console.log('成功处理:', result);  
}).catch(function(error) {  console.error('处理失败:', error);  
});  
2.3 Promise的链式操作

Promise允许使用.then().catch()进行链式调用,简化异步流程的处理。

fetch('https://api.example.com/data')  .then(response => response.json())  .then(data => console.log('获取的数据:', data))  .catch(error => console.error('获取数据失败:', error));  
2.4 Promise.all() 和 Promise.race()
  • Promise.all(iterable)
    等待所有Promise都完成,返回一个新的Promise。

    const promises = [  new Promise(resolve => setTimeout(resolve, 2000, '任务1完成')),  new Promise(resolve => setTimeout(resolve, 3000, '任务2完成'))  
    ];  Promise.all(promises).then(results => {  console.log('所有任务完成:', results);  
    });  
    
  • Promise.race(iterable)
    等待第一个完成的Promise,返回其结果。

    const promises = [  new Promise(resolve => setTimeout(resolve, 2000, '任务1完成')),  new Promise(resolve => setTimeout(resolve, 3000, '任务2完成'))  
    ];  Promise.race(promises).then(result => {  console.log('第一个完成的任务:', result);  
    });  
    

3、 Async/await

async/await是ES2017引入的语法糖,用于简化Promise的使用。它通过将异步代码写法转换为类似同步代码的方式,提升代码的可读性。

3.1 async函数的基本用法
async function DelayedLog() {  try {  const result = await new Promise(resolve => setTimeout(resolve, 2000, '完成'));  console.log(result);  } catch (error) {  console.error('发生错误:', error);  }  
}  
DelayedLog();  
  • async关键字:用于声明一个异步函数。
  • await关键字:用于等待Promise的完成,并暂停函数的执行,直到Promise返回结果。
  • try…catch块:用于处理异步操作中的错误。
3.2 在Promise链中使用async/await
async function processData() {  try {  const response = await fetch('https://api.example.com/data');  const data = await response.json();  console.log('处理的数据:', data);  } catch (error) {  console.error('处理数据失败:', error);  }  
}  
processData();  
3.3 处理多个异步操作
  • 顺序执行

    async function sequentialTasks() {  const task1 = await new Promise(resolve => setTimeout(resolve, 2000, '任务1完成'));  const task2 = await new Promise(resolve => setTimeout(resolve, 3000, '任务2完成'));  console.log('所有任务完成:', [task1, task2]);  
    }  
    sequentialTasks();  
    
  • 并行执行

    async function parallelTasks() {  const promises = [  new Promise(resolve => setTimeout(resolve, 2000, '任务1完成')),  new Promise(resolve => setTimeout(resolve, 3000, '任务2完成'))  ];  const results = await Promise.all(promises);  console.log('所有任务完成:', results);  
    }  
    parallelTasks();  
    

4、 AJAX与Fetch API

AJAX(Asynchronous JavaScript and XML)是一种在网页加载后,向服务器请求数据并更新网页内容的技术。Fetch API是现代浏览器中用于发送HTTP请求的标准API。

4.1 Fetch API的基本用法
fetch('https://api.example.com/data')  .then(response => {  console.log('响应对象:', response);  return response.json(); // 解析响应为JSON格式  })  .then(data => {  console.log('获取的数据:', data);  })  .catch(error => {  console.error('获取数据失败:', error);  });  
4.2 使用async/await调用Fetch API
async function fetchData() {  try {  const response = await fetch('https://api.example.com/data');  if (!response.ok) {  throw new Error('HTTP错误,状态码:' + response.status);  }  const data = await response.json();  console.log('获取的数据:', data);  } catch (error) {  console.error('获取数据失败:', error);  }  
}  
fetchData();  
4.3 发送POST请求
async function sendData(data) {  try {  const response = await fetch('https://api.example.com/submit', {  method: 'POST',  headers: {  'Content-Type': 'application/json',  },  body: JSON.stringify(data)  });  const result = await response.json();  console.log('提交数据结果:', result);  } catch (error) {  console.error('提交数据失败:', error);  }  
}  
sendData({ name: 'Alice', age: 30 });  

5、 总结

JavaScript中的异步编程通过回调函数、Promise、async/await以及Fetch API等技术,实现了高效的非阻塞I/O操作处理。Promise和async/await进一步简化了异步代码的编写,提升了代码的可读性和维护性。在实际应用中,掌握这些技术可以帮助开发者更高效地处理复杂的异步逻辑,提升Web应用的响应速度和用户体验。

相关文章:

34、web前端开发之JavaScript(三)

十. DOM操作详解 1、DOM简介 文档对象模型&#xff08;DOM&#xff0c;Document Object Model&#xff09;是JavaScript与网页内容交互的接口。它将HTML文档表示为一种树状结构&#xff08;DOM树&#xff09;&#xff0c;其中每个节点代表文档的一部分&#xff08;例如元素、…...

自适应卡尔曼滤波

目录 自适应卡尔曼滤波 自适应卡尔曼滤波 主要作用,去抖动 AdaptiveKalmanFilter.py import cv2 import numpy as np from collections import deque# ------------------ 核心去抖算法 ------------------ import cv2 import numpy as np from collections import deque#…...

EIP-712:类型化结构化数据的哈希与签名

1. 引言 以太坊 EIP-712: 类型化结构化数据的哈希与签名&#xff0c;是一种用于对类型化结构化数据&#xff08;而不仅仅是字节串&#xff09;进行哈希和签名 的标准。 其包括&#xff1a; 编码函数正确性的理论框架&#xff0c;类似于 Solidity 结构体并兼容的结构化数据规…...

Day 3:Leetcode 比特位计数+只出现一次的数字 II

比特位计数 本质是一个递推&#xff0c;时间复杂度O(n)&#xff0c;空间复杂度O(n)。 class Solution { public:vector<int> countBits(int n) {vector<int> ans(n 1);ans[0] 0;//ans[1] 1;for(int i 1; i < n; i){if(i & 1){ans[i] ans[i/2] 1;}else…...

CentOS7安装conda

root用户登录虚拟机后更新yum yum update 下载Miniconda&#xff0c;路径就在/root下 wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh conda分为Miniconda和Anaconda, Miniconda是Conda的轻量级版本&#xff0c;只包含conda和Python&#xf…...

[Linux]从零开始的vs code交叉调试arm Linux程序教程

一、前言 最近的项目中需要集成rknn的视觉识别&#xff0c;在这之前我并且没有将rknn集成到自己项目的经验。这里我需要在rknn原本demo的基础上我还需要集成自己的业务代码。但是又有一个问题&#xff0c;原本rknn我们都是使用交叉编译编译到开发板上的&#xff0c;并且我们还要…...

【顶刊级科研绘图】AI支持下Nature级数据可视化(如何画图、如何标注、如何改图、如何美化、如何组合、如何排序)

技术点目录 第一章、绘图原则与概念&#xff1a;规范清晰简洁自明第二章、DeepSeek、ChatGPT、R绘图系统&#xff1a;八仙过海各显神通第三章、美学设计与细节&#xff1a;完美图表华丽呈现第四章、数据类型与图表&#xff1a;宝典在手各个击破第五章、统计分析与可视化&#x…...

CSRF跨站请求伪造——入门篇【DVWA靶场low级别writeup】

CSRF跨站请求伪造——入门篇 0. 前言1. 什么是CSRF2. 一次完整的CSRF攻击 0. 前言 本文将带你实现一次完整的CSRF攻击&#xff0c;内容较为基础。需要你掌握的基础知识有&#xff1a; 了解cookie&#xff1b;已经安装了DVWA的靶场环境&#xff08;本地的或云的&#xff09;&am…...

Spring Boot应用中实现Jar包热更新的实践指南

Spring Boot应用中实现Jar包热更新的实践指南 一、引言 在现代软件开发中&#xff0c;快速迭代和持续交付是至关重要的。对于基于Spring Boot的应用程序&#xff0c;一旦部署到生产环境&#xff0c;传统的更新方式通常是重新打包并重启应用&#xff0c;这不仅耗时&#xff0c…...

JVM深入原理(七)(一):运行时数据区

目录 7. JVM运行时数据区 7.1. 运行时数据区-总览 7.2. 运行时数据区-查看内存对象 7.3. 运行时数据区-程序计数器 7.3.1. 程序计数器-作用 7.3.2. 字节码指令执行流程 7.4. 运行时数据区-Java虚拟机栈 7.4.1. 栈-概述 7.4.2. 栈帧-组成 7.4.2.1. 栈帧-帧数据 7.4.2…...

约瑟夫环的四种(数组,链表,递归,迭代)解决方案,与空间、时间复杂度分析

以下方法均没有考虑结果集的空间与时间复杂度 1.数组解法 实现代码&#xff08;未优化&#xff09; class Main {public static void main(String[] args){Scanner read new Scanner(System.in);int n read.nextInt();int m read.nextInt();int[] people new int[n]; //…...

skynet.start 的作用详细解析

目录 skynet.start 的作用详细解析1. 功能概述2. 基本用法3. 关键作用(1) 注册消息处理函数(2) 启动事件循环(3) 服务生命周期管理 4. 与其他函数的协作5. 未调用 skynet.start 的后果6. 高级场景&#xff1a;何时不需要 skynet.start7. 总结 skynet.start 的作用详细解析 在 …...

Apache Doris 2025 Roadmap:构建 GenAI 时代实时高效统一的数据底座

在全球 290 位开发者的协作下&#xff0c;Apache Doris 在 2024 年完成了 7000 次代码提交&#xff0c;并发布了 22 个版本&#xff0c;实现在实时分析、湖仓一体和半结构化数据分析等核心场景的技术突破及创新。 2025 年&#xff0c;Apache Doris 社区将秉承“以场景驱动创新…...

springboot+easyexcel实现下载excels模板下拉选择

定义下拉注解 Target(ElementType.FIELD) Retention(RetentionPolicy.RUNTIME) public interface ExcelDropDown {/*** 固定下拉选项*/String[] source() default {};/*** 动态数据源key&#xff08;从上下文中获取&#xff09;*/String sourceMethod() default "";…...

vue3+ts+element-plus 开发一个页面模块的详细过程

目录、文件名均使用kebab-case&#xff08;短横线分隔式&#xff09;命名规范 子组件目录&#xff1a;./progress-ctrl/comps 1、新建页面文件 progress-ctrl.vue <script setup lang"ts" name"progress-ctrl"></script><template>&l…...

软考《信息系统运行管理员》- 7.1 物联网运维

物联网的概念及特征 物联网是在计算机互联网的基础上&#xff0c;通过射频识别 (RFID) 、 无线传感器、红外感应器、 全球定位系统、激光扫描器等信息传感设备&#xff0c;按约定的协议&#xff0c;把物与物之间通过网络连接起来&#xff0c; 进行信息交换和通信&#xff0c;以…...

【GPT入门】第33 课 一文吃透 LangChain:chain 结合 with_fallbacks ([]) 的实战指南

[TOC](【GPT入门】第33课 一文吃透 LangChain&#xff1a;chain 结合 with_fallbacks ([]) 的实战指南) 1. fallback概述 模型回退&#xff0c;可以设置在llm上&#xff0c;也可以设置在chain上&#xff0c;都带有with_fallbacks([])函数 2. llm的回退 2.1 代码 核心代码&…...

裴蜀定理:整数解的奥秘

裴蜀定理&#xff1a;整数解的奥秘 在数学的世界里&#xff0c;裴蜀定理&#xff08;Bzout’s Theorem&#xff09;是数论中一个非常重要的定理&#xff0c;它揭示了二次方程和整数解之间的关系。它不仅仅是纯粹的理论知识&#xff0c;还在计算机科学、密码学、算法优化等多个…...

Table as Thought论文精读

标题&#xff1a;Table as Thought: Exploring Structured Thoughts in LLM Reasoning 作者&#xff1a;Zhenjie Sun, Naihao Deng, Haofei Yu, Jiaxuan You 单位&#xff1a;University of Illinois Urbana-Champaign, University of Michigan 摘要&#xff1a; llm的推理…...

PyQt6实例_A股日数据维护工具_使用

目录 前置&#xff1a; 下载预备更新的数据 使用工具更新 用工具下载未复权、前复权、权息数据 在PostgreSQL添加两个数据表 工具&视频 前置&#xff1a; 1 本系列将以 “PyQt6实例_A股日数据维护工具” 开头放置在“PyQt6实例”专栏 2 日数据可在“数据库”专栏&…...

MySQL客户端工具-图形化工具-DataGrip 安装与使用

一. 常见的图形化工具 二. DataGrip 安装 官网&#xff1a;DataGrip&#xff1a;由 JetBrains 开发的数据库和 SQL 跨平台 IDE 二. DataGrip 使用...

企业管理系统的功能架构设计与实现

一、企业管理系统的核心功能模块 企业管理系统作为现代企业的中枢神经系统&#xff0c;涵盖了多个核心功能模块&#xff0c;以确保企业运营的顺畅与高效。这些功能模块通常包括&#xff1a; 人力资源管理模块&#xff1a;负责员工信息的录入、维护、查询及统计分析&#xff0c…...

1.Qt信号与槽

本篇主要介绍信号和槽&#xff0c;如何关联信号和槽以及用QPixmap在窗口中自适应显示图片 本文部分ppt、视频截图原链接&#xff1a;[萌马工作室的个人空间-萌马工作室个人主页-哔哩哔哩视频] 1. 信号 一般不需要主动发送信号&#xff0c;只有自定义的一些控件才需要做信号的…...

再生认证体系有哪些?不同标准对应的要求及可以做的审核机构

再生认证体系 标准 GRS再生回收认证要求 再生原材料的上游企业&#xff1a;需要具备GRS认证证书&#xff0c;以确保原材料的可追溯性和再生成分。 认证条件&#xff1a; 最终商品的再生成分比例必须至少为20%。 只有由至少50%的回收材料制成的产品才能贴上GRS标签。 认证机构…...

[CISSP] [6] 密码学和对称密钥算法

密码学的目标 1. 机密性&#xff08;Confidentiality&#xff09; 目标&#xff1a;保护信息不被未授权访问。 通过 加密&#xff08;Encryption&#xff09;技术确保数据只能被授权方解密和读取。主要方法&#xff1a; 对称加密&#xff08;AES、3DES&#xff09;&#xff…...

thinkphp每条一级栏目中可自定义添加多条二级栏目,每条二级栏目包含多个字段信息

小程序客户端需要展示团购详情这种结构的内容,后台会新增多条套餐,每条套餐可以新增多条菜品信息,每条菜品信息包含菜品名称,价格,份数等字段信息,类似于购物网的商品多规格属性,数据表中以json类型存储,手写了一个后台添加和编辑的demo 添加页面 编辑页面(json数据…...

混杂模式(Promiscuous Mode)与 Trunk 端口的区别详解

一、混杂模式&#xff08;Promiscuous Mode&#xff09; 1. 定义与工作原理 定义&#xff1a;混杂模式是网络接口的一种工作模式&#xff0c;允许接口接收通过其物理链路的所有数据包&#xff0c;而不仅是目标地址为本机的数据包。工作层级&#xff1a;OSI 数据链路层&#x…...

Spring Boot项目信创国产化适配指南

将 Spring Boot 项目适配信创国产化环境&#xff0c;需要从底层基础设施到上层应用组件进行全面替换和调整。以下是主要替换点和适配步骤的总结&#xff1a; 一、基础软件替换 1. JDK 替换 国外JDK&#xff1a;Oracle JDK、OpenJDK国产JDK&#xff1a; 阿里龙井&#xff08;D…...

MySQL:数据类型

数值类型 数值类型用于存储整数、小数、浮点数等&#xff0c;主要分为整数类型和浮点类型。 整数类型 数据类型存储大小取值范围&#xff08;有符号&#xff09;取值范围&#xff08;无符号&#xff09;说明TINYINT1字节-128 ~ 1270 ~ 255小整数&#xff0c;如布尔值&#x…...

maven引入项目内本地包方法

最近在写java实现excel转pdf功能&#xff1b; 网上有个包很好用&#xff0c;免费&#xff1a;spire.xls.free-5.3.0.jar。 但是maven打包项目时报错&#xff0c;找不到这个包。 jar包位置如下&#xff1a; 在项目/src/jar/spire.xls.free-5.3.0.jar。 解决方法&#xff1a…...

ARP协议

ARP协议 ARP协议的作用 当网络设备有数据要发送给另一台网络设备时&#xff0c;必须要知道对方的网络层地址&#xff08;即IP地址&#xff09;。IP地址由网络层来提供&#xff0c;但是仅有IP地址是不够的&#xff0c;IP数据报文必须封装成帧才能通过数据链路进行发送。数据帧…...

科技赋能安居梦:中建海龙以模块化革新重塑城市更新范式

在北京市西城区桦皮厂胡同&#xff0c;一栋始建于上世纪70年代的住宅楼正经历着一场脱胎换骨的蜕变。这座曾被鉴定为D级危房的建筑&#xff0c;在中建海龙科技有限公司&#xff08;以下简称“中建海龙”&#xff09;的匠心打造下&#xff0c;仅用三个月便完成"原拆原建&qu…...

2025 AI智能数字农业研讨会在苏州启幕,科技助农与数据兴业成焦点

4月2日&#xff0c;以"科技助农数据兴业”为主题的2025AI智能数字农业研讨会在苏州国际博览中心盛大启幕。本次盛会吸引了来自全国各地相关部门领导、知名专家学者、行业协会组织&#xff0c;以及县级市农业企业代表、县级市农产品销售商等万名嘉宾齐聚姑苏城&#xff0c;…...

2000-2021年 全国各地区城镇登记失业率数据

全国各地区城镇登记失业率数据2000-2021年.ziphttps://download.csdn.net/download/2401_84585615/90259723 https://download.csdn.net/download/2401_84585615/90259723 城镇登记失业率是衡量地区就业状况的重要指标&#xff0c;反映了在一定时期内&#xff0c;符合就业条件的…...

Cursor的主要好处

以下是Cursor的主要好处&#xff1a; 代码生成与优化 • 快速生成代码&#xff1a;根据简短描述或部分代码片段&#xff0c;Cursor能快速生成完整代码模块&#xff0c;还能智能预测下一步操作&#xff0c;将光标放在合适位置&#xff0c;让开发者一路Tab键顺滑编写代码。 • …...

超便捷语音转文字工具CapsWriter-Offline本地部署与远程使用全流程

文章目录 前言1. 软件与模型下载2. 本地使用测试3. 异地远程使用3.1 内网穿透工具下载安装3.2 配置公网地址3.3 修改config文件3.4 异地远程访问服务端 4. 配置固定公网地址4.1 修改config文件 5. 固定tcp公网地址远程访问服务端 前言 今天给大家安利一个绝对能让你工作效率飙…...

什么是数据仓库

什么是数据仓库 Data warehouse 是面向主题的 主要根据各种数据来源&#xff0c;来进行历史分析 形成一个趋势分析 为数据挖掘、预测建模、机器学习提供基础数据 与传统数据库比如gaussdb的区别。数据仓库注重历史数据分析&#xff0c;guassdb注重实时事务处理 数据仓库时企业的…...

【动态规划】二分优化最长上升子序列

最长上升子序列 II 题解 题目传送门&#xff1a;AcWing 896. 最长上升子序列 II 一、题目描述 给定一个长度为 N 的数列&#xff0c;求数值严格单调递增的子序列的长度最长是多少。 输入格式&#xff1a; 第一行包含整数 N第二行包含 N 个整数&#xff0c;表示完整序列 输…...

MySQL的安装与初始化流程

MySQL概述 MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB公司开发&#xff0c;MySQL AB公司被Sun公司收购&#xff0c;Sun公司又被Oracle公司收购&#xff0c;目前属于Oracle公司。 MySQL是目前最流行的关系型数据库管理系统&#xff0c;在WEB应用方面MySQL是最…...

flink standalone集群模式部署

一. 环境准备 1、下载并安装jdk11 2、下载flink 并解压 3、确保服务器之间的免密登录 二、集群搭建 搭建集群至少有三台机器&#xff0c;每台机器的分配角色如下 master: jobManager salve01&#xff1a;taskManager salve02&#xff1a;taskManager 1、在JobManager(…...

Linux线程概念与控制:【线程概念(页表)】【Linux线程控制】【线程ID及进程地址空间布局】【线程封装】

目录 一. 线程概念 1.1什么是线程 1.2分页式存储管理 1.2.1虚拟地址和页表的由来 1.2.2物理内存管理 1.2.3页表 1.2.4页目录结构 1.2.5二级页表地址转换 1.3线程的优点 二.进程VS线程 三.Linux线程控制 3.1POSIX线程库 3.2创建线程 ​编辑 pthread库是个什么东西 …...

7-6 混合类型数据格式化输入

本题要求编写程序&#xff0c;顺序读入浮点数1、整数、字符、浮点数2&#xff0c;再按照字符、整数、浮点数1、浮点数2的顺序输出。 输入格式&#xff1a; 输入在一行中顺序给出浮点数1、整数、字符、浮点数2&#xff0c;其间以1个空格分隔。 输出格式&#xff1a; 在一行中…...

最新全开源码支付系统,赠送3套模板

最新全开源码支付系统&#xff0c;赠送3套模板 码支付是专为个人站长打造的聚合免签系统&#xff0c;拥有卓越的性能和丰富的功能。它采用全新轻量化的界面UI 让您能更方便快捷地解决知识付费和运营赞助的难题&#xff0c;同时提供实时监控和管理功能&#xff0c;让您随时随地…...

Eclipse Leshan 常见问题解答 (FAQ) 笔记

本笔记基于 Eclipse Leshan Wiki - F.A.Q. 页面内容&#xff0c;旨在解答关于 Eclipse Leshan&#xff08;一个开源的 LwM2M 服务器和客户端 Java 实现&#xff09;的常见问题&#xff0c;帮助您更好地理解和使用该工具。 一、Leshan 是什么&#xff0c;我该如何使用它&#x…...

【6】数据结构的栈篇章

目录标题 栈的定义顺序栈的实现顺序栈的初始化入栈出栈获取栈顶元素顺序栈总代码与调试 双端栈的实现双端栈的初始化入栈出栈双端栈总代码与调试 链栈的实现链栈的初始化入栈出栈获取栈顶元素链栈总代码与调试 栈的定义 定义&#xff1a;栈&#xff08;Stack&#xff09;是一种…...

开源虚拟化管理平台Proxmox VE部署超融合

Proxmox VE 是一个功能强大、开源的虚拟化平台&#xff0c;结合了 KVM 和 LXC&#xff0c;同时支持高可用集群、存储管理&#xff08;ZFS、Ceph&#xff09;和备份恢复。相比 VMware ESXi 和 Hyper-V&#xff0c;PVE 具有开源、低成本、高灵活性的特点&#xff0c;适用于中小企…...

C语言基础要素(019):输出ASCII码表

计算机以二进制处理信息&#xff0c;但二进制对人类并不友好。比如说我们规定用二进制值 01000001 表示字母’A’&#xff0c;显然通过键盘输入或屏幕阅读此数据而理解它为字母A&#xff0c;是比较困难的。为了有效的使用信息&#xff0c;先驱者们创建了一种称为ASCII码的交换代…...

函数柯里化(Currying)介绍(一种将接受多个参数的函数转换为一系列接受单一参数的函数的技术)

文章目录 柯里化的特点示例普通函数柯里化实现使用Lodash进行柯里化 应用场景总结 函数柯里化&#xff08;Currying&#xff09;是一种将接受多个参数的函数转换为一系列接受单一参数的函数的技术。换句话说&#xff0c;柯里化将一个多参数函数转化为一系列嵌套的单参数函数。 …...

基于大模型的主动脉瓣病变预测及治疗方案研究报告

目录 一、引言 1.1 研究背景 1.2 研究目的 1.3 研究意义 二、大模型预测主动脉瓣病变原理 2.1 大模型介绍 2.2 数据收集与处理 2.3 模型训练与优化 三、术前预测与评估 3.1 主动脉瓣病变类型及程度预测 3.2 患者整体状况评估 3.3 手术风险预测 四、术中应用与监测…...

VSCode开发者工具快捷键

自动生成浏览器文件.html的快捷方式 在文本里输入&#xff1a; &#xff01; enter VSCode常用快捷键列表 代码格式化&#xff1a;Shift Alt F向上或向下移动一行&#xff1a;Alt Up 或者 Alt Down快速复制一行代码&#xff1a;Shift Alt Up 或者 Shift Alt Down快速保…...