JavaScript学习教程,从入门到精通,Ajax数据交换格式与跨域处理(26)
Ajax数据交换格式与跨域处理
一、Ajax数据交换格式
1. XML (eXtensible Markup Language)
XML是一种标记语言,类似于HTML但更加灵活,允许用户自定义标签。
特点:
- 可扩展性强
- 结构清晰
- 数据与表现分离
- 文件体积相对较大
示例代码:XML数据格式
<students><student><id>1</id><name>张三</name><age>20</age><major>计算机科学</major></student><student><id>2</id><name>李四</name><age>22</age><major>软件工程</major></student>
</students>
使用Ajax获取XML数据:
// 创建XMLHttpRequest对象
let xhr = new XMLHttpRequest();// 配置请求
xhr.open('GET', 'students.xml', true);// 设置响应类型
xhr.responseType = 'document';// 发送请求
xhr.send();// 处理响应
xhr.onload = function() {if (xhr.status === 200) {// 获取XML文档对象let xmlDoc = xhr.responseXML;// 获取所有student节点let students = xmlDoc.getElementsByTagName('student');// 遍历处理数据for (let i = 0; i < students.length; i++) {let id = students[i].getElementsByTagName('id')[0].textContent;let name = students[i].getElementsByTagName('name')[0].textContent;let age = students[i].getElementsByTagName('age')[0].textContent;let major = students[i].getElementsByTagName('major')[0].textContent;console.log(`ID: ${id}, 姓名: ${name}, 年龄: ${age}, 专业: ${major}`);}}
};
2. JSON (JavaScript Object Notation)
JSON是一种轻量级的数据交换格式,易于人阅读和编写,也易于机器解析和生成。
特点:
- 轻量级,文件体积小
- 易于解析
- 与JavaScript原生兼容
- 支持多种数据类型(字符串、数字、布尔值、数组、对象、null)
示例代码:JSON数据格式
{"students": [{"id": 1,"name": "张三","age": 20,"major": "计算机科学"},{"id": 2,"name": "李四","age": 22,"major": "软件工程"}]
}
使用Ajax获取JSON数据:
// 创建XMLHttpRequest对象
let xhr = new XMLHttpRequest();// 配置请求
xhr.open('GET', 'students.json', true);// 发送请求
xhr.send();// 处理响应
xhr.onload = function() {if (xhr.status === 200) {// 解析JSON数据let data = JSON.parse(xhr.responseText);// 遍历处理数据data.students.forEach(student => {console.log(`ID: ${student.id}, 姓名: ${student.name}, 年龄: ${student.age}, 专业: ${student.major}`);});}
};
使用fetch API获取JSON数据(现代方法):
fetch('students.json').then(response => {if (!response.ok) {throw new Error('网络响应不正常');}return response.json();}).then(data => {data.students.forEach(student => {console.log(`ID: ${student.id}, 姓名: ${student.name}, 年龄: ${student.age}, 专业: ${student.major}`);});}).catch(error => {console.error('获取数据时出错:', error);});
二、无刷新列表分页
无刷新分页通过Ajax技术实现,只更新页面中需要变化的部分,而不是整个页面刷新。
实现步骤:
- 监听分页按钮点击事件
- 阻止默认行为(页面跳转)
- 发送Ajax请求获取分页数据
- 使用JavaScript动态更新页面内容
示例代码:无刷新分页实现
HTML部分:
<div id="product-list"><!-- 产品列表将在这里动态加载 -->
</div><div class="pagination"><a href="#" class="page-link" data-page="1">1</a><a href="#" class="page-link" data-page="2">2</a><a href="#" class="page-link" data-page="3">3</a><!-- 更多分页链接 -->
</div>
JavaScript部分:
// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', function() {// 默认加载第一页loadPage(1);// 为所有分页链接添加点击事件document.querySelectorAll('.page-link').forEach(link => {link.addEventListener('click', function(e) {e.preventDefault(); // 阻止默认跳转行为let page = this.getAttribute('data-page');loadPage(page);});});
});// 加载分页数据的函数
function loadPage(page) {// 显示加载状态document.getElementById('product-list').innerHTML = '<p>加载中...</p>';// 使用fetch API获取数据fetch(`api/products.php?page=${page}`).then(response => {if (!response.ok) {throw new Error('网络响应不正常');}return response.json();}).then(data => {// 清空当前内容let productList = document.getElementById('product-list');productList.innerHTML = '';// 检查是否有数据if (data.length === 0) {productList.innerHTML = '<p>没有找到产品</p>';return;}// 创建产品列表HTMLlet html = '<ul class="products">';data.forEach(product => {html += `<li class="product-item"><h3>${product.name}</h3><p>价格: ¥${product.price}</p><p>${product.description}</p></li>`;});html += '</ul>';// 更新DOMproductList.innerHTML = html;// 更新活动分页链接样式document.querySelectorAll('.page-link').forEach(link => {link.classList.remove('active');if (link.getAttribute('data-page') == page) {link.classList.add('active');}});}).catch(error => {console.error('获取数据时出错:', error);document.getElementById('product-list').innerHTML = '<p>加载数据时出错,请稍后再试</p>';});
}
三、跨域处理
1. 什么是跨域
跨域是指浏览器不能执行其他网站的脚本,它是由浏览器的同源策略造成的。
同源策略限制以下行为:
- Cookie、LocalStorage和IndexDB无法读取
- DOM无法获得
- AJAX请求不能发送
同源的定义:
- 协议相同(http/https)
- 域名相同
- 端口相同
2. JSONP (JSON with Padding)
JSONP是一种跨域解决方案,利用<script>
标签没有跨域限制的特性来实现。
实现原理:
- 前端定义一个回调函数
- 动态创建
<script>
标签,src指向跨域API并在URL中指定回调函数名 - 服务器返回的数据作为回调函数的参数
- 浏览器执行回调函数,处理返回的数据
示例代码:JSONP实现
前端代码:
// 定义回调函数
function handleResponse(data) {console.log('接收到数据:', data);// 在这里处理返回的数据
}// 创建script标签
let script = document.createElement('script');
script.src = 'https://api.example.com/data?callback=handleResponse';// 添加到文档中
document.body.appendChild(script);// 请求完成后移除script标签
script.onload = function() {document.body.removeChild(script);
};
服务器端响应(PHP示例):
<?php
$data = array('name' => '张三','age' => 25,'city' => '北京'
);$callback = $_GET['callback'];
echo $callback . '(' . json_encode($data) . ')';
?>
jQuery中的JSONP:
$.ajax({url: 'https://api.example.com/data',dataType: 'jsonp',jsonpCallback: 'handleResponse', // 可选,自定义回调函数名success: function(data) {console.log('接收到数据:', data);},error: function(xhr, status, error) {console.error('请求失败:', status, error);}
});
3. CORS (Cross-Origin Resource Sharing)
CORS是一种官方推荐的跨域解决方案,需要服务器端支持。
简单请求与非简单请求:
- 简单请求:GET、HEAD、POST,且Content-Type为text/plain、multipart/form-data、application/x-www-form-urlencoded
- 非简单请求:PUT、DELETE等,或自定义头部的请求
服务器端设置响应头:
<?php
header("Access-Control-Allow-Origin: *"); // 允许所有域名
// 或
header("Access-Control-Allow-Origin: http://example.com"); // 允许特定域名// 对于需要携带凭证的请求
header("Access-Control-Allow-Credentials: true");// 允许的HTTP方法
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");// 允许的头部
header("Access-Control-Allow-Headers: Content-Type, Authorization");
?>
前端使用CORS:
// 简单GET请求
fetch('https://api.example.com/data').then(response => response.json()).then(data => console.log(data)).catch(error => console.error(error));// 带凭证的请求
fetch('https://api.example.com/data', {credentials: 'include' // 包含cookie等凭证
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));// 非简单请求(PUT请求)
fetch('https://api.example.com/data/123', {method: 'PUT',headers: {'Content-Type': 'application/json','Authorization': 'Bearer token123'},body: JSON.stringify({name: '新名称',value: '新值'})
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
预检请求(Preflight Request):
对于非简单请求,浏览器会先发送一个OPTIONS请求进行预检,服务器需要正确处理。
四、综合案例:多图上传功能
实现一个支持多图上传、预览、删除和进度显示的功能。
HTML部分:
<div class="upload-container"><h2>多图上传</h2><!-- 文件选择区域 --><div class="upload-area"><input type="file" id="file-input" multiple accept="image/*" style="display: none;"><button id="select-btn">选择图片</button><span id="file-info">未选择文件</span></div><!-- 图片预览区域 --><div id="preview-area" class="preview-area"></div><!-- 上传按钮和进度条 --><button id="upload-btn" disabled>开始上传</button><div class="progress-container"><div id="progress-bar" class="progress-bar"></div><span id="progress-text">0%</span></div><!-- 上传结果 --><div id="result-area"></div>
</div>
CSS部分:
.upload-container {max-width: 800px;margin: 0 auto;padding: 20px;font-family: Arial, sans-serif;
}.upload-area {margin-bottom: 20px;padding: 15px;border: 2px dashed #ccc;border-radius: 5px;text-align: center;
}#select-btn {padding: 10px 15px;background-color: #4CAF50;color: white;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;
}#select-btn:hover {background-color: #45a049;
}.preview-area {display: flex;flex-wrap: wrap;gap: 10px;margin-bottom: 20px;
}.preview-item {position: relative;width: 120px;height: 120px;
}.preview-img {width: 100%;height: 100%;object-fit: cover;border-radius: 4px;
}.remove-btn {position: absolute;top: 5px;right: 5px;background-color: #f44336;color: white;border: none;border-radius: 50%;width: 20px;height: 20px;font-size: 12px;cursor: pointer;
}#upload-btn {padding: 10px 20px;background-color: #2196F3;color: white;border: none;border-radius: 4px;cursor: pointer;font-size: 16px;
}#upload-btn:disabled {background-color: #cccccc;cursor: not-allowed;
}#upload-btn:hover:not(:disabled) {background-color: #0b7dda;
}.progress-container {margin-top: 10px;display: none;
}.progress-bar {height: 20px;background-color: #f1f1f1;border-radius: 4px;overflow: hidden;
}.progress-bar::after {content: '';display: block;height: 100%;width: 0%;background-color: #4CAF50;transition: width 0.3s;
}#result-area {margin-top: 20px;padding: 10px;border-radius: 4px;
}.success {background-color: #ddffdd;border-left: 6px solid #4CAF50;
}.error {background-color: #ffdddd;border-left: 6px solid #f44336;
}
JavaScript部分:
document.addEventListener('DOMContentLoaded', function() {const fileInput = document.getElementById('file-input');const selectBtn = document.getElementById('select-btn');const fileInfo = document.getElementById('file-info');const previewArea = document.getElementById('preview-area');const uploadBtn = document.getElementById('upload-btn');const progressContainer = document.querySelector('.progress-container');const progressBar = document.getElementById('progress-bar');const progressText = document.getElementById('progress-text');const resultArea = document.getElementById('result-area');let selectedFiles = [];// 点击选择按钮触发文件输入selectBtn.addEventListener('click', function() {fileInput.click();});// 文件选择变化事件fileInput.addEventListener('change', function(e) {selectedFiles = Array.from(e.target.files);if (selectedFiles.length > 0) {fileInfo.textContent = `已选择 ${selectedFiles.length} 个文件`;uploadBtn.disabled = false;// 清空预览区域previewArea.innerHTML = '';// 显示预览图selectedFiles.forEach((file, index) => {if (!file.type.match('image.*')) {return;}const reader = new FileReader();reader.onload = function(e) {const previewItem = document.createElement('div');previewItem.className = 'preview-item';const img = document.createElement('img');img.className = 'preview-img';img.src = e.target.result;img.alt = file.name;const removeBtn = document.createElement('button');removeBtn.className = 'remove-btn';removeBtn.innerHTML = '×';removeBtn.addEventListener('click', function() {// 从数组中移除文件selectedFiles.splice(index, 1);// 从DOM中移除预览项previewItem.remove();// 更新文件信息fileInfo.textContent = selectedFiles.length > 0 ? `已选择 ${selectedFiles.length} 个文件` : '未选择文件';// 如果没有文件了,禁用上传按钮uploadBtn.disabled = selectedFiles.length === 0;});previewItem.appendChild(img);previewItem.appendChild(removeBtn);previewArea.appendChild(previewItem);};reader.readAsDataURL(file);});} else {fileInfo.textContent = '未选择文件';uploadBtn.disabled = true;}});// 上传按钮点击事件uploadBtn.addEventListener('click', function() {if (selectedFiles.length === 0) {alert('请先选择文件');return;}// 显示进度条progressContainer.style.display = 'block';progressBar.style.width = '0%';progressText.textContent = '0%';// 清空结果区域resultArea.innerHTML = '';resultArea.className = '';// 创建FormData对象const formData = new FormData();// 添加文件到FormDataselectedFiles.forEach(file => {formData.append('images[]', file);});// 添加其他数据(如果需要)formData.append('userId', '123');// 创建XMLHttpRequest对象const xhr = new XMLHttpRequest();// 配置请求xhr.open('POST', 'upload.php', true);// 进度事件xhr.upload.onprogress = function(e) {if (e.lengthComputable) {const percent = Math.round((e.loaded / e.total) * 100);progressBar.style.width = percent + '%';progressText.textContent = percent + '%';}};// 加载完成事件xhr.onload = function() {if (xhr.status === 200) {try {const response = JSON.parse(xhr.responseText);if (response.success) {resultArea.className = 'success';resultArea.innerHTML = `<p>上传成功!</p><p>共上传 ${response.data.uploaded_count} 张图片</p><ul>${response.data.images.map(img => `<li><strong>${img.original_name}</strong> - 大小: ${(img.size / 1024).toFixed(2)} KB, <a href="${img.url}" target="_blank">查看</a></li>`).join('')}</ul>`;} else {resultArea.className = 'error';resultArea.innerHTML = `<p>上传失败</p><p>${response.message}</p>${response.errors ? `<ul>${response.errors.map(err => `<li>${err}</li>`).join('')}</ul>` : ''}`;}} catch (e) {resultArea.className = 'error';resultArea.innerHTML = '<p>解析服务器响应时出错</p>';}} else {resultArea.className = 'error';resultArea.innerHTML = `<p>上传失败,服务器返回状态码: ${xhr.status}</p>`;}// 重置上传按钮和文件选择uploadBtn.disabled = true;fileInput.value = '';selectedFiles = [];fileInfo.textContent = '未选择文件';};// 错误事件xhr.onerror = function() {resultArea.className = 'error';resultArea.innerHTML = '<p>上传过程中发生网络错误</p>';};// 发送请求xhr.send(formData);});
});
服务器端PHP代码(upload.php):
<?php
header('Content-Type: application/json');// 设置跨域头(如果需要)
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Content-Type");// 响应数据结构
$response = ['success' => false,'message' => '','errors' => [],'data' => []
];// 检查是否有文件上传
if (empty($_FILES['images'])) {$response['message'] = '没有接收到任何文件';echo json_encode($response);exit;
}// 创建上传目录(如果不存在)
$uploadDir = 'uploads/' . date('Y/m/d');
if (!file_exists($uploadDir)) {mkdir($uploadDir, 0777, true);
}// 处理每个上传的文件
$uploadedFiles = [];
$errors = [];foreach ($_FILES['images']['tmp_name'] as $key => $tmpName) {// 检查上传错误if ($_FILES['images']['error'][$key] !== UPLOAD_ERR_OK) {$errors[] = '文件 ' . $_FILES['images']['name'][$key] . ' 上传失败: ' . getUploadError($_FILES['images']['error'][$key]);continue;}// 验证文件类型$fileType = mime_content_type($tmpName);if (!in_array($fileType, ['image/jpeg', 'image/png', 'image/gif'])) {$errors[] = '文件 ' . $_FILES['images']['name'][$key] . ' 不是有效的图片格式 (JPEG, PNG, GIF)';continue;}// 验证文件大小(限制为5MB)if ($_FILES['images']['size'][$key] > 5 * 1024 * 1024) {$errors[] = '文件 ' . $_FILES['images']['name'][$key] . ' 大小超过5MB限制';continue;}// 生成唯一文件名$extension = pathinfo($_FILES['images']['name'][$key], PATHINFO_EXTENSION);$filename = uniqid() . '.' . $extension;$destination = $uploadDir . '/' . $filename;// 移动文件到目标位置if (move_uploaded_file($tmpName, $destination)) {$uploadedFiles[] = ['original_name' => $_FILES['images']['name'][$key],'saved_name' => $filename,'size' => $_FILES['images']['size'][$key],'type' => $fileType,'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/' . $destination];} else {$errors[] = '无法保存文件 ' . $_FILES['images']['name'][$key];}
}// 设置响应
if (!empty($uploadedFiles)) {$response['success'] = true;$response['message'] = '部分文件上传成功';$response['data'] = ['uploaded_count' => count($uploadedFiles),'images' => $uploadedFiles];if (!empty($errors)) {$response['errors'] = $errors;}
} else {$response['message'] = '没有文件上传成功';$response['errors'] = $errors;
}// 返回JSON响应
echo json_encode($response);// 辅助函数:获取上传错误信息
function getUploadError($errorCode) {switch ($errorCode) {case UPLOAD_ERR_INI_SIZE:return '文件大小超过服务器限制';case UPLOAD_ERR_FORM_SIZE:return '文件大小超过表单限制';case UPLOAD_ERR_PARTIAL:return '文件只有部分被上传';case UPLOAD_ERR_NO_FILE:return '没有文件被上传';case UPLOAD_ERR_NO_TMP_DIR:return '缺少临时文件夹';case UPLOAD_ERR_CANT_WRITE:return '写入磁盘失败';case UPLOAD_ERR_EXTENSION:return '文件上传被PHP扩展阻止';default:return '未知上传错误';}
}
?>
五、总结
-
数据交换格式:
- XML:结构严谨,适合复杂数据结构,但体积较大
- JSON:轻量级,与JavaScript无缝集成,是现代Web应用的首选
-
无刷新分页:
- 提升用户体验
- 减少服务器负载
- 通过Ajax动态加载数据
-
跨域解决方案:
- JSONP:简单易用,但只支持GET请求
- CORS:功能强大,安全性好,需要服务器支持
- 代理服务器:另一种解决方案(未在本文中详述)
-
文件上传:
- 使用FormData对象处理多文件上传
- 提供上传进度反馈
- 客户端预览和服务器端验证
通过掌握这些技术,可以构建更加现代化、用户友好的Web应用程序。
相关文章:
JavaScript学习教程,从入门到精通,Ajax数据交换格式与跨域处理(26)
Ajax数据交换格式与跨域处理 一、Ajax数据交换格式 1. XML (eXtensible Markup Language) XML是一种标记语言,类似于HTML但更加灵活,允许用户自定义标签。 特点: 可扩展性强结构清晰数据与表现分离文件体积相对较大 示例代码࿱…...

