如何在 Vue 生态系统之外使用 Vue 3 响应式对象

发布于 2025-01-15 22:26:48 字数 680 浏览 1 评论 0原文

我试图在微前端应用程序中传递这样创建的全局状态。但问题是我必须以某种方式“观察”更改,以便在 React 应用程序中设置 State。

globalState.js

import { reactive } from 'vue'

const globalState = reactive({
  counter: 0
})

export default globalState

在 Vue 微前端中,我这样做并且工作正常

import { createApp } from 'vue'
import App from './App.vue'

export default (rootEl, globalState) => {
  const app = createApp(App)
  app.config.globalProperties.globalState = globalState
  app.mount(rootEl)
}

但是在 React 应用程序中我正确地传递了引用,但是当计数器值发生变化时,我必须以某种方式检测它并调用 setState 以便重新渲染更改。问题是我如何观察 Vue 生态系统之外的反应式对象引用的变化。

I'm trying to pass global state created like this in micro front end applications. But the problem is that I have to "watch" for changes somehow in order to setState for example in a React app.

globalState.js

import { reactive } from 'vue'

const globalState = reactive({
  counter: 0
})

export default globalState

In Vue micro front ends im doing this and it is working fine

import { createApp } from 'vue'
import App from './App.vue'

export default (rootEl, globalState) => {
  const app = createApp(App)
  app.config.globalProperties.globalState = globalState
  app.mount(rootEl)
}

However in a React app I pass the reference correctly but when counter value changes I have to somehow detect it and call setState in order to rerender the change. The Question is how can I watch for changes of this reactive object reference outside Vue ecosystem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清风夜微凉 2025-01-22 22:26:48

Reactivity API 可作为独立库使用(与 vue package) 可以在 Vue 上下文之外使用。

@vue/reactivity 包含 reactive()/ref()。并且 @vue-reactivity/watch 包括watch()/watchEffect()

例如,您可以使用 watchEffect (或 watch)来记录 globalState.counter 的新值并将其显示在页面:

// main.js
import { watchEffect } from '@vue-reactivity/watch'
import globalState from './globalState'

watchEffect(() => {
  console.log('counter', globalState.counter)
  document.querySelector('#count').innerHTML = globalState.counter
})
// globalState.js
import { reactive } from '@vue/reactivity'

const globalState = reactive({
  counter: 0
})

export default globalState

演示 1

在 React 应用程序中,您可以使用watch 记录 globalState.counter 的新值,然后调用组件的 setState() 来重新渲染组件:

import { useState, useEffect } from 'react'
import { watch } from '@vue-reactivity/watch'
import globalState from './globalState'
import GlobalCounterButton from './GlobalCounterButton'

function App() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    const unwatch = watch(
      () => globalState.counter,
      (newValue, oldValue) => {
        if (newValue !== oldValue) {
          console.log('counter', newValue)
          setCount(newValue)
        }
      }
    )
    return () => unwatch()
  })

  return (
    <div>
      <GlobalCounterButton />
      <h2>count is: {count}</h2>
    </div>
  )
}

export default App

演示 2

The Reactivity API is available as standalone libraries (separate from the vue package) that can be used outside the context of Vue.

@vue/reactivity includes reactive()/ref(). And @vue-reactivity/watch includes watch()/watchEffect().

For example, you could use a watchEffect (or watch) to log the new value of globalState.counter and display it in an element on the page:

// main.js
import { watchEffect } from '@vue-reactivity/watch'
import globalState from './globalState'

watchEffect(() => {
  console.log('counter', globalState.counter)
  document.querySelector('#count').innerHTML = globalState.counter
})
// globalState.js
import { reactive } from '@vue/reactivity'

const globalState = reactive({
  counter: 0
})

export default globalState

demo 1

In a React app, you could use a watch to log the new value of globalState.counter and then call a component's setState() to re-render the component:

import { useState, useEffect } from 'react'
import { watch } from '@vue-reactivity/watch'
import globalState from './globalState'
import GlobalCounterButton from './GlobalCounterButton'

function App() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    const unwatch = watch(
      () => globalState.counter,
      (newValue, oldValue) => {
        if (newValue !== oldValue) {
          console.log('counter', newValue)
          setCount(newValue)
        }
      }
    )
    return () => unwatch()
  })

  return (
    <div>
      <GlobalCounterButton />
      <h2>count is: {count}</h2>
    </div>
  )
}

export default App

demo 2

分开我的手 2025-01-22 22:26:48

最新版本的 @vue/reactivity 不导出 watchwatchEffect API,因此此处标记的答案不再起作用。

相反,您将使用 effect函数,其作用与 watchEffect 类似,但不返回取消订阅函数。您将使用提供的 stop函数并传递effect的返回值。

import { useState, useEffect } from 'react'
import { effect, stop } from '@vue-reactivity'
import globalState from './globalState'
import GlobalCounterButton from './GlobalCounterButton'

function App() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    const runner = effect(() => {
      setCount(globalState.counter)
    })
    return () => stop(runner)
  })

  return (
    <div>
      <GlobalCounterButton />
      <h2>count is: {count}</h2>
    </div>
  )
}

The latest versions of @vue/reactivity do not export the watch and watchEffect APIs, so the marked answer here does not work anymore.

Instead, you will use the effect function, which acts similarly to watchEffect but does not return an unsubscribe function. You'll use the provided stop function and pass the returned value of effect.

import { useState, useEffect } from 'react'
import { effect, stop } from '@vue-reactivity'
import globalState from './globalState'
import GlobalCounterButton from './GlobalCounterButton'

function App() {
  const [count, setCount] = useState(0)

  useEffect(() => {
    const runner = effect(() => {
      setCount(globalState.counter)
    })
    return () => stop(runner)
  })

  return (
    <div>
      <GlobalCounterButton />
      <h2>count is: {count}</h2>
    </div>
  )
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文