【发布时间】:2019-04-04 07:34:44
【问题描述】:
我想实现这种将this.$store.value 分配给本地数据的逻辑。
例如,我在 pages/index.vue 中就是这样做的。
method: {
this.value = this.$store.value
}
我想把它写成 mixins,因为我实际上有其他逻辑围绕它,并且我使用了一些页面。
但是,我不知道如何从 mixins 访问 this(VueInstnce)?
【问题讨论】:
我想实现这种将this.$store.value 分配给本地数据的逻辑。
例如,我在 pages/index.vue 中就是这样做的。
method: {
this.value = this.$store.value
}
我想把它写成 mixins,因为我实际上有其他逻辑围绕它,并且我使用了一些页面。
但是,我不知道如何从 mixins 访问 this(VueInstnce)?
【问题讨论】:
好的,所以我不知道这是否被认为是一种不好的做法,但我设法完成了单向数据传输没有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 个全局实例)时,此解决方案很有用。不过,您当然可以使用实例数组并按顺序循环调用它们的方法.. :)
【讨论】:
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
【讨论】: