深入理解 Vue.observable:轻量级响应式状态管理利器

目录

引言

一、什么是 Vue.observable?

二、为什么需要 Vue.observable?解决什么问题?

三、核心原理:响应式系统如何工作

四、如何使用 Vue.observable

功能说明

技术要点

五、关键注意事项与最佳实践

六、实际应用案例

七、总结


引言

在 Vue.js 应用中,状态管理是核心挑战之一。对于大型应用,Vuex 提供了强大的、集中式的解决方案。然而,对于小型到中型的组件间状态共享需求,或者希望避免引入 Vuex 的复杂度时,Vue 本身提供了一个非常优雅且轻量级的工具:Vue.observable

引入于 Vue 2.6 版本,Vue.observable 是 Vue 响应式系统底层能力的直接暴露。它允许你将一个普通的 JavaScript 对象转化为一个响应式对象。这意味着当这个对象的属性发生变化时,任何依赖这些属性的地方(如 Vue 组件的模板、计算属性、侦听器等)都会自动更新。

一、什么是 Vue.observable?

  • 核心定义: Vue.observable(object) 是一个全局 API,它接收一个普通的 JavaScript 对象作为参数,并返回该对象的响应式代理版本

  • 核心能力: 使传入的对象变得“可观察”(observable)。Vue 内部会追踪对该对象属性的访问(get 操作)和修改(set 操作)。

  • 响应式基础: 它是 Vue 实现数据绑定的基石。Vue 组件实例中的 data 选项返回的对象,在内部就是通过类似 observable 的机制(实际上是 Observer 类)处理的。

  • 轻量级状态管理: 它本身不是一个完整的状态管理库(如 Vuex),而是提供了创建响应式状态片段的能力。你可以利用它和简单的 JavaScript 模块模式来构建小型的状态存储。

二、为什么需要 Vue.observable?解决什么问题?

  1. 小型/简单状态共享:

    • 当你有几个组件需要共享一些简单的状态(如用户偏好设置、全局弹窗开关、小型的表单状态),引入 Vuex 可能显得过于臃肿和繁琐。

    • Vue.observable 提供了一种极其轻量的方式创建一个共享的、响应式的状态源。

  2. 避免“Prop Drilling”:

    • 在组件层级较深时,如果子组件需要祖先组件的数据,你可能需要一层层通过 props 传递下去,这被称为“Prop Drilling”,代码会变得冗余且难以维护。

    • 使用 Vue.observable 创建一个共享状态对象,需要数据的组件可以直接导入并使用这个对象,无需层层传递。

  3. 复用非组件逻辑的响应式状态:

    • 有时你可能有一些与 UI 组件解耦的纯 JavaScript 逻辑(如工具函数、服务层),但这些逻辑内部也需要管理一些状态,并且希望状态变化能驱动 UI 更新。

    • 用 Vue.observable 包装这些状态,就能让它们融入 Vue 的响应式系统。

  4. 理解 Vue 响应式原理的实践:

    • 直接使用 Vue.observable 有助于开发者更深入地理解 Vue 响应式系统是如何追踪依赖和触发更新的。

三、核心原理:响应式系统如何工作

理解 Vue.observable 的关键在于理解 Vue 的响应式原理(Vue 2.x 基于 Object.defineProperty,Vue 3 基于 Proxy,但概念相通)。这里以 Vue 2.x 为例:

  1. 依赖收集 (Tracking Dependencies):

    • 当你访问一个响应式对象的属性(例如 obj.a)时,Vue 会记录下“当前正在运行的代码”(通常是一个组件的渲染函数 render、一个计算属性 computed 或一个侦听器 watcher)依赖于 obj.a

    • 这个“正在运行的代码”被称为 Watcher (观察者)。

    • Vue 通过 Object.defineProperty 的 getter 拦截属性访问,并在 getter 中将当前的 Watcher 添加到该属性的依赖列表 (dep) 中。Dep (依赖) 是管理某个特定属性所有 Watcher 的类。

  2. 派发更新 (Triggering Updates):

    • 当你修改一个响应式对象的属性(例如 obj.a = 2)时,Vue 通过 Object.defineProperty 的 setter 拦截修改。

    • 在 setter 中,Vue 会通知该属性对应的 Dep

    • Dep 会遍历它所管理的所有 Watcher,告诉它们:“你们依赖的数据变了!”

    • 每个 Watcher 收到通知后,会重新执行它关联的代码(比如重新运行 render 函数更新视图、重新计算计算属性的值、执行侦听器回调函数)。

