You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3 JSX函数式组件中Ref失效原因及解决方案咨询

Vue3.2 JSX函数式组件内部ref失效问题解析

你遇到的问题:在Vue3.2的JSX函数式组件内部定义的ref无法正常工作,但将ref移到函数外部后就能正常运行,对应代码如下:

// vue3.2 jsx functinal components

import { ref } from 'vue'

// const count = ref(0) // (2) 这里定义可以正常工作

export default function Counter() {
  const count = ref(0) // (1) 这里定义无法正常工作
  return (
    <>
      <div>count: {count.value}</div>
      <button
        onClick={() => {
          count.value++
        }}
      >
        add
      </button>
    </>
  )
}

原因分析

Vue的纯函数式组件本质是一个普通函数,每次组件重新渲染时这个函数都会被完整调用一次:

  • 当count = ref(0)写在函数内部(标注(1)处)时,每次渲染都会生成一个全新的ref实例,之前点击按钮修改的状态会被直接丢弃,下一次渲染又回到初始值0,页面自然不会更新。
  • 把ref定义在函数外部(标注(2)处)时,这个ref实例只会被创建一次,属于模块级的全局变量,所有渲染周期共享同一个状态,修改后状态能被保留,页面也会正常响应更新。

可行解决方案

  • 用<script setup>语法写JSX组件:这是Vue3推荐的组件写法,内部定义的ref会被自动绑定为组件的响应式状态,不会每次渲染重建。示例:
import { ref } from 'vue'

export default defineComponent({
  setup() {
    const count = ref(0)
    return () => (
      <>
        <div>count: {count.value}</div>
        <button onClick={() => count.value++}>add</button>
      </>
    )
  }
})

更简洁的<script setup>+JSX写法:

<script setup lang="jsx">
import { ref } from 'vue'
const count = ref(0)
const render = () => (
  <>
    <div>count: {count.value}</div>
    <button onClick={() => count.value++}>add</button>
  </>
)
</script>
  • 通过闭包保留ref实例:如果一定要用纯函数式组件,可以用立即执行函数创建闭包,让ref被组件函数共享,避免每次渲染重建:
import { ref } from 'vue'

export default (() => {
  const count = ref(0)
  return function Counter() {
    return (
      <>
        <div>count: {count.value}</div>
        <button onClick={() => count.value++}>add</button>
      </>
    )
  }
})()
  • 使用组件状态属性维护:通过组件的props或上下文传递状态(比如配合reactive),但这种方式繁琐,仅适合特殊场景,不推荐作为常规方案。

内容的提问来源于stack exchange,提问作者MurphyChen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 18:36:24