Groyreg
@Groyreg
Front-end

Куда лучше записать данные с вычисляемыми переменными?

Добрый день. Хочу в компоненте сделать объект, который при изменении будет пересчитываться автоматически.
Объект выглядит так:
dataCalendar: {
			curDate: '',
			curMonth: '',
			curYear: '',
			curDay: '',
			firstDay: '',
			lastDay: '',
			weekDay: '',
			oneHour: '',
			oneDay: '',
			dateNextMonth: '',
			weekName: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
			monthName: ["Январь","Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"],
}


Назначить этим переменным значения прямо в data: не получается пишет ошибку:
TypeError: _vm.dataCalendar is undefined


Пробовал назначать через функцию в computed, но тогда данные не рендерятся адекватно.
В итоге сделал через mounted:
mounted: function(){
  	this.dataCalendar.curDate = new Date();
	this.dataCalendar.curMonth = this.dataCalendar.curDate.getUTCMonth();
	this.dataCalendar.curYear = this.dataCalendar.curDate.getFullYear();
	this.dataCalendar.curDay = this.dataCalendar.curDate.getDate();
	this.dataCalendar.firstDay = new Date(this.dataCalendar.curYear, this.dataCalendar.curMonth, 1);
	this.dataCalendar.weekDay = this.dataCalendar.firstDay.getDay();
	this.dataCalendar.oneHour = 1000 * 60 * 60;
	this.dataCalendar.oneDay = this.dataCalendar.oneHour * 24;
	this.dataCalendar.dateNextMonth = new Date(this.dataCalendar.curYear, this.dataCalendar.curMonth + 1, 1)
	this.dataCalendar.lastDay = Math.ceil((this.dataCalendar.dateNextMonth.getTime() - this.dataCalendar.firstDay.getTime() - this.dataCalendar.oneHour)/this.dataCalendar.oneDay); 
}


И в общем-то так работает, но столкнулся с проблемой, что при изменении, например, this.dataCalendar.curMonth переменная this.dataCalendar.firstDay уже не пересчитывается, хотя зависит от переменной this.dataCalendar.curMonth

Общая часть скрипта в компоненте:
<script>
import { dateTimeFormatter, isEqualDateStr} from '../tools.js'
import Vue from 'vue';
import {mapGetters} from 'vuex';

