Vue 可组合范围界定问题
Vue composable scoping issue
我们将 Vue 2 与 Vue Composition API 结合使用,我们正在尝试创建一个可组合的应用程序首选项:
// useApplicationPreferences.ts
import { ref, watch } from '@vue/composition-api'
import { useSetDarkModeMutation, useViewerQuery } from 'src/graphql/generated/operations'
const darkMode = ref(false) // global scope
export const useApplicationPreferences = () => {
const { mutate: darkModeMutation } = useSetDarkModeMutation(() => ({
variables: {
darkMode: darkMode.value,
},
}))
watch(darkMode, async (newDarkMode) => {
console.log('darkMode: ', newDarkMode)
await darkModeMutation()
})
return { darkMode }
}
此代码运行良好,但当在同时呈现的两个组件中使用可组合项时,我们可以看到 watch
已被触发两次。这很容易通过将 watch
函数移动到全局范围(函数外部)来解决。
然而,问题是我们不能使用darkModeMutation
。这个 graphql 突变不能移动到函数之外的全局范围,如果我们这样做,页面甚至不会被渲染。
目标是让 darkMode
在许多地方可用,并且当 darkMode
ref 的值发生变化时,突变只会触发一次。如何实现?
通过创建仅在需要时 watch
启动的可调用函数解决了该问题(即仅在应用程序中的某处启动一次)。
// useApplicationPreferences.ts
import { ref, watch } from '@vue/composition-api'
import { useSetDarkModeMutation, useViewerQuery } from 'src/graphql/generated/operations'
const darkMode = ref(false) // global scope
export const useApplicationPreferences = () => {
const { mutate: darkModeMutation } = useSetDarkModeMutation(() => ({
variables: {
darkMode: darkMode.value,
},
}))
const startWatch = () => {
watch(darkMode, async (newDarkMode) => {
await darkModeMutation()
})
}
return { darkMode, startWatch }
}
可以在MainLayout.vue
中调用一次:
// MainLayout.vue
import { defineComponent } from '@vue/composition-api'
import { useApplicationPreferences } from 'useApplicationPreferences'
export default defineComponent({
setup() {
const { startWatch } = useApplicationPreferences()
startWatch()
},
})
然后所有其他组件可以根据需要简单地使用 (get/set) darkMode
引用,而 watch
仅 运行 一次。
// Settings.vue
import { defineComponent } from '@vue/composition-api'
import { useApplicationPreferences } from 'useApplicationPreferences'
export default defineComponent({
setup() {
const { darkMode } = useApplicationPreferences()
return { darkMode }
},
})
我们将 Vue 2 与 Vue Composition API 结合使用,我们正在尝试创建一个可组合的应用程序首选项:
// useApplicationPreferences.ts
import { ref, watch } from '@vue/composition-api'
import { useSetDarkModeMutation, useViewerQuery } from 'src/graphql/generated/operations'
const darkMode = ref(false) // global scope
export const useApplicationPreferences = () => {
const { mutate: darkModeMutation } = useSetDarkModeMutation(() => ({
variables: {
darkMode: darkMode.value,
},
}))
watch(darkMode, async (newDarkMode) => {
console.log('darkMode: ', newDarkMode)
await darkModeMutation()
})
return { darkMode }
}
此代码运行良好,但当在同时呈现的两个组件中使用可组合项时,我们可以看到 watch
已被触发两次。这很容易通过将 watch
函数移动到全局范围(函数外部)来解决。
然而,问题是我们不能使用darkModeMutation
。这个 graphql 突变不能移动到函数之外的全局范围,如果我们这样做,页面甚至不会被渲染。
目标是让 darkMode
在许多地方可用,并且当 darkMode
ref 的值发生变化时,突变只会触发一次。如何实现?
通过创建仅在需要时 watch
启动的可调用函数解决了该问题(即仅在应用程序中的某处启动一次)。
// useApplicationPreferences.ts
import { ref, watch } from '@vue/composition-api'
import { useSetDarkModeMutation, useViewerQuery } from 'src/graphql/generated/operations'
const darkMode = ref(false) // global scope
export const useApplicationPreferences = () => {
const { mutate: darkModeMutation } = useSetDarkModeMutation(() => ({
variables: {
darkMode: darkMode.value,
},
}))
const startWatch = () => {
watch(darkMode, async (newDarkMode) => {
await darkModeMutation()
})
}
return { darkMode, startWatch }
}
可以在MainLayout.vue
中调用一次:
// MainLayout.vue
import { defineComponent } from '@vue/composition-api'
import { useApplicationPreferences } from 'useApplicationPreferences'
export default defineComponent({
setup() {
const { startWatch } = useApplicationPreferences()
startWatch()
},
})
然后所有其他组件可以根据需要简单地使用 (get/set) darkMode
引用,而 watch
仅 运行 一次。
// Settings.vue
import { defineComponent } from '@vue/composition-api'
import { useApplicationPreferences } from 'useApplicationPreferences'
export default defineComponent({
setup() {
const { darkMode } = useApplicationPreferences()
return { darkMode }
},
})