60

I tried to defined a const in a *.vue file:

<script>
    export const CREATE_ACTION = 1,
    export const UPDATE_ACTION = 2
<script>

And use them in the template:

<template>
    ...
    <select :disabled="mode === UPDATE_ACTION">
    ....
</template>

But it does not work. How can I use const in a Vue template?

maxshuty
  • 9,708
  • 13
  • 64
  • 77
litbear
  • 806
  • 1
  • 6
  • 17

8 Answers8

71

If you expose them on your data, you are making them unnecessary reactive, as @mix3d mentioned...

A better approach is to add them into Vue object Reactivity in Depth:

<template>
      <div v-if="action === CREATE_ACTION">Something</div>
</template>

<script>
export default {
    created() {
        this.CREATE_ACTION = CREATE_ACTION;
        this.UPDATE_ACTION = UPDATE_ACTION;
    }
})
</script>
tony19
  • 125,647
  • 18
  • 229
  • 307
L. Palaiokostas
  • 987
  • 6
  • 8
  • 2
    This is the most appropriate answer in my opinion. Exposing in data makes them reactive and also you still have to use string values in template which we are trying to avoid in the first place. – metasync Apr 25 '20 at 21:56
  • This has my vote. It can be further elaborated by writing a mixin factory that produces your `created` hook dynamically: ` function mixinFactory(constants) { return { created() { Object.keys(constants).forEach((cName) => this[cName] = constants[cName]); }, }; } ` – Tibi Neagu Dec 09 '20 at 15:53
  • 3
    I like this approach except for the fact that it doesn't seem to play well with TypeScript. Can anyone can suggest a way to eliminate the TS errors here? – Sean May 26 '21 at 13:12
  • Any way of making these variables into actual constants? – Incinerator May 27 '22 at 08:32
  • 1
    @Incinerator You could attach these as a [frozen object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze): `this.constants = Object.freeze({ ONE: 1, TWO: 2 })`. To make this work, you add the constants in their own frozen object to an arbitrary key of `this`, rather than to `this` directly. – Impirator Jun 21 '22 at 17:25
43

Expose them on your data:

new Vue({
    data:{
        CREATE_ACTION: CREATE_ACTION,
        UPDATE_ACTION: UPDATE_ACTION
    }
})
maxshuty
  • 9,708
  • 13
  • 64
  • 77
Bert
  • 80,741
  • 17
  • 199
  • 164
  • 14
    but I want use it in another component,and ... more graceful? – litbear Mar 08 '17 at 03:03
  • @litbear you can use mixins or plugins to include things in multiple components, but to reference them in a template, you will have to expose them on data. – Bert Mar 08 '17 at 03:05
  • 17
    The downside of this approach is that these values get all the Vue interactivity (and associated overhead) by default. Not great, but in small usages it should be ok. – mix3d Sep 13 '19 at 22:28
  • 2
    exposing them to data creates an observable copy of the values. You don't actually comparing to the constant anymore. – Thanasis Ioannidis Apr 09 '21 at 12:01
19

You can use plugin for this purpose as you want to include this in multiple components:

// constsPlugin.js
const YOUR_CONSTS = {
  CREATE_ACTION: 1,
  UPDATE_ACTION: 2
  ...
}

let YourConsts = {}; // As suggested by the comments.

YourConsts.install = function (Vue, options) {
  Vue.prototype.$getConst = (key) => {
    return YOUR_CONSTS[key]
  }
}

export default YourConsts

in main.js or where you define new Vue(), you have to use it like this:

import YourConsts from 'path/to/plugin'

Vue.use(YourConsts)

Now you can use this in a component template like following:

<div>
   <select :disabled="mode === $getConst('UPDATE_ACTION')">
</div>
tony19
  • 125,647
  • 18
  • 229
  • 307
Saurabh
  • 71,488
  • 40
  • 181
  • 244
  • I think `YOUR_CONSTS` needs to be in same case as `YourConsts` because I got error that "_YourConsts is not defined_". (ESLint also complains that `YourConsts` is not defined.) – Gino Mempin Nov 25 '19 at 03:25
  • @GinoMempin, Nope. Its because that variable hasn't been defined. Answer OP should have included, let YourConsts = {} line first before defining install method. – XPD Aug 24 '20 at 19:41
  • the author's goal is to get rid of the magic lines, and you offer them to him – user9547708 Dec 11 '20 at 11:45
11

What about using Mixins? This is the way I do it. Not sure it is the best or recommended way but the code looks so much cleaner.

data/actions.js

export const CREATE_ACTION = 1;
export const UPDATE_ACTION = 2;

export const actionsMixin = {
  data() {
    return {
      CREATE_ACTION,
      UPDATE_ACTION
    }      
  }
}

MyComponent.vue

<template>
  <div v-if="action === CREATE_ACTION">Something</div>
</template>

<script>
import {actionsMixin, CREATE_ACTION} from './data/actions.js';

export default {
  mixins: [actionsMixin]
  data() {
    return {
      action: CREATE_ACTION
    }      
  }
}
</script>
Alessandro Benoit
  • 903
  • 10
  • 19
7
<template>
  <div v-if="FOO_CONST.bar">Something</div>
</template>

<script>
import {FOO_CONST} from './const.js';

export default {
  data() {
    return {
      FOO_CONST: Object.freeze(FOO_CONST) // this makes vue not reactive this data property
    }      
  }
}
</script>
7

In Vue 3 you can use setup().

Example:

<template>
  <div>
    hello {{ fooConst }}
  </div>
</template>

<script>
const fooConst = "bar";

export default {
  setup() {
    return {
      fooConst,
    }
  },
}
</script>

or fully using the Composition API:

<script setup>
const fooConst = "bar";
</script>

<template>
  <div>
    hello {{ fooConst }}
  </div>
</template>
iSWORD
  • 768
  • 15
  • 22
2

I've found Mixins to be a neat way to add constants non-reactively to the vue object.

First create your constants:

// Action.js
const Action = {
  CREATE: 1,
  UPDATE: 2
}

Action.Mixin = {
  created () {
    this.Action = Action
  }
}

export default Action

Then in the component:

<template>
  <select :disabled="mode === Action.UPDATE">
</template>

<script>
import Action from './Action.js'

export default {
  mixins: [Action.Mixin]
}
</script>

This is like a cross between Alessandro Benoit's and L. Palaiokostas' answers.

tony19
  • 125,647
  • 18
  • 229
  • 307
woodcoder
  • 31
  • 4
  • You still have to make declarations in every component, so not much benefit over other methods. – Kalnode Mar 09 '22 at 20:20
2
<template>
  <div>
    <p :style="{ color: $options.COLOR }">
      {{$options.HELLO}} {{$options.PERSON}}
    </p>
  </div>
</template>

<script>
const HELLO = 'Hello there.';
const COLOR = 'red';

export default {
  mounted() {
    console.log('Hello world');
  },
  COLOR,
  HELLO,
  PERSON: 'General Kenobi!',
}
</script>
SRack
  • 11,495
  • 5
  • 47
  • 60
RedShift
  • 287
  • 1
  • 6
  • 17