在vue循环中动态改变元素的颜色

Dynamically change colours of element in vue loop

所以我试图实现以下设计:

特别是上面的彩色徽章。现在这些项目被分组并且可以是任意数量。 在图片中,它们分为 2 个,但很容易变成 4 个或 5 个。

我想要一种方法来以编程方式更改每个组的每个徽章的背景和文本颜色。

我已经尝试了很多对我没有用的东西,我目前充其量只能让第一个颜色改变。

这是我的页面:

<template>
  <div class="w-full flex flex-col px-6">
    <div class="flex flex-row">
      <button class="flex flex-wrap justify-center content-center w-20 h-20 bg-blob-1 bg-no-repeat bg-contain bg-center -ml-3">
        <img class="flex w-5 h-5" src="~/assets/images/icon-back.svg" alt="">
      </button>
    </div>

    <div class="flex flex-col mt-1">
      <span class="font-raleway font-black text-2xl text-white">{{ route.origin }} - {{ route.destination }}</span>
      <div class="inline-block w-44 bg-black bg-opacity-50 rounded p-2">
         <div class="font-raleway text-md text-white">{{ departureDate.formattedDate }}</div>
      </div>
    </div>

    <div class="flex flex-col mt-10">
      <type :name="name" :bg-color="colours[index].bg" :text-color="colours[index].text" v-for="(values, name, index) in schedules" :key="name" class="mb-10">
        <schedule :schedule="schedule" v-for="schedule in values" :key="schedule.id" class="mb-1" />
      </type>
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex';
import type from '~/components/bus/type.vue';
import schedule from '~/components/bus/schedule.vue';

export default {
  name: 'schedules',
  layout: 'bus-default',
  components: {type, schedule},
  async fetch({ store }) {
    const trip = store.state.trip;
    const schedule = store.state.schedule;

    await store.dispatch('schedule/getSchedules', {
      company: trip.company.alias,
      origin: trip.route.origin,
      destination: trip.route.destination, 
      date: trip.departureDate.fullDate,
      schedules: schedule.schedules
    });
  },
  computed: {
    ...mapState({
        company: state => state.trip.company.name,
        route: state => state.trip.route,
        departureDate: state => state.trip.departureDate,
        schedules: state => state.schedule.schedules,
        colours: state => state.schedule.colours
    }),
  }
}
</script>

这是我的包含徽章的组件:

<template>
  <div>
      <div :class="{bgColor: true, textColor}" :key="bgColor" class="w-auto inline-block rounded-full px-3 py-1 ml-3 absolute z-20 shadow-md -mt-4 font-raleway text-sm capitalize">{{ name }}</div>
      <slot></slot>
  </div>
</template>

<script>
import { mapState } from 'vuex';

export default {
  name: 'type',
  props: ['name', 'bg-color', 'text-color'],
  computed: {
    ...mapState({
        colours: state => state.schedule.colours
    }),
  }
}
</script>

这是我的商店文件:

export const state = () => ({
    schedules: [],
    schedule: {},
    colours: [{'bg': 'bg-red-400', 'text': 'text-white'}, {'bg': 'bg-blue-400', 'text': 'text-white'}, {'bg': 'bg-yellow-600', 'text': 'text-gray-800'}],
    colour: {}
});

export const mutations = {
    setColours(state, colours) {
        state.colours = colours;
    },
    setColour(state, colour) {
        state.colour = colour;
    },
    setSchedules(state, schedules) {
        state.schedules = schedules;
    },
}

export const actions = {
    async getSchedules({ commit }, params) {
        const res = await this.$api.get('/bus/schedules', { params: params });
        commit('setSchedules', res.data);    
    },
    initialiseColours({ commit }) {
        const colours = [{'bg': 'bg-red-400', 'text': 'text-white'}, {'bg': 'bg-blue-400', 'text': 'text-white'}, {'bg': 'bg-yellow-600', 'text': 'text-gray-800'}];
        commit('setColours', colours);  
    },
    getRandomColour({ commit, state }) {
        var colours = [...state.colours];
         console.log('colours:', colours);
        var index = Math.floor(Math.random() * colours.length);
        const colour = colours.splice(index, 1)[0];
        commit('setColours', colours); 
        commit('setColour', colour);    
    },
}

所以我想在这里实现的是以编程方式为每个组中的每个“徽章”分配随机背景颜色。我指的徽章是图中的行政和标准。

此外,文本应根据背景可见,必要时为白色,必要时为黑色。

出于某种原因,我的解决方案只更改了第一项,第二项是透明的,但是当我检查 HTML 时,我看到了 class 但它没有在浏览器中显示颜色.

编辑:所以我忘记添加的最后一件事是颜色应该在没有替换的情况下使用,这意味着当一个可以使用时它不应该再次重复。

这是一个没有 Vuex 的快速简单的解决方案。如果你真的认为你需要一些全球性的东西,应该也可以工作。

<template>
  <div>
    <div
      v-for="(button, index) in numberOfIterations"
      :key="button"
      :class="[arrayOfColours[findRandomInRange()]]"
    >
      div #{{ index }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      arrayOfColours: ['red', 'blue', 'orange'],
      numberOfIterations: 6,
    }
  },
  methods: {
    findRandomInRange() {
      return Math.floor(Math.random() * this.numberOfIterations) % this.arrayOfColours.length
    },
  },
}
</script>

<style>
.red {
  background-color: red;
}
.blue {
  background-color: blue;
}
.orange {
  background-color: orange;
}
</style>

解释:

  • numberOfIterations只是用来做一个基本的循环
  • % this.arrayOfColours.length 被赋予在我们的颜色范围内的界限。在我的示例中,我设置了 6 次迭代但只有 3 种颜色,如果我们试图获得第 5 种颜色会很烦人,因为数组中只有 3 项
  • findRandomInRange() 在渲染期间被调用,因为您可能希望它们在渲染时被着色
  • 在这种情况下 :key 显然可以做得更好
  • 在我的示例中,颜色当然会在每个 div 上随机播放,每次您再次渲染它们时

我希望剩下的是不言自明的。

这是它的样子


在我看到您想要独特的颜色,但仍然有一些随机性之后进行编辑。代码更短。

<template>
  <div>
    <div v-for="(button, index) in arrayOfColours" :key="button" :class="[arrayOfColours[index]]">
      div #{{ index }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      arrayOfColours: ['red', 'blue', 'orange'],
    }
  },
  created() {
    this.shuffle() // shuffle the order of the array before you mount it to the DOM
  },
  methods: {
    shuffle() {
      this.arrayOfColours.sort(() => Math.random() - 0.5)
    },
  },
}
</script>

您的代码即将运行,但 class 绑定中存在问题:

<div :class="{bgColor: true, textColor}"> ❌

该绑定在名为 "bgColor""textColor"div 上设置了两个 classes,但如果您实际上希望这些道具的值是 class 名称,你应该绑定这些道具的数组:

<div :class="[bgColor, textColor]">

假设那些 class 名称对应于现有样式,背景和文本颜色将相应更新。

要使徽章颜色随机化,shuffle 计算 属性:

state.schedule.colours 数组的副本
// 
function shuffleArray(array) {
  if (!array || array.length <= 1) return array;
  array = array.slice();
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    const temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
  return array;
}

export default {
  computed: {
    ...mapState({
      colours: state => shuffleArray(state.schedule.colours)
    }),
  }
}

demo