Vue.observable 的作用就是: 将一个普通对象包装起来,给它的每个属性(以及嵌套对象的属性)添加这些 getter 和 setter 拦截器,使其具备上述的依赖收集和派发更新的能力。

四、如何使用 Vue.observable

使用 Vue.observable 通常遵循以下模式:

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vue.observable 响应式状态管理</title><script src="https://cdn.staticfile.net/vue/2.7.14/vue.min.js"></script><style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);color: #333;min-height: 100vh;padding: 20px;}.container {max-width: 1200px;margin: 0 auto;}header {text-align: center;padding: 30px 0;color: white;text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);}h1 {font-size: 2.8rem;margin-bottom: 10px;}.subtitle {font-size: 1.2rem;opacity: 0.9;max-width: 800px;margin: 0 auto;line-height: 1.6;}.content {display: grid;grid-template-columns: 1fr 1fr;gap: 30px;margin-top: 30px;}@media (max-width: 768px) {.content {grid-template-columns: 1fr;}}.card {background: rgba(255, 255, 255, 0.92);border-radius: 16px;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);padding: 25px;transition: transform 0.3s ease;}.card:hover {transform: translateY(-5px);}.card h2 {color: #1a2a6c;margin-bottom: 20px;padding-bottom: 10px;border-bottom: 2px solid #fdbb2d;}.counter-display {font-size: 5rem;font-weight: bold;text-align: center;color: #b21f1f;margin: 20px 0;text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);}.btn-group {display: flex;justify-content: center;gap: 15px;margin: 20px 0;}button {background: linear-gradient(to right, #1a2a6c, #2a4a9c);color: white;border: none;padding: 12px 25px;border-radius: 50px;font-size: 1rem;font-weight: 600;cursor: pointer;transition: all 0.3s ease;box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);}button:hover {transform: translateY(-3px);box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2);background: linear-gradient(to right, #2a4a9c, #3a6adc);}button:active {transform: translateY(1px);}.secondary-btn {background: linear-gradient(to right, #fdbb2d, #ffcc5c);color: #333;}.secondary-btn:hover {background: linear-gradient(to right, #ffcc5c, #ffdd8c);}.info-box {background: #e3f2fd;border-left: 4px solid #2196f3;padding: 15px;border-radius: 4px;margin: 15px 0;}.code-block {background: #2d2d2d;color: #f8f8f2;padding: 15px;border-radius: 8px;font-family: 'Consolas', monospace;font-size: 0.95rem;overflow-x: auto;margin: 15px 0;}.user-list {list-style: none;margin: 15px 0;}.user-list li {background: white;padding: 12px 15px;margin-bottom: 10px;border-radius: 8px;box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);display: flex;justify-content: space-between;align-items: center;}.user-list li button {padding: 6px 12px;font-size: 0.85rem;}.computed-value {text-align: center;font-size: 1.2rem;padding: 15px;background: #e8f5e9;border-radius: 8px;margin: 15px 0;font-weight: bold;color: #2e7d32;}.notification {position: fixed;bottom: 20px;right: 20px;background: #4caf50;color: white;padding: 15px 25px;border-radius: 8px;box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);animation: slideIn 0.5s, fadeOut 0.5s 2.5s;}@keyframes slideIn {from {transform: translateX(100%);opacity: 0;}to {transform: translateX(0);opacity: 1;}}@keyframes fadeOut {from {opacity: 1;}to {opacity: 0;}}.theme-toggle {position: fixed;top: 20px;right: 20px;z-index: 100;}.dark-theme {background: linear-gradient(135deg, #0f1b3a, #2a0c4e, #5a1e5a);color: #e0e0e0;}.dark-theme .card {background: rgba(30, 30, 40, 0.92);color: #e0e0e0;}.dark-theme .card h2 {color: #64b5f6;}.dark-theme .info-box {background: #1e3a5f;border-left-color: #64b5f6;color: #e0e0e0;}.dark-theme .computed-value {background: #1b5e20;color: #a5d6a7;}.dark-theme .user-list li {background: #252536;color: #e0e0e0;}.dark-theme .code-block {background: #1a1a2a;}footer {text-align: center;color: white;padding: 30px 0;margin-top: 30px;font-size: 0.9rem;opacity: 0.8;}</style>
</head><body><div id="app"><div class="container"><header><h1>Vue.observable</h1><p class="subtitle">轻量级响应式状态管理解决方案 - 无需Vuex即可在组件间共享状态</p></header><div class="theme-toggle"><button @click="toggleTheme">{{ darkMode ? '浅色模式' : '深色模式' }}</button></div><div class="content"><!-- 计数器组件 --><div class="card"><h2>计数器演示</h2><div class="counter-display">{{ sharedState.count }}</div><div class="btn-group"><button @click="increment">增加</button><button @click="decrement" class="secondary-btn">减少</button><button @click="reset">重置</button></div><div class="computed-value">计数器平方: {{ countSquare }}</div><div class="info-box"><p>此计数器状态使用 Vue.observable 创建,可以在多个组件间共享。</p></div></div><!-- 用户管理组件 --><div class="card"><h2>用户管理</h2><div class="btn-group"><button @click="addUser">添加用户</button><button @click="clearUsers" class="secondary-btn">清空用户</button></div><div v-if="sharedState.users.length"><ul class="user-list"><li v-for="(user, index) in sharedState.users" :key="index"><span>{{ user.name }} ({{ user.email }})</span><button @click="removeUser(index)">删除</button></li></ul></div><div v-else class="info-box"><p>暂无用户,请点击"添加用户"按钮创建</p></div><div class="computed-value">用户总数: {{ userCount }}</div></div><!-- 通知系统 --><div class="card"><h2>通知系统</h2><div class="btn-group"><button @click="showNotification('success', '操作成功!')">成功通知</button><button @click="showNotification('error', '发生错误!')" class="secondary-btn">错误通知</button><button @click="showNotification('info', '这是信息通知')">信息通知</button></div><div class="info-box"><p>通知状态也是响应式的,可以在应用的任何地方触发。</p></div></div><!-- 代码示例 --><div class="card"><h2>实现代码</h2><div class="code-block">// 使用 Vue.observable 创建响应式状态const store = {state: Vue.observable({count: 0,users: [],notification: {show: false,message: '',type: 'info'}}),// 修改状态的方法increment() {this.state.count++;},decrement() {this.state.count--;},reset() {this.state.count = 0;},addUser() {const users = ['张三', '李四', '王五', '赵六', '钱七'];const domains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'example.com'];const name = users[Math.floor(Math.random() * users.length)];const email = `${name.toLowerCase()}@${domains[Math.floor(Math.random() * domains.length)]}`;this.state.users.push({ name, email });},removeUser(index) {this.state.users.splice(index, 1);},clearUsers() {this.state.users = [];},showNotification(type, message) {this.state.notification = {show: true,type,message};// 3秒后自动隐藏setTimeout(() => {this.state.notification.show = false;}, 3000);}};</div></div></div><footer><p>Vue.observable 示例 | Vue 2.7.14 | 响应式状态管理</p></footer></div><!-- 通知组件 --><div v-if="sharedState.notification.show" class="notification" :class="sharedState.notification.type">{{ sharedState.notification.message }}</div></div><script>// 使用 Vue.observable 创建响应式状态const store = {state: Vue.observable({count: 0,users: [],darkMode: false,notification: {show: false,message: '',type: 'info'}}),// 修改状态的方法increment() {this.state.count++;},decrement() {this.state.count--;},reset() {this.state.count = 0;},addUser() {const users = ['张三', '李四', '王五', '赵六', '钱七'];const domains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'example.com'];const name = users[Math.floor(Math.random() * users.length)];const email = `${name.toLowerCase()}@${domains[Math.floor(Math.random() * domains.length)]}`;this.state.users.push({ name, email });},removeUser(index) {this.state.users.splice(index, 1);},clearUsers() {this.state.users = [];},toggleTheme() {this.state.darkMode = !this.state.darkMode;document.body.classList.toggle('dark-theme', this.state.darkMode);},showNotification(type, message) {this.state.notification = {show: true,type,message};// 3秒后自动隐藏setTimeout(() => {this.state.notification.show = false;}, 3000);}};// 创建Vue实例new Vue({el: '#app',data: {sharedState: store.state},computed: {countSquare() {return this.sharedState.count * this.sharedState.count;},userCount() {return this.sharedState.users.length;},darkMode() {return this.sharedState.darkMode;}},methods: {increment() {store.increment();},decrement() {store.decrement();},reset() {store.reset();},addUser() {store.addUser();},removeUser(index) {store.removeUser(index);},clearUsers() {store.clearUsers();},toggleTheme() {store.toggleTheme();},showNotification(type, message) {store.showNotification(type, message);}},mounted() {// 初始添加2个用户store.addUser();store.addUser();}});</script>
</body></html>

