Vue/Nuxt: 如何定义一个所有组件都可以访问的全局方法?

Vue/Nuxt: How to define a global method accessible to all components?

我只想打电话

{{ globalThing(0) }}

在模板中,无需在每个 .vue 文件中定义 globalThing。

我已经尝试了各种插件配置方式(或者 mixins?不确定 Nuxt 是否使用该术语。),但都无济于事。似乎无论我做什么,globalThingthis.globalThing 仍然未定义。

在某些情况下,我什至可以在 Chrome 中调试并看到这个 this.globalThing 确实被定义了......但是代码还是崩溃了,我发现这很难解释。

这是我的许多尝试之一,这次使用插件:

nuxt.config.js:

plugins: [
    {
        src: '~/plugins/global.js',
        mode: 'client'
    },
],

global.js:

import Vue from 'vue';
Vue.prototype.globalFunction = arg => {
    console.log('arg', arg);
    return arg;
};

并在 .vue 文件中的模板中:

        <div>gloabal test {{globalFunction('toto')}}</div>

然后...结果:

类型错误 _vm.globalFunction 不是函数


这里有一个不同的想法,使用 Vuex store。

store/index.js:

export const actions = {
    globalThing(p) {
        return p + ' test';
    }
};

.vue 文件模板: 测试结果:{{test('fafa')}}

.vue 文件脚本:

import { mapActions } from 'vuex';

export default {

    methods: {
        ...mapActions({
            test: 'globalThing'
        }),
    }
};

aaaaaaaa 结果是……

测试结果:[object Promise]

好的,所以这次至少有这个方法。我更希望不要被迫在每个组件中执行此 "import mapActions" 舞蹈等......但如果那真的是唯一的方法,无论如何。

但是,我得到的只是一个 Promise,因为这个调用是异步的。当它完成时,promise 确实包含返回值,但这在这里没有用,因为我需要它从方法中返回。


编辑

在客户端上,"this" 是未定义的,除了......它不是!也就是说,

console.log('this', this); 

说 "undefined",但是 Chrome 的调试器声称,就在这个控制台日志之后,"this" 正是它应该的样子(组件实例),并且这个也是。$store!

我在这里添加截图作为证据,因为我什至不相信自己的眼睛。

这将是 Vuex 和 Nuxt 的方法:

// store/index.js

export const state = () => ({
    globalThing: ''
})

export const mutations = {
    setGlobalThing (state, value) {
        state.globalThing = value
    }
}


// .vue file script

export default {
    created() {
        this.$store.commit('setGlobalThing', 'hello')
    },
};



// .vue file template

{{ this.$store.state.globalThing }}

  1. 使用Nuxt的inject让方法随处可用
export default ({ app }, inject) => {
  inject('myInjectedFunction', (string) => console.log('That was easy!', string))
}
  1. 确保您以 $myInjectedFunction 的身份访问该函数(注意 $
  2. 确保您在 nuxt.config.js 插件部分添加了它

如果所有其他方法都失败了,请将函数包装在一个对象中并注入对象,这样您的模板中就会有类似 $myWrapper.myFunction() 的东西 - 我们到处都使用从插件注入的对象并且它有效(例如在模板中的 v-if 中,所以很确定它也适用于 {{ }}。

比如我们的analytics.js插件看起来比较少:

import Vue from 'vue';
const analytics = {
    setAnalyticsUsersData(store) {...}
    ...
}

//this is to help Webstorm with autocomplete
Vue.prototype.$analytics = analytics;

export default ({app}, inject) => {
    inject('analytics', analytics);
}

然后称为 $analytics.setAnalyticsUsersData(...)

P.S。刚注意到一件事。您的插件处于客户端模式。如果你在 universal 中 运行ning,你必须确保在 SSR 期间没有在任何地方使用这个插件(和函数)。如果它在模板中,它很可能实际上是在 SSR 期间使用的,因此是未定义的。在两种模式下也将您的插件更改为 运行。

https://nuxtjs.org/guide/plugins/

Nuxt 在 Inject in $root & context 部分对此进行了解释。

您必须将全局方法注入 Vue 实例和上下文。

例如我们有一个 hello.js 文件。

在 plugins/hello.js:

export default (context, inject) => {
  const hello = (msg) => console.log(`Hello ${msg}!`)
  // Inject $hello(msg) in Vue, context and store.
  inject('hello', hello)
  // For Nuxt <= 2.12, also add 
  context.$hello = hello
}

然后在nuxt.config.js中添加这个文件:

export default {
  plugins: ['~/plugins/hello.js']
}