следить за изменениями и обновлять форматированное представление с помощью объекта даты - PullRequest
0 голосов
/ 08 января 2019

Я пытаюсь сделать навигацию по дням. Поэтому мне нужно две кнопки «предыдущий» и «следующий день», чтобы изменить форматированную дату.

[ <<PREV ]    DD-MM-YYY (weekday)   [ NEXT >> ]

И у меня проблема, потому что моя дневная переменная является объектом Date. Я пытался вычислить, методы и наблюдатели, но не простое решение.

Проект работает хорошо с дополнительными переменными, но должен быть лучший способ сделать этот простой компонент.

Вот что у меня есть:

let app = new Vue({
  el: "#app",
  data: {
    day: new Date(),
    dayFormated: "not set",
    number: 1
  },
  computed: {
    dateFormated: function() {
      // computed values are cached 
      return this.showFormatedDate(this.day);
    }
  },
  watch: {
    day: {
      handler: function(val, oldVal) {
        // this is not working at all
        console("day changed");
        this.dayFormated = this.showFormatedDate(this.day);
      },
      deep: true
    },
    number: function(val) {
      // this updates dayFormated but this can't be best solution
      // and dayFormated is not set at the begining
      // this.dayFormated = this.showFormatedDate(this.day);
    }
  },
  methods: {
    previous: function() {
      console.log("prev");
      // when next line commented method showFormatedDate is not updating
      this.number--; 
      this.day.setDate(this.day.getDate() - 1);
    },
    next: function() {
      console.log("next");
      // when next line commented method showFormatedDate is not updating
      this.number++;
      this.day.setDate(this.day.getDate() + 1);
    },
    showFormatedDate: function(date) {
      let formated = date.toLocaleDateString(["pl-PL"], {
        day: "2-digit",
        month: "2-digit",
        year: "numeric"
      });
      formated +=
        " (" + date.toLocaleDateString(["pl-PL"], { weekday: "long" }) + ")";
      return formated;
    }
  }
});
.container {
  padding-top: 2rem;
}

.column {
  text-align: center;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app" class="container">  
  
  <h1 class="subtitle has-centered-text">number: {{number}}</h1>
  
  <div class="columns">
    
      <div class="column">
        <button class="button is-large is-fullwidth" @click="previous">PREV</button>    
      </div> 
    
      <div class="column">data:<br>{{day}}</div>
      <div class="column">computed:<br>{{dateFormated}}</div>
      <div class="column">method:<br>{{showFormatedDate(day)}}</div>
      <div class="column">watch:<br>{{dayFormated}}</div>
    
      <div class="column">
        <button class="button is-large is-fullwidth" @click="next">NEXT</button>  
      </div>  
    
  </div>
</div>

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Это не работает, потому что Vue не смотрит на мутации внутри объектов ( Реакционная способность Vue в глубине: Предупреждение об изменении обнаружения ).

Эти 2 строки изменяют объект day, но Vue не видит изменений, потому что ссылка на объект (this.day) остается неизменной:

this.day.setDate(this.day.getDate() - 1);
this.day.setDate(this.day.getDate() + 1);

Если вы измените это на присвоение нового объекта, это сработает, потому что теперь ссылка на this.day изменилась, и Vue заметит измененное значение:

this.day = new Date(this.day.setDate(this.day.getDate() - 1));
this.day = new Date(this.day.setDate(this.day.getDate() + 1));

Ручка с исправленным рабочим кодом здесь .

0 голосов
/ 08 января 2019

Это первый раз, когда я работаю с Vue.

Я добавил Момент в ваши отделы, потому что это позволяет легко форматировать дату так, как вы хотите.

Думаю, я сократил это до довольно простого решения. Я столкнулся с проблемой, когда Vue не реагировал на изменение даты, когда я сохранял дату как мгновенный объект (даже с this.$set(this, 'date', this.date.add(1, 'day') или добавлением глубокого наблюдателя), поэтому я отказался от этого подхода и сохранил дату вместо этого в качестве метки времени Unix (секунд эпохи), которая отлично работает:

let app = new Vue({
  el: "#app",
  data: {
    date: moment().startOf('day').unix()
  },
  methods: {
    dateString: function() {
      return moment.unix(this.date).format('DD-MM-YYYY (dddd)');
    },
    previous: function() {
      this.date = moment.unix(this.date).subtract(1, 'day').unix();
    },
    next: function() {
      this.date = moment.unix(this.date).add(1, 'day').unix();
    }
  }
});
.container {
  padding-top: 2rem;
}

.column {
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app" class="container">  
  <div class="columns">
      <div class="column">
        <button class="button is-large is-fullwidth" @click="previous">PREV</button>    
      </div> 
      <div class="column">{{ dateString() }}</div>
      <div class="column">
        <button class="button is-large is-fullwidth" @click="next">NEXT</button>  
      </div>  
    
  </div>
</div>

Примечание: нажмите Run code snipet, а затем Full Page (справа), чтобы увидеть демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...