功能说明

这个示例展示了Vue.observable的核心功能:

  1. 响应式计数器

    • 使用Vue.observable创建共享状态

    • 实现增加、减少和重置功能

    • 显示计算属性(计数器平方)

  2. 用户管理系统

    • 动态添加/删除用户

    • 显示用户总数

    • 清空用户功能

  3. 通知系统

    • 显示不同类型(成功、错误、信息)的通知

    • 通知自动消失功能

  4. 主题切换

    • 深色/浅色模式切换

  5. 代码展示

    • 展示Vue.observable的实现代码

技术要点

  1. 使用Vue.observable()创建响应式状态对象

  2. 所有状态变更都通过集中管理的方法进行

  3. 多个组件共享同一状态源

  4. 使用计算属性派生状态

  5. 演示了状态管理的完整生命周期

这个示例可以直接保存为HTML文件并在浏览器中打开运行,无需任何服务器环境。

五、关键注意事项与最佳实践

  1. 修改状态:

    • 直接修改属性: state.count = 5; 这种方式是有效的,因为 state 是响应式的,修改会触发更新。

    • 推荐使用 Actions/Mutations: 强烈建议将所有修改状态的逻辑封装在导出的 actions 方法中。这样做的好处是:

      • 集中管理: 所有状态变更逻辑都在一个地方,易于理解和维护。

      • 可追踪性: 更容易追踪状态是如何被修改的,尤其是在调试时。

      • 潜在扩展性: 如果将来需要添加日志记录、时间旅行调试(虽然 observable 本身不支持,但模式相似)或异步操作,修改 actions 内部即可。

    • 新增/删除属性: Vue 2.x 的响应式系统对对象属性的添加或删除默认无法检测。需要使用 Vue.set(object, propertyName, value) 或 Vue.delete(object, propertyName) 来确保新属性也是响应式的。Vue 3 的 reactive 基于 Proxy 则没有此限制。

  2. 性能考虑:

    • Vue.observable 创建的响应式对象,其性能开销与 Vue 组件 data 中的对象相同。

    • 对于非常大或嵌套非常深的对象,响应式转换可能会有一些初始开销。但在大多数应用场景下,这种开销是可以忽略不计的。

    • 避免将整个庞大应用的状态都塞进一个 observable 对象。它更适合管理特定领域的、规模有限的状态。如果状态变得非常复杂,Vuex 或 Pinia 仍然是更好的选择,它们提供了模块化、开发工具集成等高级特性。

  3. 与 Vuex 的比较:

    特性Vue.observableVuex
    定位轻量级响应式状态创建工具完整的、功能丰富的状态管理库
    复杂度极低,核心 API 只有一个中等,涉及概念 (state, getters, mutations, actions, modules)
    开发工具支持无 (Vue Devtools 能看到状态变化)强大的时间旅行调试、状态快照等
    模块化需自行组织 (JS 模块)内置模块系统 (modules)
    严格模式支持 (strict: true)
    插件系统
    适用场景小型应用、组件间简单共享、工具函数中大型复杂应用、需要高级功能
    异步处理需在 actions 中自行处理原生支持 actions (可异步)
    服务端渲染 (SSR)需自行处理状态共享有较好的 SSR 支持方案
  4. Vue 3 中的变化:
    在 Vue 3 中,Vue.observable API 被重命名为 reactive,并作为 vue 包导出的一个独立函数使用(不再挂载在 Vue 对象上)。它的底层实现也从 Object.defineProperty 换成了更强大的 Proxy,解决了 Vue 2 中无法检测属性添加/删除的限制。

    // Vue 3
    import { reactive } from 'vue';const state = reactive({count: 0
    });
     

    Vue 3 还引入了 ref 用于处理基本类型的响应式,以及 computedwatch 等 Composition API,与 reactive 结合使用可以构建出非常灵活的状态逻辑。

