【问题标题】:Globally Accessible Component Instance全局可访问的组件实例
【发布时间】:2020-09-29 13:18:28
【问题描述】:

在我们使用 Vue 2.x 的生产应用程序中,我们有一个 toast 组件。这个 toast 组件通过插件(下面的代码)安装一次,然后添加到 Vue 原型中,使其在每个组件实例中都可以访问。

这让生活变得更轻松,而不必在我们使用的任何地方添加吐司。

Vue 2.x 插件

export default {
install(vue: any, _: any) {
    const root = new Vue({ render: (createElement) => createElement(Toast) });
    root.$mount(document.body.appendChild(document.createElement("div")));

    const toastInstance: Toast = root.$children[0] as Toast;
    vue.prototype.$toast = {
        show: (state: ToastState, text: string) => { toastInstance.show(state, text); },
        hide: () => { toastInstance.hide(); }
    };
}

然后可以在任何组件中调用,例如:

this.$toast.show(ToastStates.SUCCESS, "Some success message");

我最近开始了另一个项目,想做类似的事情,除了使用 Vue 3。因为我们无法访问 setup 函数中的 this,所以我无法使用与以前相同的方法.

我一直在研究一些事情,并找到了一些方法,但没有一个是确定的最佳实践。

提供/注入: 这似乎是最有希望的,我可以在哪里使用

export const appInstance = createApp(App);

然后

appInstance.provide("toast", toastComponentInstance)

然后我可以将其注入任何组件。这样做的问题是,要使其在每个组件中可用,它需要附加到尚未创建的初始应用程序实例。也许我可以手动挂载它并传递它(但这似乎是一种黑客行为)。

组成: 我也在这里查看了这个问题:How to access root context from a composition function in Vue Composition API / Vue 3.0 + TypeScript? 但没有发现它很有用,我不得不做所有类型的黑客才能真正获得对插件的访问权限。总代码如下..

export function useToast() {

    const root = getCurrentInstance();

    const openToast: (options: ToastOptions) => void = (options: ToastOptions) => {
        root.ctz.$toast.open(options);
    }

    const closeToast: () => void = () => {
        root.ctx.$toast.close();
    }

    return {
        openToast,
        closeToast
    }
}

我还有其他想法,但它们似乎有点牵强。热衷于听取人们对其他解决方案的想法。我只想要一个简单的方法来拥有一个 toast 实例,我可以调用两个函数来在我想要的时间和地点打开/关闭它。

【问题讨论】:

  • 只是一般的观察,您似乎在与“Vue 方式”作斗争。与其接触子级来执行一个方法……为什么不在父级中提供一个简单的状态变量,然后对下游状态的变化做出反应?

标签: vue.js vuejs3 vue-composition-api


【解决方案1】:

这大概就是我的做法......

我会使用 Composition API,因为它使内部传递变得容易

(为简单起见,我使用弹出窗口而不是 toast)

myPopup.vue


// internal
const popupMessage = Vue.ref('');
const popupVisible = Vue.ref(true);

// external
export const popUpShow = function(message) {
    popupMessage.value = message
  popupVisible.value = true
}
export const popupHide = function () {
    popupVisible.value = false
}

export default {
    setup(){
        return {
        popupMessage, popupVisible, popupHide
    }   
  }
}

某些组件、任何地方、组合或基于类...

import { popUpShow } from "./myPopup";

export default {
  methods: {
    myTriggeredEvent() {
      popUpShow("I am your Liter")
    }
  }
}

通过公开popUpShow,它充当单例,您可以从任何地方导入它,而不必担心上下文。

使用这种设置/架构的缺点是它不能很好地扩展。如果您的架构达到一定大小,并且您有多个来自不同来源的触发器,组件需要具有复杂的逻辑来处理其状态(尽管在此示例中不太可能),就会出现问题。在这种情况下,一个托管的全局存储,即。 Vuex,可能是更好的选择。

【讨论】:

    猜你喜欢
    • 2020-06-13
    • 2021-05-22
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多