How can I map array in vue.js

1.1k Views Asked by At

I'm working with a code using Vue and anime.js. I find my code is too long, consisting of 1500+ lines. I cut my sampleText to 5 items here so Stack Overflow would accept my question, but it's actually 114 items.

Also how can I randomly place the sampleText into <li>? It should shuffle sampleText in each <li> position.

<template>
  <div>
    <ul>
      <li>
        {{ texts.text1 }}
      </li>
      <li">
        {{ texts.text2 }}
      </li>
      <li>
        {{ texts.text3 }}
      </li>
      <li>
        {{ texts.text4 }}
      </li>
      <li>
        {{ texts.text5 }}
      </li>
    </ul>
  </div>
</template>

<script>
import anime from 'animejs/lib/anime.es.js'
import { reactive, onMounted } from '@nuxtjs/composition-api'

const sampleText1 = 'インバウント'
const sampleText2 = 'BtoB'
const sampleText3 = 'セールス'
const sampleText4 = 'OODA'
const sampleText5 = '指標'

const characters =
  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
const charactersLength = characters.length

export default {
  layout: 'default',
  data() {
    return {
      sam1: sampleText1,
      sam2: sampleText2,
      sam3: sampleText3,
      sam4: sampleText4,
      sam5: sampleText5,
    }
  },
  setup() {
    const texts = reactive({
      text1: sampleText1,
      text2: sampleText2,
      text3: sampleText3,
      text4: sampleText4,
      text5: sampleText5,
    })

    const scrambleText = (text, name) => ({ progress }) => {
      if (Math.floor(progress) <= 50) {
        if (Math.floor(progress) >= 50) {
          texts[name] = text
        } else if (Math.floor(progress) % 5 === 0) {
          texts[name] = text.replace(/./g, () =>
            characters.charAt(Math.floor(Math.random() * charactersLength))
          )
        }
      }
    }

    onMounted(() => {
      anime({
        targets: '.main',
        duration: 1000,
        easing: 'linear',
        loop: true,
        update: scrambleText(sampleText1, 'text1'),
      })
      anime({
        targets: '.main',
        duration: 1000,
        easing: 'linear',
        loop: true,
        update: scrambleText(sampleText2, 'text2'),
      })
      anime({
        targets: '.main',
        duration: 1000,
        easing: 'linear',
        loop: true,
        update: scrambleText(sampleText3, 'text3'),
      })
      anime({
        targets: '.main',
        duration: 1000,
        easing: 'linear',
        loop: true,
        update: scrambleText(sampleText4, 'text4'),
      })
      anime({
        targets: '.main',
        duration: 1000,
        easing: 'linear',
        loop: true,
        update: scrambleText(sampleText5, 'text5'),
      })
    })

    return {
      texts,
    }
  },
}
</script>
2

There are 2 best solutions below

2
On BEST ANSWER

This looks like a good use case for arrays and loops.

  1. Instead of an object, put your sample text into an array, and iterate that with a for-loop.

  2. Update scrambleText() call to pass the array index instead of the object key previously used for your object:

const texts = reactive([ // 1️⃣
  'インバウント',
  'BtoB',
  'セールス',
  'OODA',
  '指標',
  //...
])

onMounted(() => {
  for (let i = 0; i < texts.length; i++) { // 1️⃣
    anime({
      duration: 1000,
      easing: 'linear',
      loop: true,
      update: scrambleText(texts[i], i), // 2️⃣
    })
  }
})
  1. In your template, use a v-for to iterate the texts array:
<ul>
  <li v-for="text in texts">{{ text }}</li>
</ul>

demo

4
On

You can put all your texts in an array and iterate over it like so:

<ul>
   <li v-for="text in texts" :key="text">{{ text }}</li>
</ul>

Key given with the condition that all of your texts are unique.

And follow up with changing the functions in the onMounted to do something like:

texts.forEach((text, index) => {
      anime({
        targets: ".main",
        duration: 1000,
        easing: "linear",
        loop: true,
        update: scrambleText(text, index),
      });
    });