六、实际应用案例

  1. 全局 UI 状态管理:

    • 管理侧边栏的展开/折叠状态 (isSidebarOpen)。

    • 管理全局加载指示器的显示/隐藏 (isLoading)。

    • 管理主题切换 (亮色/暗色模式) (currentTheme)。

    • 管理全局通知/消息条 (notification 对象包含 texttypevisible)。

  2. 表单状态共享:

    • 一个复杂的多步骤表单,每个步骤是独立的组件,但共享同一个表单数据对象 (formData)。observable 状态可以让每个步骤组件实时读写表单数据并保持同步。

  3. 简单的购物车:

    • 管理购物车中的商品列表 (cartItems)。

    • 计算购物车总价 (totalPrice 计算属性可以在 store 中定义,组件直接使用)。

    • 添加商品 (addToCart action)、移除商品 (removeFromCart action)、更新数量 (updateQuantity action)。

  4. 用户偏好设置:

    • 存储用户的语言设置 (language)。

    • 存储用户的时区设置 (timezone)。

    • 存储用户的自定义视图偏好 (viewPreferences 对象)。这些设置可以在不同组件中读取和修改,并持久化到 localStorage

  5. 跨组件实时通信:

    • 简单的实时聊天组件,共享当前消息列表 (messages) 和在线用户列表 (onlineUsers)。