const inBrowser = typeof window !== 'undefined'
export default {
  name: 'cal-panel',
  data () {
    return {
     	shift: 0,
		curEventsDate:"all",
		dataCalendar: {
			curDate: '',
			curMonth: '',
			curYear: '',
			curDay: '',
			firstDay: '',
			lastDay: '',
			weekDay: '',
			oneHour: '',
			oneDay: '',
			dateNextMonth: '',
			weekName: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
			monthName: ["Январь","Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"],
		}
    }
  },
  props: {
    events: {
      type: Array,
      required: true
    },
    calendar: {
      type: Object,
      required: true
    },
    selectedDay: {
      type: String,
      required: false
    }
  },
  computed: {
 	activityTypes(){
 		return this.$store.state.diary.activity_types;
 	},
 	diaryActivities(){
 		return this.$store.state.diary.diary;
 	},
    dayList () {
        let startDate = new Date(this.dataCalendar.firstDay)
        let item, itemDay, status, tempArr = [], tempItem
        for (let i = 0 + this.shift ; i < 28 + this.shift; i++) {
            item = new Date(startDate);
            itemDay = item.getDay();
            item.setDate(startDate.getDate() + i);
            itemDay = item.getDay();

            if (this.dataCalendar.curMonth === item.getMonth()) {
              status = 1
            } else {
              status = 1
            }
            tempItem = {
              date: `${item.getFullYear()}/${item.getMonth()+1}/${item.getDate()}`,
              status: status,
              dayWeekNumber: itemDay,
              dayWeekName: this.dataCalendar.weekName[itemDay]
              
            }
            this.events.forEach((eventm) => {
              if (isEqualDateStr(eventm.date, tempItem.date)) {
                tempItem.id = eventm.id
                tempItem.date = eventm.date
                tempItem.activities = eventm.activities
              }
            })
            tempArr.push(tempItem)
        }
        return tempArr 
    },
    today () {
      let dateObj = new Date()
      return `${dateObj.getFullYear()}/${dateObj.getMonth()+1}/${dateObj.getDate()}`
    },
  },
  methods: {
    nextMonth () {
    	if (this.dataCalendar.curMonth < 11){
    		this.dataCalendar.curMonth++
    	} else {
        	this.dataCalendar.curYear++
        	this.dataCalendar.curMonth = 0
    	}
    	this.offset = 0
    },
    preMonth () {
     	if (this.dataCalendar.curMonth > 0) {
        	this.dataCalendar.curMonth--
     	} else {
        	this.dataCalendar.curYear--
        	this.dataCalendar.curMonth = 11
      	}
      	this.offset = 0
    },
    handleChangeCurday (date) {
      if (date.status) {
        this.$emit('cur-day-changed', date.date)
      }
    },
    changeDayListUp(val){
    	this.shift += val;
    	if(this.shift >= this.dataCalendar.lastDay){
    		this.shift = this.shift - this.dataCalendar.lastDay 
      		this.dataCalendar.curMonth.nextMonth()
    	}
    },
    changeDayListDown(val){
    	this.shift -= val;
    	if(this.shift <= 0){
    		this.shift = this.dataCalendar.lastDay - val
    		this.$EventCalendar.preMonth()
      		this.$emit('month-changed', this.curYearMonth)
      	}
      		
    }
  },
  mounted: function(){
  	this.dataCalendar.curDate = new Date();
	this.dataCalendar.curMonth = this.dataCalendar.curDate.getUTCMonth();
	this.dataCalendar.curYear = this.dataCalendar.curDate.getFullYear();
	this.dataCalendar.curDay = this.dataCalendar.curDate.getDate();
	this.dataCalendar.firstDay = new Date(this.dataCalendar.curYear, this.dataCalendar.curMonth, 1);
	this.dataCalendar.weekDay = this.dataCalendar.firstDay.getDay();
	this.dataCalendar.oneHour = 1000 * 60 * 60;
	this.dataCalendar.oneDay = this.dataCalendar.oneHour * 24;
	this.dataCalendar.dateNextMonth = new Date(this.dataCalendar.curYear, this.dataCalendar.curMonth + 1, 1)
	this.dataCalendar.lastDay = Math.ceil((this.dataCalendar.dateNextMonth.getTime() - this.dataCalendar.firstDay.getTime() - this.dataCalendar.oneHour)/this.dataCalendar.oneDay);
  }
}
</script>

Скажите, как правильно создать такой объект, чтобы он был реактивным?
  • Вопрос задан
  • 144 просмотра
Решения вопроса 1
0xD34F
@0xD34F Куратор тега Vue.js
this.dataCalendar.curMonth++

this.dataCalendar.curYear--

Страшно на такое смотреть. И ещё эти условия - curMonth < 11, curMonth > 0... Изменился месяц - надо поменять день (или не надо?), надо поменять год (или не надо - по-всякому бывает), поменять ещё чёрт знает что. Увеличили день - надо менять месяц, если это 30/31 число, иногда год - если было 31 декабря. Ну и т.д. и т.п.

Почему бы непосредственно не изменять ТОЛЬКО свойство даты - а все остальные пусть пересчитываются при изменении curDate? Вместо curMonth++ будет что-то вроде

curDate = new Date(curDate.setMonth(curDate.getMonth() + 1))

А остальные свойства из обычных станут вычисляемыми:

computed: {
  calendarData() {
    return {
      year: this.curDate.getFullYear(),
      month: this.curDate.getMonth(),
      // ...
    };
  }
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы