Vue.js中声明全局变量的最佳方法是什么?

81

我需要在每个组件中访问我的hostname变量。

将它放在data中是一个好主意吗?

如果这样做,我理解得对吗?我将能够在任何地方使用 this.hostname 调用它吗?

7个回答

97

由于每个组件都需要访问您的主机名变量,并在开发模式下将其更改为localhost,或在生产模式下更改为生产主机名,因此您可以在原型中定义此变量。

像这样:

Vue.prototype.$hostname = 'http://localhost:3000'

而且 $hostname 将在所有 Vue 实例中可用:

new Vue({
  beforeCreate: function () {
    console.log(this.$hostname)
  }
})

对于我的情况,为了自动地从开发模式切换到生产模式,我已经在实例化Vue的文件中,按照一个Vue生产提示变量定义了$hostname原型。

像这样:

Vue.config.productionTip = false
Vue.prototype.$hostname = (Vue.config.productionTip) ? 'https://hostname' : 'http://localhost:3000'

文档中有一个例子: 添加实例属性的文档

有关生产提示配置的更多信息可在此处找到:

Vue生产提示的文档


18
为了清晰起见,第一行应该放在main.js文件中。 - MonoThreaded
3
由于变量默认是只读的,建议使用 Object.defineProperty(Vue.prototype, '$hostname', { value: 'http://localhost:3000' })。您可以在这篇文章中了解更多详细信息:https://dzone.com/articles/use-any-javascript-library-with-vuejs - Ulysse BN
2
我可以问一下为什么要使用$hostname而不是hostname吗?这只是自定义属性的样式惯例,还是为了避免属性名称冲突? - Digital Ninja
7
来自文档的@DigitalNinja:“这里没有任何魔法。$是Vue用于所有实例可用属性的约定。这避免了与任何已定义的数据、计算属性或方法发生冲突。” [文档](https://vuejs.org/v2/cookbook/adding-instance-properties.html#The-Importance-of-Scoping-Instance-Properties) - Josiel Faleiros
2
@DigitalNinja,这是一种避免意外冲突的约定。 - Josiel Faleiros
显示剩余10条评论

36

这个答案Vue3替代方案

// Vue3

const app = Vue.createApp({})
app.config.globalProperties.$hostname = 'http://localhost:3000'


app.component('a-child-component', {
  mounted() {
    console.log(this.$hostname) // 'http://localhost:3000'
  }
})

不错!这很好。 - Anoop Thiruonam
随着Vue 3变得越来越受欢迎,这个应该会更高。与其他方案相比,它真的很容易使用,如果您正在使用Vue 3和单文件组件,则不容易混淆。 - theberzi
全局属性是否需要以“$”开头? - nwfistere

20

警告:下面的答案使用的是 Vue 1.x。在Vue 2.x中,twoWay数据变异已被删除(幸运的是!)。

对于“全局”变量——即附加到全局对象上的变量,在Web浏览器中就是window对象,最可靠的声明变量的方法是显式地将其设置在全局对象上:

window.hostname = 'foo';

然而从Vue的层次结构角度来看(根视图模型和嵌套组件),数据可以向下传递(如果指定了双向绑定,还可以向上修改)。

例如,如果根视图模型有一个hostname数据,可以通过v-bind指令将值绑定到嵌套组件,如v-bind:hostname="hostname"或简写为:hostname="hostname"

在组件内部,绑定的值可以通过组件的props属性访问。

最终,数据将被代理到this.hostname中,并在需要时可在当前的Vue实例中使用。

var theGrandChild = Vue.extend({
  template: '<h3>The nested component has also a "{{foo}}" and a "{{bar}}"</h3>',
    props: ['foo', 'bar']
});

var theChild = Vue.extend({
  template: '<h2>My awesome component has a "{{foo}}"</h2> \
             <the-grandchild :foo="foo" :bar="bar"></the-grandchild>',
  props: ['foo'],
  data: function() {
    return {
      bar: 'bar'
    };
  },
  components: {
    'the-grandchild': theGrandChild
  }
});


// the root view model
new Vue({
  el: 'body',
  data: {
    foo: 'foo'
  },
  components: {
    'the-child': theChild
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.16/vue.js"></script>
<h1>The root view model has a "{{foo}}"</h1>
<the-child :foo="foo"></the-child>


当需要向上改变父组件的数据时,我们可以在绑定声明中添加 .sync 修饰符,例如 :foo.sync="foo",并指定给定的 'props' 应该是一个 双向绑定 的数据。

因此,通过修改组件中的数据,父组件的数据也会相应地改变。

例如:

var theGrandChild = Vue.extend({
  template: '<h3>The nested component has also a "{{foo}}" and a "{{bar}}"</h3> \
             <input v-model="foo" type="text">',
    props: {
      'foo': {
        twoWay: true
      },  
      'bar': {}
    }
});

var theChild = Vue.extend({
  template: '<h2>My awesome component has a "{{foo}}"</h2> \
             <the-grandchild :foo.sync="foo" :bar="bar"></the-grandchild>',
  props: {
    'foo': {
      twoWay: true
    }
  },
  data: function() {
    return { bar: 'bar' };
  },  
  components: {
    'the-grandchild': theGrandChild
  }
});

// the root view model
new Vue({
  el: 'body',
  data: {
    foo: 'foo'
  },
  components: {
    'the-child': theChild
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.16/vue.js"></script>
<h1>The root view model has a "{{foo}}"</h1>
<the-child :foo.sync="foo"></the-child>


36
请定义"soon"这个词。 - noɥʇʎԀʎzɐɹƆ
14
我猜他的意思是“从不”。 - Red fx
5
他不需要这样做。Vue更快,并且重新实现了它:https://vuejs.org/v2/guide/components.html#sync-Modifier - ndevln

15

我强烈推荐你查看Vuex,它专为在Vue中实现全局访问数据而设计。

如果你只需要一些基本变量且永远不会被修改,我建议使用ES6导入:

// config.js
export default {
   hostname: 'myhostname'
}

// .vue file
import config from 'config.js'

console.log(config.hostname)

您也可以以同样的方式导入json文件,这样可以由不具备编码知识的人编辑或导入到SASS中。


6

对于任何单文件组件用户,这里是我如何设置全局变量:

  1. Assuming you are using Vue-Cli's webpack template

  2. Declare your variable(s) in somewhere variable.js

     const shallWeUseVuex = false;
    
  3. Export it in variable.js

     module.exports = { shallWeUseVuex : shallWeUseVuex };
    
  4. Require and assign it in your vue file

     export default {
         data() {
             return {
                 shallWeUseVuex: require('../../variable.js')
             };
         }
     }
    

参考: https://v2.vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch

本文介绍了从头开始实现简单状态管理的方法。它提供了一个事件总线和一个全局状态对象,以便在Vue组件之间共享数据。通过简单的示例代码,您可以了解如何将这些工具集成到您的应用程序中,从而更好地组织和管理您的数据。


2
不幸的是,当在data(){}中定义时,shallWeUseVuex是一个变量,即它可以被更改。然而,你不能在模板或HTML中使用“const shallWeUseVuex”,而是必须从data(){}引用变量版本 - 正如前面提到的那样,这不是一个常量。 - Dave Durbin
现在支持已经很高,请使用本地模块而不是commonJS(使用import而不是requireexport default而不是module.exports =)。 - Fabian von Ellerts

1
在Vue CLI 3中,您可以像以下方式在main.js中定义变量:

window.basurl="http://localhost:8000/";

你也可以使用 window.basurl 在任何组件中访问该变量。


1

一种可能性是在index.html中声明变量,因为它是真正的全局变量。可以通过添加JavaScript方法来返回变量的值,并且它将是只读的。

这种解决方案的示例可以在以下答案中找到: https://dev59.com/5FgR5IYBdhLWcg3ww_oz#62485644


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接