探索原生JS的力量:自定义实现类似于React的useState功能
1.写在前面
本方案特别适合希望在历史遗留的原生JavaScript项目中实现简单轻量级数据驱动机制的开发者。无需引入任何框架或第三方库,即可按照此方法封装出类似于React中useState
的功能,轻松为项目添加状态管理能力,既保持了项目的轻量性,又提升了开发效率
2.优势总结 ★ 了解
1. 轻量级响应式系统
-
无虚拟DOM:直接监听状态变化并更新真实DOM,避免虚拟DOM的diff计算开销
-
精准更新:只有订阅了状态变化的DOM元素会更新(相比React的组件级重渲染更精确)
2. 类React开发体验
-
提供
useState
+setState
的API设计,降低学习成本 -
支持函数式更新:
setState(prev => prev + 1)
3. 状态不可变性
-
自动深拷贝状态,避免意外修改
-
每次更新都生成新状态,便于实现时间旅行调试
4. 批量更新优化
-
batch()
可合并多次更新为单次渲染 -
避免频繁DOM操作导致的布局抖动
5. 多实例隔离
-
不同模块可以使用独立的状态实例,避免全局污染
3.单例模式 ★ 重要
单例模式效果展示
单例模式封装
/*** 单例模式状态管理* 整个应用共享同一个状态实例*/// ==================== 深拷贝工具 ====================
function deepClone(obj, hash = new WeakMap()) {if (obj == null) return obj;if (typeof obj !== 'object') return obj;const constructor = obj.constructor;const specialTypes = ['Date', 'RegExp', 'Map', 'Set'];if (specialTypes.includes(constructor.name)) {return new constructor(obj);}if (hash.has(obj)) return hash.get(obj);const clone = Array.isArray(obj) ? [] : Object.create(Object.getPrototypeOf(obj));hash.set(obj, clone);[...Object.getOwnPropertySymbols(obj), ...Object.keys(obj)].forEach(key => {clone[key] = deepClone(obj[key], hash);});return clone;
}// ==================== 核心实现 ====================
const subscribers = new Map();
let batchQueue = [];
let isBatching = false;function batchNotify(proxy) {const callbacks = subscribers.get(proxy);if (!callbacks) return;Promise.resolve().then(() => {callbacks.forEach(cb => {try {cb(proxy.value);} catch (e) {console.error('回调执行失败:', e);}});});
}export const useState = (initialState) => {if (typeof initialState === 'undefined') {throw new Error('初始状态不能为undefined');}const proxy = new Proxy({ value: deepClone(initialState) }, {set(target, key, value) {if (key !== 'value') return false;target[key] = deepClone(value);if (!isBatching) batchNotify(proxy);return true;}});return {get state() { return proxy.value; },setState: (updater) => {if (isBatching) {batchQueue.push({ proxy, updater });} else {proxy.value = typeof updater === 'function' ? updater(proxy.value) : updater;}},subscribe: (callback) => {if (typeof callback !== 'function') {throw new Error('回调必须是函数');}if (!subscribers.has(proxy)) {subscribers.set(proxy, new Set());}subscribers.get(proxy).add(callback);return () => {subscribers.get(proxy)?.delete(callback);};}};
};export const batch = (callback) => {if (isBatching) return callback();isBatching = true;batchQueue = [];try {callback();const updatesByProxy = new Map();batchQueue.forEach(({ proxy, updater }) => {if (!updatesByProxy.has(proxy)) {updatesByProxy.set(proxy, []);}updatesByProxy.get(proxy).push(updater);});updatesByProxy.forEach((updaters, proxy) => {let state = proxy.value;updaters.forEach(updater => {state = typeof updater === 'function' ? updater(state) : updater;state = deepClone(state);});proxy.value = state;batchNotify(proxy);});} finally {isBatching = false;batchQueue = [];}
};
单例模式HTML测试
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>单例模式测试</title><script type="module">import { useState, batch } from './singleton-state.js';const counter = useState(0);counter.subscribe(count => {document.getElementById('count').textContent = count;console.log('当前计数:', count);});// 普通更新document.getElementById('increment').addEventListener('click', () => {counter.setState(c => c + 1);});// 批量更新document.getElementById('increment-5').addEventListener('click', () => {batch(() => {counter.setState(c => c + 1);counter.setState(c => c + 1);counter.setState(c => c + 1);counter.setState(c => c + 1);counter.setState(c => c + 1);});});</script>
</head>
<body>
<h1>单例模式测试</h1>
<div>计数: <span id="count">0</span></div>
<button id="increment">+1</button>
<button id="increment-5">+5 (批量)</button>
</body>
</html>
4.多例模式 ★ 重要·推荐
双例模式效果展示
双例模式封装
/*** 多例模式状态管理工具* 允许创建多个独立的状态管理实例,每个实例拥有独立的状态和订阅系统* * 主要特点:* 1. 可创建多个隔离的状态管理实例* 2. 每个实例拥有独立的useState和batch方法* 3. 完整的状态不可变性保证* 4. 支持批量更新优化性能* * 使用方式:* const store = createStateStore();* const counter = store.useState(0);* * counter.subscribe(state => console.log(state));* counter.setState(prev => prev + 1);* store.batch(() => { ... });*/// ==================== 深拷贝工具函数 ====================/*** 高性能深拷贝函数* @param {any} obj - 需要拷贝的对象* @param {WeakMap} [hash=new WeakMap()] - 用于存储已拷贝对象的WeakMap(防止循环引用)* @returns {any} 深拷贝后的对象* * 实现特点:* 1. 处理基本数据类型:直接返回* 2. 处理循环引用:使用WeakMap缓存已拷贝对象* 3. 保留特殊对象类型:Date、RegExp等* 4. 原型链继承:保持原型链关系* 5. 性能优化:使用Object.keys+Symbol属性遍历*/
function deepClone(obj, hash = new WeakMap()) {// 处理null和undefinedif (obj == null) return obj;// 处理基本数据类型(string, number, boolean, symbol, bigint)if (typeof obj !== 'object') return obj;// 处理特殊对象类型const constructor = obj.constructor;const specialTypes = ['Date', 'RegExp', 'Map', 'Set', 'WeakMap', 'WeakSet'];if (specialTypes.includes(constructor.name)) {return new constructor(obj);}// 检查循环引用if (hash.has(obj)) return hash.get(obj);// 根据对象类型创建空对象或数组const clone = Array.isArray(obj) ? [] : Object.create(Object.getPrototypeOf(obj));// 缓存当前对象,防止循环引用hash.set(obj, clone);// 拷贝Symbol类型属性const symKeys = Object.getOwnPropertySymbols(obj);if (symKeys.length > 0) {symKeys.forEach(symKey => {clone[symKey] = deepClone(obj[symKey], hash);});}// 拷贝普通属性Object.keys(obj).forEach(key => {clone[key] = deepClone(obj[key], hash);});return clone;
}// ==================== 状态管理工厂函数 ====================/*** 创建新的状态管理实例* @returns {Object} 包含useState和batch方法的对象* * 每个实例包含:* 1. 独立的订阅者系统* 2. 独立的批量更新队列* 3. 独立的状态树*/
export function createStateStore() {/*** 订阅者集合* Map结构:* key: 状态代理对象(Proxy)* value: 该状态的订阅者回调集合(Set)*/const subscribers = new Map();/*** 批量更新队列* 数组结构,每个元素包含:* - proxy: 状态代理对象* - updater: 更新函数或值*/let batchQueue = [];/*** 批量更新标志* @type {boolean}*/let isBatching = false;// ==================== 内部工具方法 ====================/*** 通知订阅者状态变更* @param {Proxy} proxy - 状态代理对象* * 实现特点:* 1. 使用微任务(Promise)异步执行通知* 2. 错误处理避免影响其他订阅者* 3. 自动清理无效订阅*/function batchNotify(proxy) {// 获取当前状态的所有订阅者const callbacks = subscribers.get(proxy);if (!callbacks || callbacks.size === 0) return;// 使用微任务异步执行通知Promise.resolve().then(() => {// 获取当前状态值const state = proxy.value;// 遍历执行所有订阅回调callbacks.forEach(callback => {try {callback(state);} catch (error) {console.error('[状态通知错误] 订阅回调执行失败:', error);}});});}// ==================== 公开API ====================/*** 创建响应式状态* @param {any} initialState - 初始状态* @returns {Object} 包含state、setState和subscribe方法的对象* * @throws {Error} 当initialState为undefined时抛出错误*/function useState(initialState) {// 参数校验if (typeof initialState === 'undefined') {throw new Error('useState: 初始状态不能为undefined');}// 创建响应式代理对象const proxy = new Proxy({ value: deepClone(initialState) },{/*** 代理set陷阱* @param {Object} target - 目标对象* @param {string} key - 属性名* @param {any} value - 新值* @returns {boolean} 是否设置成功*/set(target, key, value) {// 只处理value属性的变更if (key !== 'value') return false;// 深拷贝新值,确保状态不可变target[key] = deepClone(value);// 非批量模式下立即通知订阅者if (!isBatching) {batchNotify(proxy);}return true;}});/*** 订阅状态变更* @param {Function} callback - 状态变更回调函数* @returns {Function} 取消订阅的函数* * @throws {Error} 当callback不是函数时抛出错误*/function subscribe(callback) {// 参数校验if (typeof callback !== 'function') {throw new Error('subscribe: 回调必须是函数');}// 初始化该状态的订阅者集合if (!subscribers.has(proxy)) {subscribers.set(proxy, new Set());}// 添加订阅者const callbacks = subscribers.get(proxy);callbacks.add(callback);// 返回取消订阅函数return function unsubscribe() {callbacks.delete(callback);// 清理空订阅集合if (callbacks.size === 0) {subscribers.delete(proxy);}};}/*** 更新状态* @param {Function|any} updater - 更新函数或新状态值* * 更新规则:* 1. 如果是函数:updater(prevState) => newState* 2. 如果是值:直接替换状态*/function setState(updater) {if (isBatching) {// 批量模式下将更新操作加入队列batchQueue.push({proxy,updater});} else {// 直接更新模式proxy.value = typeof updater === 'function'? updater(proxy.value): updater;}}// 返回状态访问接口return {/*** 获取当前状态值* @returns {any} 当前状态*/get state() {return proxy.value;},setState,subscribe};}/*** 批量更新状态* @param {Function} callback - 包含多个状态更新的回调函数* * 实现特点:* 1. 合并多个setState调用为一次更新* 2. 自动处理状态依赖关系* 3. 最终只触发一次订阅通知*/function batch(callback) {// 如果已经在批量模式中,直接执行回调if (isBatching) {callback();return;}// 进入批量模式isBatching = true;batchQueue = [];try {// 执行用户回调,收集所有setState操作callback();// 按状态代理分组更新操作const updatesByProxy = new Map();batchQueue.forEach(({ proxy, updater }) => {if (!updatesByProxy.has(proxy)) {updatesByProxy.set(proxy, []);}updatesByProxy.get(proxy).push(updater);});// 处理每个状态代理的更新updatesByProxy.forEach((updaters, proxy) => {let currentState = proxy.value;// 按顺序应用所有更新器updaters.forEach(updater => {currentState = typeof updater === 'function'? updater(currentState): updater;// 确保每次更新都是不可变的currentState = deepClone(currentState);});// 最终更新状态值proxy.value = currentState;// 通知该状态的订阅者batchNotify(proxy);});} finally {// 确保无论是否出错都退出批量模式isBatching = false;batchQueue = [];}}// 返回实例方法return { useState, batch };
}// ==================== 可选默认实例 ====================/*** 默认导出的状态管理实例* 为方便使用,同时提供创建新实例和默认实例两种方式*/
const defaultStore = createStateStore();
export const { useState: defaultUseState, batch: defaultBatch } = defaultStore;
双例模式HTML测试
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>多例模式状态管理测试</title><style>body {font-family: Arial, sans-serif;max-width: 600px;margin: 0 auto;padding: 20px;}.counter {margin: 20px 0;padding: 15px;border: 1px solid #ddd;border-radius: 5px;}button {padding: 8px 16px;margin-right: 10px;cursor: pointer;}</style>
</head>
<body><h1>多例模式状态管理测试</h1><div class="counter"><h2>独立计数器1</h2><div>当前值: <span id="counter1-value">0</span></div><button id="counter1-increment">增加</button><button id="counter1-batch">批量增加(+3)</button></div><div class="counter"><h2>独立计数器2</h2><div>当前值: <span id="counter2-value">100</span></div><button id="counter2-increment">增加</button></div><script type="module">// 从模块导入创建方法import { createStateStore } from './multi-state.js';// 创建两个完全独立的状态管理实例const store1 = createStateStore();const store2 = createStateStore();// 实例1:计数器1const counter1 = store1.useState(0);counter1.subscribe(state => {document.getElementById('counter1-value').textContent = state;console.log('计数器1更新:', state);});document.getElementById('counter1-increment').addEventListener('click', () => {counter1.setState(prev => prev + 1);});document.getElementById('counter1-batch').addEventListener('click', () => {store1.batch(() => {counter1.setState(prev => prev + 1);counter1.setState(prev => prev + 1);counter1.setState(prev => prev + 1);});});// 实例2:计数器2 (完全独立)const counter2 = store2.useState(100);counter2.subscribe(state => {document.getElementById('counter2-value').textContent = state;console.log('计数器2更新:', state);});document.getElementById('counter2-increment').addEventListener('click', () => {counter2.setState(prev => prev + 10);});// 暴露到全局方便测试window.stores = { store1, store2, counter1, counter2 };</script><div style="margin-top: 30px; color: #666;"><h3>测试说明:</h3><p>1. 两个计数器使用完全独立的状态管理实例</p><p>2. 打开控制台可以查看状态变化日志</p><p>3. 在控制台输入 <code>stores</code> 可以访问状态实例</p></div>
</body>
</html>
5.单例模式和双例模式的区别 ★ 了解
-
单例模式:
-
全局共享一个状态树
-
直接导出
useState
和batch
-
适合中小型应用
-
-
多例模式:
-
通过
createStateStore()
创建独立实例 -
每个实例有自己的状态和订阅系统
-
适合大型应用或需要隔离状态的场景
-
6.兼容性分析 ★ 了解
1. 支持的浏览器
特性 | 最低支持版本 | 覆盖率 |
---|---|---|
Proxy | Chrome 49+ | ~98% |
Firefox 18+ | ||
Edge 12+ | ||
Safari 10+ | ||
WeakMap | IE 11+ | ~99% |
Promise (微任务) | ES6+ | ~98% |
2. 不兼容场景
-
IE 11及以下:不支持Proxy(可用
Object.defineProperty
降级) -
老旧移动浏览器:部分Android 4.x设备不支持ES6
3. Polyfill方案
// 在入口文件添加以下polyfill
import 'core-js/stable'; // 提供Promise/WeakMap等
import 'proxy-polyfill'; // 提供Proxy的简单实现
7.全代码测试页 ★ 了解·测试
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>高性能响应式状态管理</title><style>body {font-family: Arial, sans-serif;max-width: 800px;margin: 0 auto;padding: 20px;line-height: 1.6;}button {padding: 8px 16px;margin: 5px;cursor: pointer;background-color: #4CAF50;color: white;border: none;border-radius: 4px;}button:hover {background-color: #45a049;}.container {margin: 20px 0;padding: 15px;border: 1px solid #ddd;border-radius: 5px;}pre {background-color: #f5f5f5;padding: 10px;border-radius: 4px;overflow-x: auto;}.perf-info {color: #666;font-size: 0.9em;margin-top: 5px;}</style>
</head>
<body>
<h1>高性能响应式状态管理</h1><!-- 计数器容器 -->
<div class="container"><h2>性能计数器</h2><div>当前值: <span id="counter-value">0</span></div><div class="perf-info" id="counter-perf"></div><button id="increment">增加 (+1)</button><button id="increment-100">快速增加100次</button><button id="increment-1000">压力测试1000次</button>
</div><!-- 用户信息容器 -->
<div class="container"><h2>用户信息</h2><pre id="user-info"></pre><div class="perf-info" id="user-perf"></div><button id="update-user">更新用户信息</button>
</div><!-- 待办事项容器 -->
<div class="container"><h2>待办事项</h2><ul id="todo-list"></ul><input type="text" id="new-todo" placeholder="输入新事项"><button id="add-todo">添加</button><div class="perf-info" id="todo-perf"></div>
</div><script>/*** 高性能深拷贝函数* 特点:* 1. 处理循环引用* 2. 保留特殊对象类型(Date, RegExp等)* 3. 惰性拷贝(按需拷贝)* @param {any} obj - 需要拷贝的对象* @param {WeakMap} hash - 用于存储已拷贝对象的WeakMap(防止循环引用)* @return {any} 深拷贝后的对象*/function deepClone(obj, hash = new WeakMap()) {// 基本类型直接返回if (obj === null || typeof obj !== 'object') return obj;// 处理循环引用if (hash.has(obj)) return hash.get(obj);// 处理特殊对象const constructor = obj.constructor;if (/^(Date|RegExp|Map|Set)$/i.test(constructor.name)) {return new constructor(obj);}// 初始化克隆对象const clone = Array.isArray(obj) ? [] : Object.create(Object.getPrototypeOf(obj));hash.set(obj, clone);// 使用Object.keys+forEach比for-in性能更好Object.keys(obj).forEach(key => {clone[key] = deepClone(obj[key], hash);});return clone;}/*** 创建高性能状态管理Store* @return {Object} 包含useState和batch方法的对象*/function createStore() {const subscribers = new Map(); // 存储订阅者回调函数let batchQueue = []; // 批量更新队列let isBatching = false; // 是否处于批量更新模式/*** 批量执行回调(使用微任务节流)* @param {Proxy} proxy - 状态代理对象*/function batchNotify(proxy) {const callbacks = subscribers.get(proxy);if (!callbacks) return;// 使用微任务确保在UI更新前处理所有状态变更Promise.resolve().then(() => {const state = proxy.value;callbacks.forEach(callback => {try {callback(state);} catch (e) {console.error('订阅回调出错:', e);}});});}/*** 创建响应式状态* @param {any} initialState - 初始状态* @return {Object} 包含state、setState和subscribe方法的对象*/function useState(initialState) {// 验证初始状态if (typeof initialState === 'undefined') {throw new Error('Initial state cannot be undefined');}// 创建响应式代理const proxy = new Proxy({ value: deepClone(initialState) }, {set(target, key, value) {if (key !== 'value') return false;// 深拷贝新值target[key] = deepClone(value);// 非批量模式下立即通知if (!isBatching) {batchNotify(proxy);}return true;}});/*** 订阅状态变化* @param {Function} callback - 状态变化时的回调函数* @return {Function} 取消订阅的函数*/function subscribe(callback) {if (typeof callback !== 'function') {throw new Error('订阅回调必须是一个函数');}if (!subscribers.has(proxy)) {subscribers.set(proxy, new Set());}const callbacks = subscribers.get(proxy);callbacks.add(callback);// 返回取消订阅函数return () => {callbacks.delete(callback);if (callbacks.size === 0) {subscribers.delete(proxy);}};}/*** 更新状态* @param {Function|any} updater - 更新函数或新状态*/function setState(updater) {if (isBatching) {// 批量模式下将更新器和代理存入队列batchQueue.push({proxy,updater});} else {// 直接更新proxy.value = typeof updater === 'function'? updater(proxy.value): updater;}}return {get state() { return proxy.value; }, // 获取当前状态setState, // 更新状态方法subscribe // 订阅状态变化方法};}/*** 批量更新* @param {Function} callback - 包含多个状态更新的回调函数*/function batch(callback) {isBatching = true;batchQueue = []; // 清空队列try {callback(); // 执行回调,收集所有setState调用// 将更新按对应的状态代理分组const updatesByProxy = new Map();batchQueue.forEach(({ proxy, updater }) => {if (!updatesByProxy.has(proxy)) {updatesByProxy.set(proxy, []);}updatesByProxy.get(proxy).push(updater);});// 处理每个代理的更新队列updatesByProxy.forEach((updaters, proxy) => {let currentState = proxy.value;// 按顺序应用所有更新器函数updaters.forEach(updater => {currentState = typeof updater === 'function'? updater(currentState) // 基于当前状态计算新值: updater;currentState = deepClone(currentState); // 深拷贝新状态});// 一次性更新代理的值proxy.value = currentState;// 手动触发通知batchNotify(proxy);});} finally {isBatching = false;batchQueue = []; // 清空队列}}return { useState, batch };}// ==================== 使用示例 ====================const { useState, batch } = createStore();/*** 性能监控工具* @param {string} name - 监控器名称* @return {Object} 包含record和updateUI方法的对象*/function createPerfMonitor(name) {let lastTime = performance.now();let count = 0;let totalTime = 0;return {/*** 记录性能数据* @return {Object} 包含duration、avg和count的性能数据*/record() {const now = performance.now();const duration = now - lastTime;lastTime = now;count++;totalTime += duration;return {duration: duration.toFixed(2),avg: (totalTime / count).toFixed(2),count};},/*** 更新UI显示性能数据* @param {string} elementId - 显示性能数据的元素ID*/updateUI(elementId) {const perf = this.record();document.getElementById(elementId).textContent =`最近更新: ${perf.duration}ms | 平均: ${perf.avg}ms | 更新次数: ${perf.count}`;}};}// 1. 计数器状态const counter = useState(0);const counterPerf = createPerfMonitor('counter');// 订阅计数器状态变化counter.subscribe(count => {document.getElementById('counter-value').textContent = count;counterPerf.updateUI('counter-perf');});// 2. 用户信息状态const user = useState({name: '张三',age: 25,address: {city: '北京',street: '朝阳区'},createdAt: new Date()});const userPerf = createPerfMonitor('user');// 订阅用户信息状态变化user.subscribe(user => {document.getElementById('user-info').textContent = JSON.stringify(user, null, 2);userPerf.updateUI('user-perf');});// 3. 待办事项状态const todos = useState([]);const todoPerf = createPerfMonitor('todo');// 订阅待办事项状态变化todos.subscribe(todos => {const listElement = document.getElementById('todo-list');listElement.innerHTML = '';todos.forEach((todo, index) => {const li = document.createElement('li');li.textContent = `${index + 1}. ${todo.text}`;if (todo.completed) {li.style.textDecoration = 'line-through';li.style.color = '#888';}// 添加完成/取消按钮const completeButton = document.createElement('button');completeButton.textContent = todo.completed ? '取消' : '完成';completeButton.style.marginLeft = '10px';completeButton.onclick = () => {todos.setState(prev => {const newTodos = [...prev];newTodos[index] = {...newTodos[index],completed: !newTodos[index].completed};return newTodos;});};li.appendChild(completeButton);listElement.appendChild(li);});todoPerf.updateUI('todo-perf');});// ==================== 事件绑定 ====================// 计数器操作document.getElementById('increment').addEventListener('click', () => {counter.setState(c => c + 1);});document.getElementById('increment-100').addEventListener('click', () => {batch(() => {for (let i = 0; i < 100; i++) {counter.setState(c => c + 1);}});});document.getElementById('increment-1000').addEventListener('click', () => {batch(() => {for (let i = 0; i < 1000; i++) {counter.setState(c => c + 1);}});});// 用户信息操作document.getElementById('update-user').addEventListener('click', () => {user.setState(prev => ({...prev,age: prev.age + 1,address: {...prev.address,street: `朝阳区${Math.floor(Math.random() * 100)}号`},updatedAt: new Date()}));});// 待办事项操作document.getElementById('add-todo').addEventListener('click', () => {const input = document.getElementById('new-todo');const text = input.value.trim();if (text) {todos.setState(prev => [...prev,{ text, completed: false }]);input.value = '';}});// 初始化输入框回车事件document.getElementById('new-todo').addEventListener('keypress', (e) => {if (e.key === 'Enter') {document.getElementById('add-todo').click();}});
</script>
</body>
</html>
相关文章:
探索原生JS的力量:自定义实现类似于React的useState功能
1.写在前面 本方案特别适合希望在历史遗留的原生JavaScript项目中实现简单轻量级数据驱动机制的开发者。无需引入任何框架或第三方库,即可按照此方法封装出类似于React中useState的功能,轻松为项目添加状态管理能力,既保持了项目的轻量性&am…...
Android系统深度定制:源码级拦截adb install的完整解决方案
一、需求背景与技术挑战 在Android 12.0系统定制开发中,我们面临一个关键需求:需要实现设备级应用安装管控,要求彻底禁用adb install安装方式。这种管控需要满足以下技术指标: 系统级全局拦截,覆盖所有adb install安装…...
基于大模型的非阵发性室性心动过速风险预测与诊疗方案研究报告
目录 一、引言 1.1 研究背景与意义 1.2 研究目的 1.3 国内外研究现状 二、非阵发性室性心动过速概述 2.1 定义与分类 2.2 发病机制 2.3 临床症状与诊断方法 三、大模型在预测中的应用原理 3.1 大模型简介 3.2 数据收集与预处理 3.3 模型训练与优化 3.4 预测原理与…...
HttpServletRequest是什么
HttpServletRequest 是 Java Servlet API 中的一个接口,表示 HTTP 请求对象。它封装了客户端(如浏览器)发送到服务器的请求信息,并提供了访问这些信息的方法。 1. 基本概念 作用: HttpServletRequest 提供了一种机制&…...
【现代深度学习技术】循环神经网络02:文本预处理
【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上,结合当代大数据和大算力的发展而发展出来的。深度学习最重…...
【微服务】SpringBoot 整合 Lock4j 分布式锁使用详解
目录 一、前言 二、Lock4j 概述 2.1 Lock4j 介绍 2.1.1 Lock4j 是什么 2.1.2 Lock4j 主要特征 2.1.3 Lock4j 技术特点 2.2 Lock4j 支持的锁类型 2.3 Lock4j 工作原理 2.4 Lock4j 应用场景 三、springboot 整合 lock4j 3.1 前置准备 3.1. 1 导入依赖 3.2 基于Redis…...
如何将前端组件封装并发布到npm的步骤详解
以下是封装前端组件并发布至npm仓库的完整步骤指南,结合多个最佳实践和常见问题解决方案: 一、环境准备与项目初始化 创建项目结构 • 使用Vue CLI或Create React App初始化项目: vue create my-component-lib # Vue npx create-react-app my-component-lib --template ty…...
【QT】QWidget 概述与核心属性(API)
🌈 个人主页:Zfox_ 🔥 系列专栏:Qt 目录 一:🔥 控件概述 🦋 控件体系的发展阶段 二:🔥 QWidget 核心属性 🦋 核心属性概览🦋 用件可用(…...
vue + uniapp 实现仿百度地图/高德地图/美团/支付宝 滑动面板 纯css 实现
概要 使用百度地图、各种单车APP时,对地图上的滑动面板很感兴趣,于是根据自己的理解实现了一下 之前用的js实现,滑动的时候没有原生好 这一次用的css实现 代码 <template><view class"container"><mapstyle"…...
124. 二叉树中的最大路径和
https://leetcode.cn/problems/binary-tree-maximum-path-sum/description/?envTypestudy-plan-v2&envIdtop-interview-150对于这题我开始的思路是路径我们可以看作是一条线,我们确定一个点后可以往两侧延伸(就是左右子树的方向)&#x…...
spark运行架构
运行架构:Spark采用master - slave结构,Driver作为master负责作业任务调度,Executor作为slave负责实际执行任务。 核心组件: Driver:执行Spark任务的main方法,负责将用户程序转化为作业、调度任务、跟踪E…...
开源的7B参数OCR视觉大模型:RolmOCR
1. 背景介绍 早些时候,Allen Institute for AI 发布了 olmOCR,这是一个基于 Qwen2-VL-7B 视觉语言模型(VLM)的开源工具,用于处理 PDF 和其他复杂文档的 OCR(光学字符识别)。开发团队对该工具的…...
Http代理服务器选型与搭建
代理服务器选型-Squid 缓存加速 缓存频繁访问的网页、图片等静态资源,减少对原始服务器的重复请求,提升响应速度支持HTTP、HTTPS、FTP等协议,通过本地缓存直接响应客户端请求 访问控制 基于ACL(访问控制列表)实现精细…...
如何实现Microsoft Word (.docx) 格式到 FastReport .NET (.frx) 文件的转换
现代数据处理技术和文档工作流自动化需要集成各种文件格式,以确保软件产品之间的无缝交互。Microsoft Word 凭借其丰富的功能,已成为最受欢迎的文本编辑器之一,适用于各种任务。 有时,您可能需要将这些文档转换为其他应用程序特定…...
雷电多开器自动化运行、自动登录APP刷新日用户活跃量
文章目录 简介接单价格代码对爬虫、逆向感兴趣的同学可以查看文章,一对一小班教学(系统理论和实战教程)、提供接单兼职渠道:https://blog.csdn.net/weixin_35770067/article/details/142514698 简介 客户有一个APP,需要在雷电模拟器每天自动运行APP,每台模拟器设置不同的I…...
Dify教程01-Dify是什么、应用场景、如何安装
Dify教程01-Dify是什么、应用场景、如何安装 大家好,我是星哥,上篇文章讲了Coze、Dify、FastGPT、MaxKB 对比,今天就来学习如何搭建Dify。 Dify是什么 **Dify 是一款开源的大语言模型(LLM) 应用开发平台。**它融合了后端即服务(…...
《深入探秘:分布式软总线自发现、自组网技术原理》
在当今数字化浪潮中,分布式系统的发展日新月异,而分布式软总线作为实现设备高效互联的关键技术,其自发现与自组网功能宛如打开智能世界大门的钥匙,为多设备协同工作奠定了坚实基础。 分布式软总线的重要地位 分布式软总线是构建…...
spring扫描自定义注解注册bean
前言 我们知道,在spring中,我们只需要加上注解Component,就可以自动注入到spring容器中,如果我们自定义注解,怎么让spring识别到,注入到容器中呢,下面我们来看看。 基础使用 自定义注解 Tar…...
【RL系列】StepFun之Open-Reasoner-Zero
1. 简介 开源了一个大规模RL训练框架之Open-Reasoner-Zero,仅使用vanilla PPO,GAE中参数 λ 1 , γ 1 \lambda 1, \gamma 1 λ1,γ1,rule-based reward,不需要KL regularization就可以增加response length和benchmark上的指标。…...
括号匹配问题--栈
括号匹配问题 栈的应用代码概览栈操作函数详解1.初始化栈(stackInit)2.向栈中压入元素(stackpush)3.获取栈顶元素(stacktop)4.弹出栈顶元素(stackpop)5.销毁栈(stackdest…...
LangChain4j(7):Springboot集成LangChain4j实现知识库RAG
我们之前的直接整合进SpringBoot进行实战,最终其实还会将查询到的内容,和对话上下文组合起来,发给LLM为我们组织语言进行回答: 配置一个Content Retriever 内容检索器,提供向量数据库和向量模型及其他参数将内容检索器绑定到AiSe…...
企业使用Excel开展数据分析限制和建议完整版
Excel作为企业数据分析的常用工具,虽然功能强大,但也存在一些限制和使用时的注意事项。以下是综合整理的关键点: 一、Excel在企业数据分析中的限制 数据处理规模有限 Excel的行列限制(如Excel 2019及之前版本最多支持1,048,576行…...
41、web前端开发之Vue3保姆教程(五 实战案例)
一、项目简介和需求概述 1、项目目标 1.能够基于Vue3创建项目 2.能够基本Vue3相关的技术栈进行项目开发 3.能够使用Vue的第三方组件进行项目开发 4.能够理解前后端分离的开发模式 2、项目概述 使用Vue3结合ElementPlus,ECharts工具实现后台管理系统页面,包含登录功能,…...
Quill富文本编辑器支持自定义字体(包括新旧两个版本,支持Windings 2字体)
文章目录 1 新版(Quill2 以上版本)2 旧版(Quill1版本) 1 新版(Quill2 以上版本) <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta n…...
Flutter命令行打包打不出ipa报错
Flutter打包ipa报错解决方案 在Flutter开发中,打包iOS应用时可能会遇到以下错误: error: exportArchive: The data couldn’t be read because it isn’ in the correct format. 或者 Encountered error while creating the IPA: error: exportArchive…...
UV安装与使用
1. 概述 GitHub:astral-sh/uv: An extremely fast Python package and project manager, written in Rust. 官网:uv An extremely fast Python package and project manager, written in Rust. 效率神器,基于Rust实现,比传统工具快…...
SQL练习题
数据表介绍 –1.学生表 Student(SId,Sname,Sage,Ssex) --SId 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别–2.课程表 Course(CId,Cname,TId) --CId 课程编号,Cname 课程名称,TId 教师编号–3.教师表 Teacher(TId,Tname) --TId 教师编号,Tname 教师姓名–4.成绩表…...
Rust Command无法执行*拓展解决办法
async fn run_cmd_async_out<I, S>(cmd: &str, args: I, timeout_s: u64, with_http_proxy: bool) -> Result<String> whereI: IntoIterator<Item S>,S: AsRef<OsStr>, {let mut cmd tokio::process::Command::new(cmd);// 让 sh 来运行命令&…...
利用Hadoop MapReduce实现流量统计分析
在现代大数据时代,处理和分析海量数据是一项常见的任务。Hadoop MapReduce提供了一种高效的方式来处理分布式数据集。本文将通过一个具体的示例——流量统计分析,来展示如何使用Hadoop MapReduce进行数据处理。 项目背景 在电信行业中,对用…...
Spring Boot应用程序接入ELK-003
Spring Boot应用程序接入ELK 一、项目依赖集成 在将Spring Boot应用程序接入ELK日志搜索引擎时,首先要在项目中集成相关依赖: (一)Logstash依赖 <dependency><groupId>net.logstash.logback</groupId><a…...
spark(一)
本节课围绕Spark Core展开深入学习,了解了Spark的运行架构、核心组件、核心概念以及提交流程,明晰其整体运行机制与各部分协作逻辑。重点聚焦于两个核心组件;对RDD相关概念进行了细致学习,包括其核心属性、执行原理、序列化方式、…...
绿电直供零碳园区:如何用清洁能源重塑企业竞争力?
引言 在全球积极应对气候变化的大背景下,“双碳” 目标已成为世界各国实现可持续发展的关键战略方向。我国也明确提出要在 2030 年前实现碳达峰,2060 年前实现碳中和,这一宏伟目标的提出,对各行各业都产生了深远影响,…...
国家科技奖项目答辩ppt设计_科技进步奖PPT制作_技术发明奖ppt美化_自然科学奖ppt模板
国家科学技术奖 为了奖励在科学技术进步活动中做出突出贡献的公民、组织,调动科学技术工作者的积极性和创造性,加速科学技术事业的发展,提高综合国力而设立的一系列奖项。每两三年评选一次。 科技奖ppt案例 WordinPPT / 持续为双一流高校、…...
LLM应用实战2-理解Tokens
文章目录 基本定义Tokenization 的作用主流 Tokenization 算法示例示例GPT-4o&GPT-4o miniGPT-3.5 & GPT-4 基本定义 Tokens 是大型语言模型(LLM)处理文本或代码的最小语义单元,可包含以下形式: 字符(如英文…...
【Java面试系列】Spring Boot微服务架构下的分布式事务处理与性能优化详解 - 3-5年Java开发必备知识
【Java面试系列】Spring Boot微服务架构下的分布式事务处理与性能优化详解 - 3-5年Java开发必备知识 引言 在当今的微服务架构中,分布式事务处理和性能优化是面试中经常被问及的高频话题。随着系统规模的扩大,如何保证数据一致性和系统性能成为了开发者…...
NO.80十六届蓝桥杯备战|数据结构-字符串哈希|兔子与兔子(C++)
回忆:哈希函数与哈希冲突 哈希函数:将关键字映射成对应的地址的函数,记为 Hash(key) Addr 。哈希冲突:哈希函数可能会把两个或两个以上的不同关键字映射到同⼀地址,这种情况称为哈希冲突。 字符串哈希 定义⼀个把字…...
Spring MVC 请求类型注解详解
Spring MVC 请求类型注解详解 1. 核心注解分类 Spring MVC 中的请求处理注解分为以下几类: 类别注解示例作用范围方法级注解RequestMapping, GetMapping 等方法级别参数级注解RequestParam, RequestBody方法参数模型/会话注解ModelAttribute, SessionAttributes方…...
RabbitMQ的死信队列和ttl
TTL ttl即过期时间,rbbitmq可以对队列和消息设置过期时间,当消息到存活时间之后,还没有被消费,就会被自动清除 例如:在网上购物,经常会遇到一个场景,当下单超过24小时还未付款,订单…...
[特殊字符] Hyperlane:Rust 高性能 HTTP 服务器库,开启 Web 服务新纪元!
🚀 Hyperlane:Rust 高性能 HTTP 服务器库,开启 Web 服务新纪元! 🌟 什么是 Hyperlane? Hyperlane 是一个基于 Rust 语言开发的轻量级、高性能 HTTP 服务器库,专为简化网络服务开发而设计。它支…...
【后端开发】Spring MVC-常见使用、Cookie、Session
文章目录 代码总结初始化传递参数单参数多参数 传递对象后端参数重命名(后端参数映射)必传参数设置非必传参数 传递数组传递集合传递JSON数据JSON语法JSON格式转换JSON优点传递JSON对象 获取URL中参数传递文件 Cookie与SessionCookieCookie机制 SessionC…...
Element Plus 去掉表格外边框
使用el-table组件拖拽时, 想使用自定义样式进行拖拽, 想去掉外边框, 并在表头加入竖杠样式 css代码: <style lang"less" scoped>// 表格右边框线 .el-table--border::after {width: 0; }// 表格上边框线 :deep(.el-table__i…...
安全厂商安全理念分析
奇安信(toB企业安全) 安全理念:率先提出 “内生安全” 理念。即把安全能力内置到信息化环境中,通过信息化系统和安全系统的聚合、业务数据和安全数据的聚合、IT 人才和安全人才的聚合,让安全系统像人的免疫系统一样&a…...
GaussDB Plan Hint调优实战:从执行计划控制到性能优化
GaussDB Plan Hint调优实战:从执行计划控制到性能优化 一、GaussDB Plan Hint核心价值 执行计划控制原理 mermaid graph TD A[SQL提交] --> B(优化器决策) B --> C{使用Hint?} C -->|是| D[强制指定执行路径] C -->|否| E[自动生成最优计划] D --&g…...
【力扣hot100题】(078)跳跃游戏Ⅱ
好难啊,我愿称之为跳崖游戏。 依旧用了两种方法,一种是我一开始想到的,一种是看答案学会的。 我自己用的方法是动态规划,维护一个数组记录到该位置的最少步长,每遍历到一个位置就嵌套循环遍历这个位置能到达的位置&a…...
基于 DeepSeek API 实现一个简单的数据分析 Agent
写在前面 本文将带你一步步了解: 什么是(简单的)数据分析 Agent?为什么使用 LLM 进行数据分析?如何利用 DeepSeek API 的能力?设计并实现一个基于 Python 和 Pandas 的基础数据分析 Agent。探讨其局限性、安全考量及未来方向。我们的目标是构建一个简单的 Agent,它能理…...
VUE3+TS+elementplus+Django+MySQL实现从前端增加数据存入数据库,并显示在前端界面上
一、前言 前面实现了从数据库读取数据,显示在前端界面上VUE3TSelementplusDjangoMySQL实现从数据库读取数据,显示在前端界面上,以及使用VUE3TSelementplus创建一个增加按钮。今天通过在前端的增加功能,新增数据,传到后…...
Django 创建CSV文件
Django使用Python内置的CSV库来创建动态的CSV(逗号分隔值)文件。我们可以在项目的视图文件中使用这个库。 让我们来看一个例子,这里我们有一个Django项目,我们正在实现这个功能。创建一个视图函数 getfile() 。 Django CSV例子 …...
最新版RubyMine超详细图文安装教程,带补丁包(2025最新版保姆级教程)
目录 前言 一、RubyMine最新版下载 二、RubyMine安装 三、RubyMine补丁 四、运行RubyMine 前言 RubyMine是由JetBrains开发的集成开发环境(IDE),专为Ruby和Ruby on Rails开发者设计,提供智能代码补全、调试、测试、版本控制集…...
spring之JdbcTemplate、GoF之代理模式、面向切面编程AOP
一、JdbcTemplate JdbcTemplate是Spring提供的一个JDBC模板类,是对JDBC的封装,简化JDBC代码。 当然,你也可以不用,可以让Spring集成其它的ORM框架,例如:MyBatis、Hibernate等。 接下来我们简单来学习一下&…...
【QT】QT中的文件IO
QT中的文件IO 一、有关文件IO的类二、步骤1、定义QFile的对象,与要读写的文件绑定在一起2、打开文件3、读写文件1)读取文件2)写入文件 4、关闭文件5、示例代码: 三、QString和QByteArray之间的转换1、方法2、示例代码: 四、QFileI…...