七、总结

Vue.observable (Vue 3 中的 reactive) 是 Vue.js 框架提供的一个强大而基础的工具,它揭示了 Vue 响应式系统的核心能力。通过将一个普通对象转化为响应式对象,它使得状态的变化能够自动驱动依赖该状态的视图更新。

核心价值在于:

  • 轻量级: 无需引入额外的库,API 简单直接。

  • 解决简单状态共享: 完美应对小型应用、组件间简单数据共享、避免 Prop Drilling 的场景。

  • 理解响应式原理: 使用它是深入理解 Vue 响应式工作机制的良好实践。

  • 灵活性: 可以与 JavaScript 模块模式结合,自由构建适合项目需求的状态管理结构。

何时选择 Vue.observable:

  • 你的状态共享需求相对简单,集中在几个属性或小型对象上。

  • 你希望避免引入 Vuex 或 Pinia 的额外概念和复杂度。

  • 项目规模较小,或者只在应用的特定局部需要共享状态。

  • 你需要为一些非组件的工具逻辑添加响应式能力。

何时考虑 Vuex/Pinia:

  • 应用状态变得庞大且复杂。

  • 需要严格的单向数据流、状态变更追踪、时间旅行调试。

  • 需要模块化组织状态和逻辑。

  • 需要处理复杂的异步操作流。

  • 需要更好的服务端渲染 (SSR) 支持。

  • 需要利用丰富的插件生态系统。

最佳实践建议:

  1. 封装 Actions: 始终将修改状态的逻辑封装在函数 (actions) 中,不要直接在组件里随意修改状态属性。这提高了代码的可维护性和可预测性。

  2. 模块化组织: 根据功能域将状态划分到不同的模块文件中。

  3. 注意属性增删 (Vue 2): 在 Vue 2 中,使用 Vue.set 和 Vue.delete 来确保新属性响应式。

  4. 优先计算属性: 在组件中使用计算属性 (computed) 来访问 observable 状态,而不是在模板中写复杂的表达式或在 methods 中频繁访问。

  5. 命名清晰: 给你的状态存储文件和导出的变量 (stateactions) 起清晰、有意义的名字。

