78

I'm developing a couple of Vue apps using single file components. I find quite a few of my components require common config information, for example an object containing delivery methods which I might define like this:

const DeliveryMethods = {
  DELIVERY: "Delivery",
  CARRIER: "Carrier",
  COLLATION: "Collation",
  CASH_AND_CARRY: "Cash and carry"
}

What is the cannonical way to make that available to my components? At the moment, I have done it with a file 'config.js', as below:

export default {

  DeliveryMethods: {
    DELIVERY: "Delivery",
    CARRIER: "Carrier",
    COLLATION: "Collation",
    CASH_AND_CARRY: "Cash and carry"
  }

}

In my components where I need it, I have import config from 'src/config.js', and where I want to use one of these, I'll refer to e.g., config.DeliveryMethods.CASH_AND_CARRY. This seems to me rather long-winded and repetitive, though, and I'd prefer to be able to use just DeliveryMethods.CASH_AND_CARRY instead of config.DeliveryMethods.CASH_AND_CARRY.

What is the canonical way to based on js lint and/or the jquery style guide? Are there any other authorities to consider?

ntg
  • 12,950
  • 7
  • 74
  • 95
John Moore
  • 6,739
  • 14
  • 51
  • 67
  • 2
    If you just want `DeliveryMethods.CASH_AND_CARRY` why not just export the POJO without the extra scoping of `DeliveryMethods: {...}` and just export the `{DELIVERY: "Delivery", ...}` portion; Then `import DeliveryMethods from "./src/config.js"` ? – subhaze Dec 01 '17 at 16:30

2 Answers2

60

delivery-methods/index.js

const DELIVERY = "Delivery"
const CARRIER = "Carrier"
const COLLATION = "Collation"
const CASH_AND_CARRY = "Cash and carry"
    
export default {
  DELIVERY: DELIVERY,
  CARRIER: CARRIER,
  COLLATION: COLLATION,
  CASH_AND_CARRY: CASH_AND_CARRY
}

Usage

import DeliveryMethods from './path/to/delivery-methods'

console.log(DeliveryMethods.CARRIER)

Or:

config.js

export default Object.freeze({
  DELIVERY: "Delivery",
  CARRIER: "Carrier",
  COLLATION: "Collation",
  CASH_AND_CARRY: "Cash and carry"
})

Usage:

import DeliveryMethods from './path/to/delivery-methods'

console.log(DeliveryMethods.CARRIER)
Paul P
  • 3,346
  • 2
  • 12
  • 26
  • Thanks, this and subhaze's comment pointed me in the right direction. DeliveryMethods isn't the only constant I'd want to use, so `export default` doesn't work if I want to have all my constants in a single file for ease of maintenance. What I've done is this: – John Moore Dec 01 '17 at 17:43
  • 1
    is there any other way then importing file in each and every vue file where we want to use that constant ? – Amit Joshi Aug 21 '19 at 06:18
  • Is the OR variant correct? How can you import DeliveryMethods, when the config.js defines no DeliveryMethods? – Ev0oD Sep 17 '21 at 10:46
29

Thanks, this and subhaze's comment pointed me in the right direction. DeliveryMethods isn't the only constant I'd want to use, so export default doesn't work if I want to have all my constants in a single file for ease of maintenance. What I've done is this:

export const DeliveryMethods = {
    DELIVERY: "Delivery",
    CARRIER: "Carrier",
    COLLATION: "Collation",
    CASH_AND_CARRY: "Cash and carry"
};

In my components I have import {DeliveryMethods} from 'src/config.js', which allows me to simply use e.g. DeliveryMethods.COLLATION. I can export/import any number of constants clearly and simply. Still feeling my way round Javascript modules!

LATER: Following WaldemarIce's suggestion, I have changed this to:

export const DeliveryMethods = Object.freeze({
    DELIVERY: "Delivery",
    CARRIER: "Carrier",
    COLLATION: "Collation",
    CASH_AND_CARRY: "Cash and carry"
});

That works better.

John Moore
  • 6,739
  • 14
  • 51
  • 67
  • Try what happens if you try to redefine `DeliveryMethods.DELIVERY = 'bla'`. –  Dec 01 '17 at 18:00
  • Well, I know that I can mutate the properties of an object even though the object itself has been declared via `const`, so the object isn't immutable. Your declaration of the constants themselves via `const` prior to assigning them to properties of the object would guard against that. But it's a little more verbose than I want to do it that way, and I'm thinking of the way I've done it as a kind of convention - title case object name with uppercase properties means it's an object with constants, so don't tamper! – John Moore Dec 01 '17 at 19:42
  • 4
    Ok, I understand, but why not to use the second option with Object.freeze()? It is not so verbose and it simulate constants, you cant change the properties of the freezed object. –  Dec 01 '17 at 19:50
  • Thanks, I've changed my answer now to use Object.freeze() as you suggest. Best of both worlds. – John Moore Dec 02 '17 at 11:26
  • 1
    Hmm ... I tried your suggestion, and it does not work for me? the DeliveryMethods object ends up being undefined. How do you refer to it in the Vue component? – themathmagician Oct 08 '18 at 18:51