fix(feed): 改用 articlesWithPrompts computed + TransitionGroup 正确联动
问题: 之前用 v-for items + v-show,虽然类型对,但 v-show 元素始终在 DOM,
TransitionGroup 的 leave 动画处理的是 v-for key 移除,而 v-show 元素
不在 v-for 移除路径上 → 提示条几乎瞬间消失(用户看不见)
修法: 抽 articlesWithPrompts = items.filter(hasPrompt) computed
- 只有真有提示条的 article 才进 wrapper v-for
- hide_read 模式下,items.splice 移除 a 时 articlesWithPrompts 也跟着变
- TransitionGroup 对 wrapper 节点触发 leave 动画,跟 NCard 同步
- 没有 v-for+v-if 同元素的 TS warning
- 不会有孤儿 wrapper(过滤基于 items 本身)
This commit is contained in:
@@ -39,6 +39,15 @@ const categoryPromptsByArticle = ref<Map<number, CategoryPromptItem[]>>(new Map(
|
|||||||
const pendingCategory = ref<string | null>(null) // 正在请求"全部已读"的分类(category 名)
|
const pendingCategory = ref<string | null>(null) // 正在请求"全部已读"的分类(category 名)
|
||||||
let categoryPromptTimer: number | null = null
|
let categoryPromptTimer: number | null = null
|
||||||
|
|
||||||
|
// 只渲染"还在 items 里"且"有提示条"的 article 列表(给 TransitionGroup 用作 v-for)
|
||||||
|
// computed 保证响应式
|
||||||
|
// - items 没这条 → 不渲染(孤儿)
|
||||||
|
// - items 有 + Map 也有 → 渲染
|
||||||
|
// - items 有 + Map 没 → 不渲染(用户已 dismiss/确认/超时)
|
||||||
|
const articlesWithPrompts = computed(() =>
|
||||||
|
items.value.filter((a) => (categoryPromptsByArticle.value.get(a.id)?.length ?? 0) > 0)
|
||||||
|
)
|
||||||
|
|
||||||
// 移除某篇文章的所有提示条(8 秒超时 / 确认后 / 过滤变化)
|
// 移除某篇文章的所有提示条(8 秒超时 / 确认后 / 过滤变化)
|
||||||
function clearPromptsForArticle(articleId: number) {
|
function clearPromptsForArticle(articleId: number) {
|
||||||
if (categoryPromptsByArticle.value.has(articleId)) {
|
if (categoryPromptsByArticle.value.has(articleId)) {
|
||||||
@@ -693,14 +702,14 @@ onMounted(async () => {
|
|||||||
</NCard>
|
</NCard>
|
||||||
<!--
|
<!--
|
||||||
该文章对应的分类提示条(per-article 挂载,卡片**下方**):
|
该文章对应的分类提示条(per-article 挂载,卡片**下方**):
|
||||||
- 独立的 v-for 循环,key 用 a.id 跟 NCard 共享,这样 hide_read 模式下
|
- 用 articlesWithPrompts(过滤后只有有提示条的 article)做 v-for
|
||||||
items.splice 移除文章时,提示条会跟 NCard 同步触发 leave 动画
|
- key 用 a.id 跟 NCard 共享(但 NCard 已经在自己的 v-for 里,key 不冲突,
|
||||||
|
因为这是独立的 v-for 节点),hide_read 模式下 items.splice 移除文章时,
|
||||||
|
对应的提示条 wrapper 会从 articlesWithPrompts 移除 → leave 动画
|
||||||
- 内部 NAlert v-for 用 ${a.id}-${category} 作为 key,确保多个 category 时各自独立
|
- 内部 NAlert v-for 用 ${a.id}-${category} 作为 key,确保多个 category 时各自独立
|
||||||
- 用 v-show 而非 v-if:v-for 始终渲染 wrapper,内部 NAlert 按需显示
|
|
||||||
-->
|
-->
|
||||||
<div
|
<div
|
||||||
v-for="a in items"
|
v-for="a in articlesWithPrompts"
|
||||||
v-show="!!categoryPromptsByArticle.get(a.id)?.length"
|
|
||||||
:key="`prompt-wrapper-${a.id}`"
|
:key="`prompt-wrapper-${a.id}`"
|
||||||
class="feed-category-prompt-wrapper"
|
class="feed-category-prompt-wrapper"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user