总而言之,Vue.observable 是 Vue 开发者工具箱中一件精悍的利器。它巧妙地在框架内置能力和轻量级状态管理之间找到了平衡点,为构建简洁、响应式的小型应用或功能模块提供了优雅的解决方案。理解并善用它,可以让你在合适的场景下写出更简洁、更高效的 Vue 代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/86620.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS设计模式(5): 发布订阅模式

解锁JavaScript发布订阅模式&#xff1a;让代码沟通更优雅 在JavaScript的世界里&#xff0c;我们常常会遇到这样的场景&#xff1a;多个模块之间需要相互通信&#xff0c;但是又不想让它们产生过于紧密的耦合。这时候&#xff0c;发布订阅模式就像一位优雅的信使&#xff0c;…

【电路物联网】SDN架构与工作原理介绍

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;数据结构&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;网络编程等领域UP&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff0…

vscode 保存 js 时会自动格式化,取消设置也不好使

vscode 里的设置搜索 Editor: Format On Save 取消勾选 卸载 Prettier - Code formatter 这个插件后好使了&#xff0c;本来以为是插件的问题&#xff0c;后来发现是工作区设置的问题。 因为我是用 GitHub 下载的工程打开后&#xff0c; vscode 认为是工作区了, 因为 .vscode…

xcode中project.pbxproj点开为空白问题

由于需要修改signing里面的配置&#xff0c;点击了project.pbxproj。但是发现一片空白&#xff0c;如图 以为是配置文件损坏&#xff0c;邮件show in Finder看了一通后没看出什么所以然。并且发现entitlement文件、list文件全都是点开为白&#xff0c;并且没有任何保存 最后发…

JUC并发编程(四)常见模式

目录 一 同步与协调模式 1 保护性暂停模式 2 顺序控制模式 3 生产者消费者模式 4 Balking模式&#xff08;犹豫模式&#xff09; 二 线程管理/生命周期模式 1 两阶段终止模式 一 同步与协调模式 1 保护性暂停模式 一个线程需要等待另一个线程提供特定条件&#xff08;通常是…

Vue 数据代理机制对属性名的要求