【FreeRTOS】事件标志组
文章目录 1 简介1.1事件标志1.2事件组 2事件标志组API2.1创建动态创建静态创建 2.2 删除事件标志组2.3 等待事件标志位2.4 设置事件标志位在任务中在中断中 2.5 清除事件标志位在任务中在中断中 2.6 获取事件组中的事件标志位在任务中在中断中 2.7 函数xEventGroupSync 3 事件标…...

超级扩音器手机版:随时随地,大声说话
在日常生活中,我们常常会遇到手机音量太小的问题,尤其是在嘈杂的环境中,如KTV、派对或户外活动时,手机自带的音量往往难以满足需求。今天,我们要介绍的 超级扩音器手机版,就是这样一款由上海聚告德业文化发…...

【数据可视化-27】全球网络安全威胁数据可视化分析(2015-2024)
🧑 博主简介:曾任某智慧城市类企业算法总监,目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…...

【6G 开发】NV NGC
配置 生成密钥 API Keys 生成您自己的 API 密钥,以便通过 Docker 客户端或通过 NGC CLI 使用 Secrets Manager、NGC Catalog 和 Private Registry 的 NGC 服务 以下个人 API 密钥已成功生成,可供此组织使用。这是唯一一次显示您的密钥。 请妥善保管您的…...
计算机视觉各类任务评价指标详解
文章目录 计算机视觉各类任务评价指标详解一、图像分类(Image Classification)常用指标1. 准确率(Accuracy)2. Top-k Accuracy3. 精确率(Precision)、召回率(Recall)、F1 分数&#…...

