I am experimenting with Vue.js (version 2.5.16) and its v-for
directive which should be able to repeat an element according to some integer range, according to the official Vue.js documentation. Concretely, I am trying to write a component that draws a number of circular counters based on an integer-valued property.
The following snippet, containing the hard-coded literal value 10
, does indeed render precisely ten circles: (jsfiddle)
<svg class="counter" v-for="n in 10" :key="n"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 10 10">
<circle cx="5" cy="5" r="5"></circle>
</svg>
However, hard-coding the value is of limited utility. I have added an integer-valued property to my component as follows: (typescript)
export default Vue.extend({
props: {
counter: Number
},
...
... and tried the following variants of the v-for
directive:
But neither of them achieve a variable number of rendered circles. (Note: I have employed the Vue developer tools to ensure that the counter
property of the component does, in fact, hold the correct value.)
This brings me to my question: How do you use v-for
with an integer range set by a property of your component?
If this is not possible, then the integer-range support of v-for
is indeed rather useless. How often does one want to use a hard-coded range?
However, I still want the behaviour. How would one implement it without v-for
? I can think of several possible alternatives:
counter
property in a computed property that returns an array of the desired size and use v-for
on that array.v-for
to an array and hook into changes of the counter
property to update that internal array using only array mutations that are listed on the array change detection page so that Vue does not discard and rebuild the entire DOM substructure on every change.Option 1 seems like a tonne of work for such a simple use-case. Option 2 is trivially easy but I fear that it will cause Vue to discard and regenerate all the repeated child elements on every change. Option 3 seems like it would perform the best, if it is possible, but I don't really know how to go about it. (As I said, I am investigating Vue for the first time.)
What to do?
You just have to bind value to your counter
property.Let's assume your component is called circ
.
<div id="app">
<circ :counter="10"></circ>
</div>
<template id="circ">
<div>
<svg class="counter" v-for="n in counter" :key="n"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 10 10">
<circle cx="5" cy="5" r="5"></circle>
</svg>
</div>
</template>