81

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?

zcoop98
  • 2,590
  • 1
  • 18
  • 31
Dmitry Bubnenkov
  • 9,415
  • 19
  • 85
  • 145

7 Answers7

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

tony19
  • 125,647
  • 18
  • 229
  • 307
Josiel Faleiros
  • 1,437
  • 2
  • 15
  • 19
  • 18
    For clarity, the first line goes in main.js – MonoThreaded Mar 12 '18 at 02:28
  • In my opinion this is a great alternative to using vuex if you want to create your own ES6 data model to replace the global "store" in vuex. This gives you complete flexibility with your code structure. Example: Vue.prototype.$session = new Session(), where "Session" is a custom ES6 class. This allows you to create a globally accessible session object but with your own data structure. – Sam Oct 03 '18 at 19:12
  • 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: https://dzone.com/articles/use-any-javascript-library-with-vuejs – Ulysse BN Jan 09 '19 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..? – Digital Ninja Aug 04 '19 at 09: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](https://vuejs.org/v2/cookbook/adding-instance-properties.html#The-Importance-of-Scoping-Instance-Properties) – Josiel Faleiros Aug 04 '19 at 14:31
  • 2
    @DigitalNinja, so this is a convention to not have unexpected conflicts – Josiel Faleiros Aug 04 '19 at 14:34
  • 1
    Note: It is also available in Vue Router. Ex. `Vue.prototype.my_routes = {}; /* Will be available in router like this -> */ new VueRouter({ routes: this.app.my_routes })` – Steffan Feb 10 '20 at 09:22
  • 1
    You are awesome, thanks man. I have one more question. Can i use this variable inside – Shujat Munawar Mar 25 '20 at 14:49
  • You are welcome! Yes you can use in the same way as if you had declared in `data()` Thanks for the compliment, and any doubts I'here :) – Josiel Faleiros Mar 25 '20 at 15:03
  • Is there any way to make these global variables persist when navigating between routes? – Nicke Manarin May 11 '20 at 17:15
  • @NickeManarin have you tried it? here works between routes by Vue Router – Josiel Faleiros May 11 '20 at 17:38
  • @JosielFaleiros Perhaps it's not working because my routes are lazy loaded (separated JS files). – Nicke Manarin May 11 '20 at 17:42
  • The property is defined in the imported Vue, so check if you are using the same Vue imported, because reimporting could lead the property to not working, (not sure about this) – Josiel Faleiros May 11 '20 at 18:45
  • Lazy loading by itself should not broke it – Josiel Faleiros May 11 '20 at 18:47
  • Vue.config vs Vue.prototype ?? – Pawel Cioch Sep 21 '22 at 16:16
33

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'
  }
})
iraj jelodari
  • 3,118
  • 3
  • 35
  • 45
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>
James Skemp
  • 8,018
  • 9
  • 64
  • 107
Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
14

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.

Fabian von Ellerts
  • 4,763
  • 40
  • 35
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

tony19
  • 125,647
  • 18
  • 229
  • 307
KuN
  • 1,143
  • 18
  • 23
  • 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. – Dave Durbin Jan 24 '17 at 00:24
  • Now that support is high, please use native modules instead of commonJS (`import` instead of `require` & `export default` instead of `module.exports = `). – Fabian von Ellerts Sep 26 '19 at 08: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

user8099291
  • 279
  • 1
  • 3
  • 12
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

Derzu
  • 7,011
  • 3
  • 57
  • 60