SIEMENS PLC程序解读 -Serialize(序列化)SCATTER_BLK(数据分散)
1、程序数据 第12个字节 PI 2、程序数据 第16个字节 PI 3、程序数据 第76个字节 PO 4、程序代码 2、程序解读 图中代码为 PLC 梯形图,主要包含以下指令及功能: Serialize(序列化): 将 SRC_VARIABLEÿ…...

宁德时代25年时代长安动力电池社招入职测评SHL题库Verify测评语言理解数字推理真题
测试分为语言和数字两部分,测试时间各为17分钟,测试正式开始后不能中断或暂停...
python源码打包为可执行的exe文件
文章目录 简单的方式(PyInstaller)特点步骤安装 PyInstaller打包脚本得到.exe文件 简单的方式(PyInstaller) 特点 支持 Python 3.6打包为单文件(–onefile)或文件夹形式自动处理依赖项 步骤 安装 PyIns…...
数据加密技术:从对称加密到量子密码的原理与实战
数据加密技术:从对称加密到量子密码的原理与实战 在网络安全体系中,数据加密是保护信息机密性、完整性的核心技术。从古代的凯撒密码到现代的量子加密,加密技术始终是攻防博弈的关键战场。本文将深入解析对称加密、非对称加密、哈希函数的核…...
高性能的开源网络入侵检测和防御引擎:Suricata介绍
一、Debian下使用Suricata 相较于Windows,Linux环境对Suricata的支持更加完善,操作也更为便捷。 1. 安装 Suricata 在Debian系统上,你可以通过包管理器 apt 轻松安装 Suricata。 更新软件包列表: sudo apt update安装 Suricata: sudo apt …...

