我想创建用 TypeScript 编写的可重用包装函数,以通过使用合成函数来触发吐司通知,如Vue 3.0的当前规范:Composition API RFC。
此示例使用BootstrapVue v2.0吐司组件。在Vue 2中,可以通过this.$bvToast
Vue组件实例注入在根上下文中进行调用:
this.$bvToast.toast('Error happened', {
title: 'Oh no',
variant: 'danger'
});
类似于服务的合成功能看起来像这样:
// File: @/util/notify.ts
export function useNotify() {
const notifyError = (title: string, msg: string) => {
// How to access context.root as in a function component, without passing it to this function?
context.root.$bvToast.toast(msg, {
title,
variant: 'danger'
});
};
return { notifyError};
}
export default useNotify;
并且将非常像这样使用:
// Use in your functional component:
import { createComponent } from '@vue/composition-api';
import { useNotify} from '@/util/notify';
export default createComponent({
name: 'MyFailingComponent',
setup() {
const { notifyError } = useNotify();
notifyError('Request error', 'There was an error processing your request, please try again later.');
return {};
}
});
答案 0 :(得分:5)
还有:
import { getCurrentInstance } from 'vue' // or from '@vue/composition-api'
这将从此方法获取调用组件的root
上下文。
const root = getCurrentInstance(); // same as ctx.root in component
答案 1 :(得分:2)
您可能最终将上下文传递给每个可组合对象,因为它们的依赖关系可能需要上下文本身。
有另一种解决方案,可以提供根实例,而无需将其传递给您拥有的每个可组合对象。这使得它们在组件中的使用更加容易:
您可以创建通用的useRoot
可组合文件,并使用Vue的“提供/插入”功能来实现它:
// File: @/components/Root.js
// This is the app root
import useRoot from '@/composables/useRoot'
export default {
setup(props, context) {
const { provideRoot } = useRoot()
provideRoot(context.root)
}
}
// File: @/composables/useFancyStuff
// This is your composable (no arguments needed!)
import useRoot from '@/composables/useRoot'
export default function useNavigation() {
const { injectRoot } = useRoot()
const { $router } = injectRoot() // if you want to use the router
$router.push('/')
}
// File: @/composables/useRoot
// The implementation
import { provide, inject } from '@vue/composition-api'
const ProviderSymbol = Symbol()
export default function useRoot() {
const provideRoot = root => provide(ProviderSymbol, root)
const injectRoot = () => inject(ProviderSymbol)
return {
provideRoot,
injectRoot
}
}
答案 2 :(得分:1)
好吧,我很快在同一RFC站点上找到了一个正确的例子。但是决定在这里分享我的例子。
为了清晰起见,我假设RFC网站目前不在TypeScript中包含示例。随着这种新的Vue 3.0组件和组合功能(替代Mixins)的编写方式需要一些习惯。
答案:在将所需的部分分解为组件代码时,可以将上下文对象直接传递给composition函数。
// File: @/util/notify.ts
import { SetupContext } from '@vue/composition-api';
export function useNotify(context: SetupContext) {
const notifyError = (title: string, msg: string) => {
context.root.$bvToast.toast(msg, {
title,
variant: 'danger'
});
};
return { notifyError};
}
export default useNotify;
// Use in your functional component:
import { createComponent, SetupContext } from '@vue/composition-api';
import { useNotify} from '@/util/notify';
export default createComponent({
name: 'MyFailingComponent',
setup(props: any, context: SetupContext) {
const { notifyError } = useNotify(context);
notifyError('Request error', 'There was an error processing your request, please try again later.');
return {};
}
});
在将多个函数参数作为对象传递时,与使用具有复杂对象分解功能的TypeScript类型相同:
// File: @/util/notify.ts
import { SetupContext } from '@vue/composition-api';
export function useNotify({ context, defaultTitle = 'Hey!' }: { context: SetupContext, defaultTitle?: string }) {
const notifyError = (msg: string, title?: string) => {
context.root.$bvToast.toast(msg, {
title: title || defaultTitle,
variant: 'danger',
});
};
return {
notifyError,
};
}
export default useNotify;
// Usage like:
const { notifyError } = useNotify({ context });
// Or
const { notifyError } = useNotify({ context, defaultTitle: 'Hey there' });
语法整洁,Vue社区做得很好!