在v-for循环中为类绑定访问数组项

时间:2019-05-31 14:50:41

标签: typescript vue.js

当使用Vue的动态类绑定使用三元运算符根据currentValue和循环数组中项的ID绑定类时,Vue似乎完全忽略了该类。

“第一个”和“最后一个”类绑定都起作用,但是使用item.id时,永远不会分配该类。但是会触发该函数,因为事件已成功发出并且已更新currentValue var。

ContentSwitcher.vue

<template>
  <div class="content-switcher-wrapper">
    <section class="content-items">
      <a v-for="(item, index) in options"
         class="content-item"
         :class="[ index === 0 ? 'first' : '',
                   index === options.length -1 ? 'last' : '',
                   item.id === currentValue ? 'selected' : '',]"
         @click="updateSelected(item.id)">
        {{ item.text }}
      </a>
    </section>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';

@Component
export default class ContentSwitcher extends Vue {
  @Prop()
  public options!: any;

  public currentValue!: string;

  public created(): void {
    this.currentValue = this.options[0].id;
  }

  public updateSelected(value: string): void {
    this.currentValue = value;
    this.$emit('contentSwitcherUpdated', value);
  }
}
</script>

用法

<content-switcher :options="tabSwitcherOptions"></content-switcher>

已通过选项

  private tabSwitcherOptions: any = [
    {
      id: 'week',
      text: 'Week',
    },
    {
      id: 'month',
      text: 'Maand',
    },
  ];

点击“月”时,会触发该事件,但是不会将分类为“选定”的内容添加到标签中。

2 个答案:

答案 0 :(得分:1)

组件的问题在于,初始化时,typescript类中的数据属性为undefined。因此,currentValue是无反应的。

official Vue documentation

  

要在Babel和TypeScript的装饰器行为之间保持一致,如果vue-class-component具有未定义为初始值的属性,则不会使该属性成为反应性的。您应该使用null作为初始值,或者使用数据挂钩初始化未定义的属性。

您需要使用钩子初始化数据属性:

@Component
export default class ContentSwitcher extends Vue {
  @Prop()
  public options!: any;

  public currentValue!: string;

  // Here!
  data () {
    return {
      currentValue: undefined
    }
  }

  public created(): void {
    this.currentValue = this.options[0].id;
  }

  public updateSelected(value: string): void {
    this.currentValue = value;
    this.$emit('contentSwitcherUpdated', value);
  }
}

这里是working example on codesandox

此外,当我在Javascript中对其进行测试时,您的代码也可以正常工作。

Vue.config.productionTip = false;

Vue.component('content-switcher', {
  template: `
<div class="content-switcher-wrapper">
  Selected: {{ currentValue }}
  </br>
  <section class="content-items">
    <a v-for="(item, index) in options"
       class="content-item"
       :class="[ index === 0 ? 'first' : '',
                 index === options.length -1 ? 'last' : '',
                 item.id === currentValue ? 'selected' : '',]"
       @click="updateSelected(item.id)">
      {{ item.text }}
    </a>
  </section>
</div>
  `,
  props: {
    options: Array
  },
  data: () => ({
    currentValue: undefined,
  }),
  created() {
    this.currentValue = this.options[0].id;
  },
  methods: {
    updateSelected(value) {
      this.currentValue = value;
    }
  }
});

new Vue({
   el: '#app',
   template: `
    <div>
     <content-switcher :options="tabSwitcherOptions" />
   </div>
   `,
   data: () => ({
      tabSwitcherOptions: [
        {
          id: 'week',
          text: 'Week',
        },
        {
          id: 'day',
          text: 'Day',
        },
        {
          id: 'month',
          text: 'Maand',
        },
      ]
   })
})
.first { color: red; }
.last { color: green; }
.selected { font-size: 2em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

答案 1 :(得分:0)

我认为您所拥有的实际上是这里public currentValue!: string上出现的反应性问题。在创建钩子之前,不会分配currentValue。创建的钩子不是构造函数,并且在实例化之后执行,这意味着最初创建组件currentValue时实际上是未定义的。实例属性必须具有初始值才能进行更改检测。将其更改为public currentValue: string = '';,您应该会看到想要的结果。

有关更多信息,请参见Declaring-Reactive-Properties