【硬核解析:基于Python与SAE J1939-71协议的重型汽车CAN报文解析工具开发实战】
引言:重型汽车CAN总线的数据价值与挑战 随着汽车电子化程度的提升,控制器局域网(CAN总线)已成为重型汽车的核心通信网络。不同控制单元(ECU)通过CAN总线实时交互海量报文数据,这些数据隐藏着车…...
React类组件与React Hooks写法对比
React 类组件 vs Hooks 写法对比 分类类组件(Class Components)函数组件 Hooks组件定义class Component extends React.Componentconst Component () > {}状态管理this.state this.setState()useState()生命周期componentDidMount, componentDidU…...

Uniapp 自定义 Tabbar 实现教程
Uniapp 自定义 Tabbar 实现教程 1. 简介2. 实现步骤2.1 创建自定义 Tabbar 组件2.2 配置 pages.json2.3 在 App.vue 中引入组件 3. 实现过程中的关键点3.1 路由映射3.2 样式设计3.3 图标处理 4. 常见问题及解决方案4.1 页面跳转问题4.2 样式适配问题4.3 性能优化 5. 扩展功能5.…...

记录一次使用面向对象的C语言封装步进电机驱动
简介 (2025/4/21) 本库对目前仅针对TB6600驱动下的42步进电机的基础功能进行了一定的封装, 也是我初次尝试以面向对象的思想去编写嵌入式代码, 和直流电机的驱动步骤相似在调用stepmotor_attach()函数和stepmotor_init()函数之后仅通过结构体数组stepm然后指定枚举变量中的id即…...

