Vue 列表渲染设计决策表(v-for source)

11 阅读2分钟

使用场景:

  • v-for
  • computed → v-for

一、v-for 数据源设计(最核心)

问题必须满足正确做法错误做法后果
v-for 的 source 初始值是什么?必须可遍历[] / {} / Map()undefined / null / false列表语义无法建立
source 的类型是否稳定?类型不可跃迁[] → [...]undefined → []diff 通道缺失
是否依赖 ?. 比如 v-for = listItem in object?.listobject?.list不能是undefined初始值:object=reactive({list:[]})初始值:object=ref(undefined)列表语义无法建立

二、computed + v-for 决策

场景推荐不推荐原因
computed 作为 v-for source返回 []返回 undefinedundefind会导致未建立列表语义结构
computed 内部判空?. ?? []if (!x) return避免短路,短路会导致v-for source为undefined
computed 首次执行访问完整结构return {list:[]}这样的预定义稳定结构v-for source只会在首次建立列表语义结构,即使source值变化了,也不会再重新建立语义结构
v-for 绑定computedListcomputed?.listv-for source不能依赖?.,因为可能返回undefined,会导致未定义列表结构语义

三、看到v-for检查设计列表

  • v-for 的 source 第一次 render 是不是数组 / 对象?

  • 是否存在 undefined → array 的路径?

  • 是否用了 ?. 直接喂给 v-for?

  • computed 是否可能 return 非遍历值?

四、可以反复使用的代码模版

const state = reactive({
  list: [],
  loading: true
})

onMounted(async () => {
  state.list = await fetchList()
  state.loading = false
})
<template>
  <div v-if="state.loading">loading...</div>
  <div v-else>
    <div v-for="item in state.list" :key="item.id" />
  </div>
</template>

五、关于v-for的统一心智模型

你可以把 Vue 渲染分成三层:

① 编译期(决定结构)
② 首次 render(建立语义)
③ diff 更新(只做比较)

v-for 的“可遍历语义”只在第 ② 步建立一次

如果你在第 ② 步给了:

  • undefined
  • null
  • false

👉 后面改不回来了,即使v-for source变了也不会重新建立

结果:列表一定始终渲染不出来

编译期报错的后果

如果在编译期v-for source = souceObject.property,而且source初始值为null,那么必然报错Can not read property of null (reading property),编译期报错会导致白屏