- API 路由统一: 移除 /api/h5/,统一 /api/pms/ 入口 - 二进制改名: api-server -> pms-api(与服务名一致) - nginx: 合并 /api/ + /pms/api/ 为 /api/pms/ - 新增 docs/API.md 接口文档 - 后端: CabinetDetail 增加 rssi/pow_fail/address/soc 等字段 - Redis 管道批量读取仓体实时数据(SOC/电压/电流/功率) - DB: 所有 TIMESTAMP 列改为 DATETIME(修复类型不匹配) - 用户管理: 新增创建时间/修改时间列,状态改用 Switch - 角色管理/用户管理: 操作按钮改为图标 - PC 设备详情: 基本信息补全 RSSI/ICCID/电源/地址 - PC 卡片: 通道统计改用 Lucide 图标,颜色统一 - PC 二维码: canvas 渲染,含编号文字,支持右键下载 - H5: 按 uni-app 规范修正导航(navigateTo 替代 reLaunch) - H5: 详情页加返回导航条 - H5: 扫码支持摄像头(jsQR)+ ?id= 参数 - H5: 底部 tabBar 在所有页面常显 - H5: 首页统计改为 6 项(设备/通道/空闲/充电/充满/故障) - H5: 下拉刷新 / 上拉加载 - 产品首页: 添加业务联系 - 文档: 清理过时文件,补充缺失规范章节
4.2 KiB
4.2 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| defineModel Value Changes Apply After Next Tick | MEDIUM | Reading model.value immediately after setting it returns the old value, not the new one | gotcha |
|
defineModel Value Changes Apply After Next Tick
Impact: MEDIUM - When you assign a new value to a defineModel() ref, the change doesn't take effect immediately. Reading model.value right after assignment still returns the previous value. The new value is only available after Vue's next tick.
This can cause bugs when you need to perform operations with the updated value immediately after changing it.
Task Checklist
- Don't read model.value immediately after setting it expecting the new value
- Use the value you assigned directly instead of re-reading from model
- Use nextTick() if you must read the updated value after assignment
- Consider batching related updates together
Incorrect - Expecting immediate value update:
<script setup>
const model = defineModel<string>()
function updateAndLog() {
model.value = 'new value'
// WRONG: This still logs the OLD value!
console.log(model.value) // Logs previous value, not 'new value'
// WRONG: Computation uses stale value
const length = model.value.length // Length of OLD value
// WRONG: Conditional check on stale value
if (model.value === 'new value') {
// This block may not execute!
doSomething()
}
}
</script>
Correct - Use the value directly:
<script setup>
const model = defineModel<string>()
function updateAndLog() {
const newValue = 'new value'
model.value = newValue
// CORRECT: Use the value you just assigned
console.log(newValue) // Logs 'new value'
// CORRECT: Compute from the known value
const length = newValue.length
// CORRECT: Check the known value
if (newValue === 'new value') {
doSomething()
}
}
</script>
Alternative - Use nextTick for deferred operations:
<script setup>
import { nextTick } from 'vue'
const model = defineModel<string>()
async function updateAndProcess() {
model.value = 'new value'
// Wait for Vue to apply the update
await nextTick()
// NOW model.value reflects the new value
console.log(model.value) // 'new value'
processUpdatedValue(model.value)
}
// Or using callback style
function updateWithCallback() {
model.value = 'new value'
nextTick(() => {
// Safe to read updated value here
console.log(model.value) // 'new value'
})
}
</script>
Why This Happens
defineModel uses Vue's internal synchronization mechanism (watchSyncEffect) to sync with the parent. When you assign to model.value:
- The local ref updates
- An
update:modelValueevent is emitted to parent - Parent updates its ref
- Vue syncs back to child in the next tick
During this cycle, the child's local value briefly differs from what's been committed.
Pattern: Object Updates with Immediate Access
<script setup>
import { nextTick } from 'vue'
const model = defineModel<{ name: string; validated: boolean }>()
async function validateAndUpdate(newName: string) {
// Build the new object
const updated = {
...model.value,
name: newName,
validated: true
}
// Assign to model
model.value = updated
// Use 'updated' for immediate operations, not model.value
saveToServer(updated) // CORRECT: Use local reference
// If you need model.value specifically (e.g., for DOM sync):
await nextTick()
focusValidatedField() // Now safe to assume DOM updated
}
</script>
Watch Callbacks Also See Updated Values
<script setup>
import { watch } from 'vue'
const model = defineModel<string>()
// Watch callback receives the new value
watch(model, (newValue, oldValue) => {
// 'newValue' is reliable here
console.log('Changed from', oldValue, 'to', newValue)
})
function update() {
model.value = 'new value'
// watch callback will fire with correct 'new value'
}
</script>