【问题标题】:How to access Vue Instance from mixins?如何从 mixins 访问 Vue 实例?
【发布时间】:2019-04-04 07:34:44
【问题描述】:

我想实现这种将this.$store.value 分配给本地数据的逻辑。 例如,我在 pages/index.vue 中就是这样做的。

method: {
  this.value = this.$store.value
}

我想把它写成 mixins,因为我实际上有其他逻辑围绕它,并且我使用了一些页面。

但是,我不知道如何从 mixins 访问 this(VueInstnce)?

【问题讨论】:

    标签: vue.js vuex nuxt.js


    【解决方案1】:

    好的,所以我不知道这是否被认为是一种不好的做法,但我设法完成了单向数据传输没有event bus。

    我正在使用 vuejs 3 和 composition api。 要求:所有组件都应该能够访问显示在整个应用顶部的全局单例组件。

    plugin.js - 这里我们使用mixin 中的created 事件来获取组件实例的引用。在下面的 example 中,我总是只有 1 个 tracker 组件实例(全局弹出窗口)。 如果您有其他更复杂的场景,我建议您改用事件总线解决方案。

    import Tracker from "@/plugins/ProgressTracker/components/Tracker.vue";
    
    export default {
      install(app, params = {}) {
        app.component("tracker", Tracker);
    
        let instance = undefined;
    
        app.mixin({
          created() {
            if (this.$options.name === "ProgressTrackerPopup") {
              instance = this;
            }
          },
        });
    
        const progressTracker = () => {
          //
        };
    
        progressTracker.show = function () {
          instance.show();
        };
    
        app.config.globalProperties.$progressTracker = progressTracker;
      },
    };
    

    useProgressTracker.js - 公开show 方法的全局可重用组合函数

    import { ref, computed, getCurrentInstance } from "vue";
    
    export default function useProgressTracker() {
      const internalInstance = getCurrentInstance();
      const progressTracker = internalInstance.appContext.config.globalProperties.$progressTracker;
    
      const show = () => {
        progressTracker.show();
      };
    
      return {
        show,
      };
    }
    

    Tracker.vue - 我们需要从任何其他组件(它的方法)全局访问的组件。name 很重要。 应设置它以使mixin 能够能够检测到您的组件创建

    <template>
      <div class="onTop" v-if="isShow">test</div>
    </template>
    <script>
    import { ref } from "vue";
    
    export default {
      name: "ProgressTrackerPopup",
      setup() {
        var isShow = ref(false);
    
        const show = () => {
          isShow.value = true;
        };
    
        return {
          isShow,
          show,
        };
      },
    };
    </script>
    <style scoped>
    .onTop{
      position: absolute;
      z-index: 1999;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: #0000004f;
    }
    </style>
    

    就是这样。不要忘记注册插件:

    import ProgressTracker from "@/plugins/plugin.js";
    // ..
    app.use(ProgressTracker, {});
    

    现在,当您希望显示弹出窗口时,您调用:

    // <tracker />
    
    import useProgressTracker from "@/plugins/ProgressTracker/use/useProgressTracker.js";
    
    const tracker = useProgressTracker();
    tracker.show();
    

    最后一行代码基本上会调用全局组件实例本身的show 方法!而如果您使用 event bus 代替 - 您将订阅目标组件本身的 pop 事件。

    我发现当您不想处理事件总线并且情况相对简单(您始终只有 1 个全局实例)时,此解决方案很有用。不过,您当然可以使用实例数组并按顺序循环调用它们的方法.. :)

    【讨论】:

      【解决方案2】:

      Vue 不支持,因为 mixin 在组件代码之前运行, 然后 mixin 被 Vue 绑定(合并)到组件实例,因此很容易从组件/实例范围访问 mixin,但反之则不然。

      为了满足您的需求,我认为 mixin 方法(例如 created)应该(例如)以对组件实例的给定引用作为参数运行,但事实并非如此。

      但是,如果您重新组织代码以运行 instance.created 所需的内容 可以访问那里的方法和 mixin 的数据并自行传递参数:

      var mixin = {
        data: {mixin: 'mixin'},
        created: function () {
          console.log('mixin hook called')
        },
        methods: { test: function(arg){console.log(arg); } }
      };
      
      vm=new Vue({
        data: {component: 'component'},
        mixins: [mixin],
        created: function () {
          console.log('called hook of ' + this.component + ' and accessing ' + this.mixin)
        },
      });
      
      vm.test(vm.mixin);
      vm.test(vm.component);  // no problem to run mixin's method with component's data
      
      > mixin hook called
      > called hook of component and accessing mixin
      > mixin
      > component
      

      【讨论】:

        猜你喜欢
        • 2018-06-13
        • 2018-09-08
        • 2017-08-22
        • 2020-07-14
        • 2020-06-14
        • 1970-01-01
        • 1970-01-01
        • 2021-09-02
        相关资源
        最近更新 更多