值更改时如何更新Dom(重新渲染元素)?

时间:2019-08-12 21:32:05

标签: vue.js bootstrap-vue

因此,我有一个正在显示的变量startWeek,当我单击按钮时,有一个将日期添加7天的方法。我希望页面显示新日期,但不确定如何执行此操作吗?

我希望每次更新日期范围时都能输入和输出日期,但是我不确定如何执行。我曾考虑过使用两个v-if语句,然后在它们之间来回过渡,但是我肯定有更好的方法。我已经研究了观察者和计算出的属性,但不确定在这种情况下它们是否是答案或如何实现。

示例:

<template>
<b-button @click="subtractWeek(7)></b-button>
<span id="thingIwantToUpdateInDOM">{{ startWeek + " - " + endWeek}}</span>
<b-button @click="addWeek(7)></b-button>
</template>


export default {
   data(){
    return{
           startWeek: null,
           endWeek: null,
          }
         },
methods: { 
   addWeek(days){
      this.startWeek.setDate(this.startWeek.getDate() + days)
      this.endWeek.setDate(this.endWeek.getDate() + days)
    },
substractWeek(7){
      this.startWeek.setDate(this.startWeek.getDate() - days)
      this.endWeek.setDate(this.endWeek.getDate() - days)
    },
getInitialDate(){
     this.startWeek = new Date();
     var tempEndWeek = new Date();
     this.endWeek = tempEndWeek;
  },
created() {
this.getInitialDate();
}
 }
}

我的最终目标是让日期范围在每次点击按钮或更改值时像轮播效果一样滑动我们的过渡效果。任何建议都将不胜感激!

1 个答案:

答案 0 :(得分:1)

您的最终目标还有很多优化工作,但是下面的代码段应该可以帮助您入门。您的日期操作很好,所以有关实现的一些注意事项:

  • 我不完全了解Vue如何在data对象中进行状态更改跟踪,但是我很确定它涉及getter and setter property accessors。当您执行this.x = new Date(); this.x.setDate(this.x.getDate() + 7);时,this.x会跟踪日期对象而不是其值,因此Vue将看不到更改。您需要先克隆日期,设置一个新日期,然后将其重新分配this.x(请参见下面的navigationWeeks方法)。
  • 监视在您想要对单个特定的属性更改做出反应时很有用,在这种情况下,动态startWeek是一个理想的选择。如果更改某件事的事实比 what 更为重要,请使用updated钩子(典型用例:使用新参数销毁并重新初始化第三方库窗口小部件)。
  • 计算对于始终保持同步从另一个属性派生的属性很有用,在您的示例中,endDate总是在startDate之后7天,因此一个完美的候选人。在代码段中,我还为HTML日期输入期望的ISO日期格式使用了计算值。
    • 最后,您可以使用setTimeout,一些CSS关键帧以及切换.transitioning类来做相当高级的事情

Vue.component('fading-date', {
  template: `
    <span><input :class="className" type="date" :value="htmlValue"></span>
  `,
  props: {
    value: { type: Date },
    fadeDuration: { type: Number, default: 1 }
  },
  data() { 
    return { transitioning: false, timer: null };
  },
  computed: {
    htmlValue() {
      return this.value.toISOString().split('T')[0];
    },
    className() {
      return this.transitioning ? 'transitioning' : '';
    }
  },
  watch: {
    value() {
      clearTimeout(this.timer);
      this.transitioning = true;
      this.timer = setTimeout(() => {
        this.transitioning = false;
      }, 1000 * this.fadeDuration);
    }
  }
});

new Vue({
  el: '#app',
  data: {
    selectedWeek: new Date()
  },
  computed: {
    weekAfterSelected() {
      const date = this.selectedWeek;
      const endDate = new Date(date);
      endDate.setDate(date.getDate() + 7);
      return endDate;
    }
  },
  methods: {
    navigateWeeks(numWeeks = 1) {
      const newDate = new Date(this.selectedWeek);
      newDate.setDate(newDate.getDate() + (7 * numWeeks));
      this.selectedWeek = newDate;
    }
  }
});
input[type="date"] {
  background: transparent;
  border: none;
}

@keyframes fade{
  0% {
    opacity:1;
  }
  50% {
    opacity:0;
  }
  100% {
    opacity:1;
  }
}


.transitioning {
  animation: fade ease-out 1s;
  animation-iteration-count: infinite;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <fading-date :value="selectedWeek" :fade-duration="1"></fading-date>
  <fading-date :value="weekAfterSelected" :fade-duration="1"></fading-date>
  <br>
  <button type="button" @click="navigateWeeks(-1)">A week sooner</button>
  <button type="button" @click="navigateWeeks(1)">A week later</button>
</div>