Vue 3 组合 API - ref 在 npm 包中不起作用



我有这个非常简单的 Vue 3 组件。一切正常。value每 0.5 秒更改一次(正在调用控制台.log),浏览器中的值也每 0.5 秒更改一次。

<template>
<pre>value: {{ value }}</pre>
</template>
<script>
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup () {
const value = ref(false)
setInterval(() => {
value.value = !value.value
console.log('value changed to ', value.value)
}, 500)
return { value }
}
})
</script>

这是我的问题...如果我创建自己的 npm 包,假设使用以下代码进行@my/package

import { ref } from 'vue'
const value = ref(false)
setInterval(() => {
value.value = !value.value
console.log('value changed to ', value.value)
}, 500)
export { value }

然后我在 Vue 3 组件中使用我的包,如下所示:

<template>
<pre>value: {{ value }}</pre>
</template>
<script>
import { defineComponent } from 'vue'
import { value } from '@my/package'
export default defineComponent({
setup () {
return { value }
}
})
</script>

那就行不通了。确切地说,console.log每 0.5 秒记录一次不同的值(truefalse),但我的浏览器仍然只呈现初始false值。

控制台中没有错误。似乎我的"反应性"以某种方式神奇地拒绝工作,如果ref()在我的 Vue 应用程序之外调用。

这也不适用于reactive()和Vuex。我想创建一个 npm 包,它将公开一些反应式引用(由ref()创建),我的 Vue 应用程序将import这些值。在这种情况下如何保持反应性?我在这里错过了什么?

编辑:我刚刚发现,如果我将ref从我的 Vue 应用程序传递到 npm 包函数,它确实可以正常工作。示例代码:

import { defineComponent, ref } from 'vue'
import { createValue } from '@my/package'
export default defineComponent({
setup () {
// Notice Im passing the ref to the createValue function
const value = createValue(ref)
return { value }
}
})

和我的@my/package代码:

export function createValue (ref) {
const value = ref(false)
setInterval(() => {
value.value = !value.value
console.log('value changed to ', value.value)
}, 500)
return value
}

所以看起来我的 Vue 应用程序中的ref和我的包中的ref并不相同。但是为什么?

编辑 2:我像window.ref1 = ref一样在 Vue 应用程序中保存了我的ref,然后我像window.ref2 = ref一样将我的ref保存在 npm 包中。当我运行window.ref1 === window.ref2它是错误的。所以我在 Vue 应用程序中的ref与我在 npm 包中的ref不同。我使用以下代码导入两者:

import { ref } from 'vue'

编辑3:所以真正的问题是我有两个单独的Vue npm包。一个在/node_modules/,第二个在/node_modules/@my/package/node_modules.当然,每个 Vue 都有自己的ref。我使用对等依赖解决了这个问题。

所以我找到了解决方案。问题是我使用$ yarn link命令链接了@my/package,所以我有两个vue副本。因此,当我在 Vue 应用程序中导入ref时,它的功能与在 @my/package 中导入的ref不同。

这里最简单的解决方案可能只是简单地克隆 Vue 存储库并在 Vue 应用程序和包中运行$ yarn link vue

我建议在可组合函数中定义该代码,例如:

import { ref,onMounted } from 'vue'
export default function useValue(){
const value = ref(false)
onMounted(()=>{
setInterval(() => {
value.value = !value.value
console.log('value changed to ', value.value)
}, 500)
})
return {value}
}

然后像这样使用它:


<template>
<pre>value: {{ value }}</pre>
</template>
<script>
import { defineComponent } from 'vue'
import useValue from '@my/package'
export default defineComponent({
setup () {
const { value} =useValue();
return { value }
}
})
</script>

如果您在另一个 Vue 应用程序中将一个 Vue 应用程序用作 NPM 包,并且您遇到应用程序反应停止工作的问题,@mspiderv提到的建议当然会有所帮助(他们肯定把我送到了正确的方向)。

最终完全解决我的问题的是将其添加到两个 Vue 应用程序的 webpack 配置中(主应用程序和通过 NPM 包提供的应用程序):

resolve: {
alias: {
'vue$': path.resolve(__dirname, 'node_modules/vue')
}
}

这是我找到此解决方案的地方:https://github.com/vuejs/core/issues/1503

只是在这里提到它,以防它帮助其他人或以更好的方式为@mspiderv问题提供更理想的解决方案。

最新更新