Star 按钮点错了:隐藏副本 DOM 与可见 DOM 的状态分裂

举报
yd_216677863 发表于 2026/11/10 08:52:53 2026/11/10
【摘要】 同一个按钮在页面上存在两份,class 相同、文本相同,只有宽高不同。点错那份,本地状态会变,请求不会发。本文给出判定与校验方法。

一次自动化操作里,同一个 Star 按钮我点了两次:第一次页面上的文字变成了 Starred,可仓库的星标数没动;第二次才真正生效。两次点击的目标元素 class 完全一样,区别只在一个数字:getBoundingClientRect().width,一次是 25,一次是 0。

现象

脚本按 .status-btn__text 取元素,用 find() 拿到第一个文本含 Star 的节点,派发 pointerdown / mousedown / pointerup / mouseup / click 五连事件。返回之后回读 textContent,变成 Starred,看起来成功。可页面主区域仍然写着 Star 118,星标数没有任何变化。

原因

这个页面的头部渲染了两份操作区:一份给宽屏,一份给窄屏,都用 repo-action-group--star 包裹,内部按钮的结构相同、class 相同。宽屏那份被 CSS 隐藏,但它仍然留在 DOM 里,所以 querySelector 能选中它。

在被隐藏的副本上派发事件,前端框架照样改了它的本地状态,这就是文本变 Starred 的来源;而提交网络请求的那层逻辑挂在可见节点上,或者被隐藏容器的 display:none 短路了,请求根本没发出去。

判定方法

选中元素之后先算一次矩形,宽高为 0 的直接丢弃,再做文本匹配:

const visible = [...document.querySelectorAll(".status-btn__text")]
  .filter(el => el.getBoundingClientRect().width > 0);

这样拿到的一定是真正占据布局的那个节点,派发事件才会走到提交逻辑。点完再回读一次宽高与文本,两个都变了才算走通。

校验要看服务端渲染的量

只回读 textContent 判断点击是否成功并不可靠,它反映的是本地状态,不等于服务端已受理。稳的校验是回读服务端渲染的计数:星标数、点赞数、收藏数、评论数,数字变了才算数。

还有一条辅助线索是 class:成功之后节点会从 status-btn is-no-wrapper 变成 status-btn starred is-no-wrapper。class 变了但计数没变,就是本地状态改了、请求没走,正好对应隐藏副本这种情况。

小结

同类问题不止出现在星标按钮上。凡是响应式布局会给同一功能渲染多份节点的页面,包括移动端与桌面端各一份、折叠区里一份、弹层里一份,用选择器批量取第一个都可能踩到隐藏副本。三个动作可以固定下来:取节点先过滤宽高,派发事件后回读 class,最后用服务端计数收口。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。