Vue/Nuxt: 如何定义一个所有组件都可以访问的全局方法?
Vue/Nuxt: How to define a global method accessible to all components?
我只想打电话
{{ globalThing(0) }}
在模板中,无需在每个 .vue 文件中定义 globalThing。
我已经尝试了各种插件配置方式(或者 mixins?不确定 Nuxt 是否使用该术语。),但都无济于事。似乎无论我做什么,globalThing
和 this.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 }}
- 使用Nuxt的inject让方法随处可用
export default ({ app }, inject) => {
inject('myInjectedFunction', (string) => console.log('That was easy!', string))
}
- 确保您以 $myInjectedFunction 的身份访问该函数(注意 $)
- 确保您在 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']
}
我只想打电话
{{ globalThing(0) }}
在模板中,无需在每个 .vue 文件中定义 globalThing。
我已经尝试了各种插件配置方式(或者 mixins?不确定 Nuxt 是否使用该术语。),但都无济于事。似乎无论我做什么,globalThing
和 this.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 }}
- 使用Nuxt的inject让方法随处可用
export default ({ app }, inject) => {
inject('myInjectedFunction', (string) => console.log('That was easy!', string))
}
- 确保您以 $myInjectedFunction 的身份访问该函数(注意 $)
- 确保您在 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']
}