82

I need access to my hostname variable in every component.

Is it a good idea to put it inside data?

Am I right in understanding that if I do so, I will able to call it everywhere with this.hostname?

7 Answers 7

97

As you need access to your hostname variable in every component, and to change it to localhost while in development mode, or to production hostname when in production mode, you can define this variable in the prototype.

Like this:

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

And $hostname will be available in all Vue instances:

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

In my case, to automatically change from development to production, I've defined the $hostname prototype according to a Vue production tip variable in the file where I instantiated the Vue.

Like this:

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

An example can be found in the docs: Documentation on Adding Instance Properties

More about production tip config can be found here:

Vue documentation for production tip

15
  • 19
    For clarity, the first line goes in main.js Commented Mar 12, 2018 at 2:28
  • 3
    You should prefer Object.defineProperty(Vue.prototype, '$hostname', { value: 'http://localhost:3000' } since the variable would be read-only by default. You can see more details in this article: dzone.com/articles/use-any-javascript-library-with-vuejs
    – Ulysse BN
    Commented Jan 9, 2019 at 15:41
  • 2
    May i ask why $hostname over hostname? Is it just a style convention for custom properties, or avoiding collisions for property names..? Commented Aug 4, 2019 at 9:24
  • 7
    @DigitalNinja from the docs: "No magic is happening here. $ is a convention Vue uses for properties that are available to all instances. This avoids conflicts with any defined data, computed properties, or methods." docs Commented Aug 4, 2019 at 14:31
  • 3
    @DigitalNinja, so this is a convention to not have unexpected conflicts Commented Aug 4, 2019 at 14:34
38

a vue3 replacement of 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'
  }
})
5
  • Neat! this is nice. Commented Apr 27, 2021 at 7:19
  • As Vue 3 gets more popular, this should be higher. It's really easy compared to other solutions and less confusing if you're using Vue 3 and single-file components.
    – theberzi
    Commented Jun 5, 2021 at 8:09
  • Are the globalProperties required to start with a '$'?
    – nwfistere
    Commented Mar 26, 2022 at 4:48
  • this.$myGlobalProperty is inaccessible in another component for me. I used the app instance in main.js, idk if that's wrong Commented Apr 28 at 9:21
  • Seems this is only available in the options Api, as I read in this answer Commented Apr 28 at 9:50
20

Warning: The following answer is using Vue 1.x. The twoWay data mutation is removed from Vue 2.x (fortunately!).

In case of "global" variables—that are attached to the global object, which is the window object in web browsers—the most reliable way to declare the variable is to set it on the global object explicitly:

window.hostname = 'foo';

However form Vue's hierarchy perspective (the root view Model and nested components) the data can be passed downwards (and can be mutated upwards if twoWay binding is specified).

For instance if the root viewModel has a hostname data, the value can be bound to a nested component with v-bind directive as v-bind:hostname="hostname" or in short :hostname="hostname".

And within the component the bound value can be accessed through component's props property.

Eventually the data will be proxied to this.hostname and can be used inside the current Vue instance if needed.

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>


In cases that we need to mutate the parent's data upwards, we can add a .sync modifier to our binding declaration like :foo.sync="foo" and specify that the given 'props' is supposed to be a twoWay bound data.

Hence by mutating the data in a component, the parent's data would be changed respectively.

For instance:

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
16

I strongly recommend taking a look at Vuex, it is made for globally accessible data in Vue.

If you only need a few base variables that will never be modified, I would use ES6 imports:

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

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

console.log(config.hostname)

You could also import a json file in the same way, which can be edited by people without code knowledge or imported into SASS.

1
  • please explain how would one import a json file
    – churchill
    Commented Mar 28 at 3:32
6

For any Single File Component users, here is how I set up global variable(s)

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

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

2
  • 2
    Unfortunately shallWeUseVuex is a variable when defined in data(){} i.e. it can be changed. Alas, you can't use 'const shallWeUseVuex' in templates or HTML, rather you have to reference the variable version from data(){} - which is, as mentioned, not a constant. Commented Jan 24, 2017 at 0:24
  • Now that support is high, please use native modules instead of commonJS (import instead of require & export default instead of module.exports = ). Commented Sep 26, 2019 at 8:03
1

In vue cli-3 You can define the variable in main.js like

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

And you can also access this variable in any component by using the the window.basurl

1

A possibility is to declare the variable at the index.html because it is really global. It can be done adding a javascript method to return the value of the variable, and it will be READ ONLY.

An example of this solution can be found at this answer: https://stackoverflow.com/a/62485644/1178478

Not the answer you're looking for? Browse other questions tagged or ask your own question.