Spark-streaming核心编程
1.导入依赖: <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-streaming-kafka-0-10_2.12</artifactId> <version>3.0.0</version> </dependency> 2.编写代码: 创建Sp…...
Exposure Adjusted Incidence Rate (EAIR) 暴露调整发病率:精准量化疾病风险
1. 核心概念 1.1 传统发病率的局限性 1.1.1 公式与定义 传统发病率公式为新发病例数除以总人口数乘以观察时间。例如在某社区观察1年,有10例新发病例,总人口1000人,发病率即为10/10001=0.01。 此公式假设所有个体暴露时间和风险相同,但实际中个体差异大,如部分人暴露时间…...

vue3+TS+echarts 折线图
需要实现的效果如下 <script setup lang"ts" name"RepsSingleLineChart">import * as echarts from echartsimport { getInitecharts } from /utils/echartimport type { EChartsOption } from echarts// 定义 props 类型interface Props {id: strin…...
MYSQL中为什么不建议delete数据
在 MySQL 中不建议频繁使用 delete 删除数据的原因主要在于性能、数据安全等方面的问题,以下是具体介绍: 性能问题 磁盘空间与碎片:delete 操作只是将数据标记为 “已删除”,并不会立即释放磁盘空间,频繁执行会导致大量…...
Linux多线程技术
什么是线程 在一个程序里的多执行路线就是线程。线程是进程中的最小执行单元,可理解为 “进程内的一条执行流水线”。 进程和线程的区别 进程是资源分配的基本单位,线程是CPU调度的基本单位。 fork创建出一个新的进程,会创建出一个新的拷贝&…...
12个HPC教程汇总!从入门到实战,覆盖分子模拟/材料计算/生物信息分析等多个领域
在科学研究、工程仿真、人工智能和大数据分析等领域,高性能计算 (High Performance Computing, HPC) 正扮演着越来越重要的角色。它通过并行处理、大规模计算资源的整合,极大提升了计算效率,使原本耗时数日的任务能够在数小时内完成。 随着计…...
[OpenGL] Lambertian材质漫反射BRDF方程的解释与推导
一、简介 本文简单的介绍了 Physical Based Rendering, PBR 中的 Lambertian 材质漫反射BRDF公式 f r l a m b e r t i a n c d i f f π fr_{lambertian}\frac{c_{diff}}{\pi} frlambertianπcdiff的推导。 二、漫反射项 根据 渲染方程: L o ( v ) ∫ …...