Vue 数据代理机制对属性名的要求 在 Vue 的数据代理机制中,属性名需遵循以下关键规则: 1. 禁止以 _ 或 $ 开头 ⚠️ Vue 会跳过代理以 _ 或 $ 开头的属性原因:这些前缀被 Vue 保留用于内部属性(如 _data, _uid, $refs, $el 等)示例:data() {return {count: 1, // ✅…

pdf.js在iOS移动端分页加载优化方案(ios移动端反复刷新加载问题)

背景与问题 在iOS移动端加载大型PDF文件时&#xff0c;由于设备内存限制&#xff0c;经常遇到以下问题&#xff1a; 内存不足导致页面崩溃大文件加载缓慢页面反复重新加载 ##解决方案 采用PDF.js的分页加载策略&#xff0c;实现按需加载当前可视页面及相邻页面&#xff0c;…

【C++】来学习使用set和map吧

各位大佬好&#xff0c;我是落羽&#xff01;一个坚持不断学习进步的大学生。 如果您觉得我的文章有所帮助&#xff0c;欢迎多多互三分享交流&#xff0c;一起学习进步&#xff01; 也欢迎关注我的blog主页: 落羽的落羽 文章目录 一、set和map是什么二、set系列1. set2. mult…

h5st逆向分析

h5st最新5.1版本逆向分析 申明定位h5st生成的位置动态插桩,事半功倍日志分析,十分钟还原算法逻辑申明 本文仅用来记录学习过程以免日后忘了,如有侵权请联系删除。 定位h5st生成的位置 通过关键字“sign”搜索,可以定位到window.PSign.sign(f)这个位置,f参数的值为{ &qu…

湖北理元理律师事务所企业债务优化路径:司法重整中的再生之道

一、企业债务危机的核心矛盾&#xff1a;生存与清偿的博弈 通过分析湖北理元理律师事务所经办的17件企业债务案件&#xff0c;发现共性难题&#xff1a; 债权人要求立即清偿 → 企业需持续经营造血 → 司法程序存在时间差 解决方案&#xff1a;构建“三重防火墙”机制 经…

链家Android面试题及参考答案

目录 请详细解释类加载的过程,包括每一步的具体实现。并说明Android中的dex分包技术及其在热更新中的应用 比较JVM和DVM的区别。在JVM中一个程序崩溃是否可能导致系统崩溃?DVM中呢? 请解释网络IP协议、TCP、UDP、HTTP、HTTPS、Socket的概念,并说明它们之间的区别 请深入…

LeetCode-多语言实现冒泡排序以及算法优化改进

目录 一、冒泡排序算法 二、应用场景/前提条件 &#x1f308; 优点 &#x1f4e2; 缺点 三、经典算法实现并优化改进 方法一&#xff1a;记录最后一次交换位置&#xff0c;下一轮只遍历到该位置 方法二&#xff1a;添加标志位跟踪是否发生交换&#xff0c;无交换则提前终…

JAVA毕业设计227—基于SpringBoot+hadoop+spark+Vue的大数据房屋维修系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于SpringBoothadoopsparkVue的大数据房屋维修系统(源代码数据库)227 一、系统介绍 本项目前后端分离&#xff0c;分为业主、维修人员、管理员三种角色 1、业主&#xff1a; 登…

MADlib —— 基于 SQL 的数据挖掘解决方案(9)—— 数据探索之概率统计

目录 一、概率 1. 概率的定义 2. 概率质量函数与概率密度函数 3. 条件概率 4. 期望值 二、MADlib 的概率相关函数 1. 函数语法 2. 示例 &#xff08;1&#xff09;求标准正态分布下&#xff0c;1 的概率密度函数 &#xff08;2&#xff09;求标准正态分布下&#xff…

耳蜗里的春天

早春的郑州飘着细雨&#xff0c;我牵着女儿小满的手走进市残疾人康复中心时&#xff0c;玻璃门内突然传来一阵清脆的笑声。穿天蓝色毛衣的小女孩戴着粉色耳蜗&#xff0c;正踮脚拍打着墙上的卡通贴画&#xff0c;银色的连接线在她耳后晃动&#xff0c;像一只折翼却仍在起舞的蝴…

OCR(光学字符识别)算法

OCR&#xff08;光学字符识别&#xff09;算法在景区护照阅读器中的应用是核心技术之一&#xff0c;它通过图像处理和机器学习快速提取护照信息&#xff0c;显著提升自动化水平。以下是其具体应用场景、技术实现及优化方向&#xff1a; 一、OCR在护照阅读器中的核心作用 关键信…

html打印合同模板

概述&#xff08;吐槽&#xff09;&#xff1a;记录一个html打印合同模板的功能&#xff0c;技术栈有点杂&#xff0c;千禧年出产老系统的数据库是sqlserver2008&#xff0c;原系统框架是c#&#xff0c;无法二开&#xff0c;因为原系统的合同生成功能出现bug&#xff0c;没有供…

DeepCritic: SFT+RL两阶段训练突破LLM自我监督!显著提升大模型的自我批判能力!!

摘要&#xff1a;随着大型语言模型&#xff08;LLMs&#xff09;的迅速发展&#xff0c;对其输出进行准确反馈和可扩展监督成为一个迫切且关键的问题。利用LLMs作为批评模型以实现自动化监督是一个有前景的解决方案。在本研究中&#xff0c;我们专注于研究并提升LLMs在数学批评…

【深度学习】深度学习中的张量:从多维数组到智能计算单元

✅ 一、n维数组&#xff08;张量&#xff0c;Tensor&#xff09; 1. 定义 张量&#xff08;Tensor&#xff09;是一个通用的n维数组数据结构。 它的维度&#xff08;维数&#xff09;决定了它的形状&#xff0c;例如&#xff1a; 维度名称举例说明0维标量&#xff08;scalar…

以太网MDI信号PCB EMC设计要点

1. PHY侧和RJ45连接器侧通用MDI布局建议 1. MDI差分对保持对称走线&#xff0c;走线上的焊盘封装应一致&#xff0c;焊盘放置位置也应对称。可以减少EMI测试中的模式转换。   2. MDI走线应保持阻抗匹配&#xff0c;从而减少信号线上的反射。   3. MDI走线下需有连续完整的接…