【问题标题】:What is the best way to declare global variables in Vue.js?在 Vue.js 中声明全局变量的最佳方式是什么?
【发布时间】:2016-09-18 22:51:47
【问题描述】:

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

把它放在data里面是个好主意吗?

我是否正确理解,如果我这样做,我将能够在任何地方使用this.hostname 调用它?

【问题讨论】:

    标签: global-variables vue.js


    【解决方案1】:

    由于您需要访问每个组件中的主机名变量,并在开发模式下将其更改为 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'
    

    可以在文档中找到一个示例: Documentation on Adding Instance Properties

    更多关于生产提示配置可以在这里找到:

    Vue documentation for production tip

    【讨论】:

    • 为了清楚起见,第一行进入 main.js
    • 您应该更喜欢Object.defineProperty(Vue.prototype, '$hostname', { value: 'http://localhost:3000' },因为默认情况下该变量是只读。您可以在本文中查看更多详细信息:dzone.com/articles/use-any-javascript-library-with-vuejs
    • 请问为什么$hostname 超过hostname?它只是自定义属性的样式约定,还是避免属性名称冲突..?
    • @DigitalNinja 来自文档:“这里没有发生任何魔法。$ 是 Vue 用于所有实例的属性的约定。这避免了与任何定义的数据、计算的属性或方法发生冲突。 " docs
    • @DigitalNinja,所以这是避免意外冲突的约定
    【解决方案2】:

    警告:以下答案是使用 Vue 1.x。 twoWay 数据突变已从 Vue 2.x 中移除(幸运的是!)。

    如果是“全局”变量(附加到全局对象,即 Web 浏览器中的窗口对象),声明变量的最可靠方法是将其显式设置在全局对象上:

    window.hostname = 'foo';
    

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

    例如,如果根 viewModel 有一个 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”应该是twoWay 绑定数据。

    因此通过改变组件中的数据,父级的数据将分别改变。

    例如:

    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>

    【讨论】:

    【解决方案3】:

    我强烈建议您查看Vuex,它是为 Vue 中的全球可访问数据而设计的。

    如果您只需要一些永远不会修改的基本变量,我会使用 ES6 导入:

    // config.js
    export default {
       hostname: 'myhostname'
    }
    
    // .vue file
    import config from 'config.js'
    
    console.log(config.hostname)
    

    你也可以用同样的方法导入json文件,没有代码知识的人也可以编辑,也可以导入SASS。

    【讨论】:

      【解决方案4】:

      vue3 replacement 中的this answer

      // 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'
        }
      })
      

      【讨论】:

      • 整洁!这很好。
      • 随着 Vue 3 越来越流行,这应该会更高。如果您使用的是 Vue 3 和单文件组件,那么与其他解决方案相比,它真的很容易并且不会造成混淆。
      【解决方案5】:

      对于任何单一文件组件用户,这是我设置全局变量的方式

      1. 假设你使用的是 Vue-Cli 的 webpack 模板
      2. 在 variable.js 中声明你的变量

        const shallWeUseVuex = false;
        
      3. 在 variable.js 中导出

        module.exports = { shallWeUseVuex : shallWeUseVuex };
        
      4. Require 并在你的 vue 文件中分配它

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

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

      【讨论】:

      • 不幸的是,shallWeUseVuex 在 data(){} 中定义时是一个变量,即可以更改。唉,您不能在模板或 HTML 中使用 'const shallWeUseVuex',而是必须从 data(){} 引用变量版本 - 如前所述,这不是常量。
      • 既然支持率很高,请使用原生模块而不是 commonJS(import 代替 require & export default 代替 module.exports = )。
      【解决方案6】:

      在 vue cli-3 中可以像在 main.js 中定义变量

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

      您还可以在任何组件中使用 的 window.basurl

      【讨论】:

        【解决方案7】:

        一种可能性是在 index.html 中声明变量,因为它实际上是全局的。可以添加一个javascript方法来返回变量的值,它将是只读的。

        可以在此答案中找到此解决方案的示例: https://stackoverflow.com/a/62485644/1178478

        【讨论】:

          猜你喜欢
          • 2011-12-01
          • 1970-01-01
          • 2022-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-06-05
          • 2016-05-19
          • 1970-01-01
          • 2010-10-12
          相关资源
          最近更新 更多