小火电视桌面TV版下载-小火桌面纯净版下载-官方历史版本安装包
别再费心地寻找小火桌面的官方历史版本安装包啦,试试乐看家桌面吧,它作为纯净版本的第三方桌面,具有诸多优点。 界面简洁纯净:乐看家桌面设计简洁流畅,页面简洁、纯净无广告,为用户打造了一个干净的电视操…...
VSFTPD+虚拟用户+SSL/TLS部署安装全过程(踩坑全通)
Author : Spinach | GHB Link : http://blog.csdn.net/bocai8058文章目录 前言准备配置虚拟用户1.创建虚拟用户列表文件2.生成数据库文件3.设置虚拟用户独立访问权限 配置PAM认证1.创建PAM配置文件2.测试PAM认证 创建虚拟用户映射的系统用户生成SSL/TLS证书配置VSFTPD服务1…...
07 Python 字符串全解析
文章目录 一. 字符串的定义二. 字符串的基本用法1. 访问字符串中的字符2. 字符串切片3. 字符串拼接4. 字符串重复5.字符串比较6.字符串成员运算 三. 字符串的常用方法1. len() 函数2. upper() 和 lower() 方法3. strip() 方法4. replace() 方法5. split() 方法 四. 字符串的进阶…...

androidstudio安装配置
B站配置视频AndroidStudio安装配置教程(最新版本教程)3分钟搞定 快速安装使用_哔哩哔哩_bilibili 1、环境变量 D:\AndroidSdk ANDROID_HOME ANDROID_SDK_HOME 2、新建 3、配置 distributionUrlhttps://mirrors.cloud.tencent.com/gradle/gradle-8.11.1-…...
全面解析 MCP(Model Context Protocol):AI 大模型的“万能连接器”
一、MCP 的定义与技术定位 **MCP(Model Context Protocol,模型上下文协议)**是由 Anthropic 公司于 2024 年 11 月推出的开源协议,旨在为 AI 大模型与外部数据源、工具之间建立标准化连接通道。它被业界称为 “AI 的 USB-C 接口”,通过统一的通信协议和数据结构,解决大模…...

《AI大模型趣味实战》基于RAG向量数据库的知识库AI问答助手设计与实现
基于RAG向量数据库的知识库AI问答助手设计与实现 引言 随着大语言模型(LLM)技术的快速发展,构建本地知识库AI问答助手已成为许多企业级应用的需求。本研究报告将详细介绍如何基于FLASK开发一个使用本地OLLAMA大模型底座的知识库AI问答助手&…...
Lua 第8部分 补充知识
8.1 局部变量和代码块 Lua 语言中的变量在默认情况下是全局变量 ,所有的局部变量在使用前必须声明 。 与全局变量不同,局部变量的生效范围仅限于声明它的代码块。一个代码块( block )是一个控制结构的主体,或是一个函…...
正则表达式三剑客之——awk命令
目录 一.什么是awk 二.awk的语法格式 1.选项 2. 模式(Pattern) 3. 操作(Action) 4. 输入文件(file) 5.总结 三.awk的工作原理 1. 逐行扫描输入 2. 匹配模式 1.正则表达式: 2.逻辑…...