setInterval() в Vue делает мою переменную this неопределенной

#vue.js

#vue.js

Вопрос:

Привет, итак, я создаю базовые часы в Vue, и по какой-то причине с помощью этого кода я получаю начальное значение времени bazinga , но как только оно обновляется, оно указывает, что оно не определено. Мне удалось «заставить это работать», если я также определяю now и другие переменные внутри setInterval() функции, но это не кажется хорошим выбором. Почему this.bazinga после первой итерации становится неопределенным?

 <template>
    <div id="clock">
        <h2>The time is now</h2>
        <p>{{ bazinga }}</p>
        
    </div>
</template>

<style>

</style>

<script>
export default {
    data(){
        const now = new Date()
        const hours = now.getHours()
        const minutes = now.getMinutes()
        const seconds = now.getSeconds()
        return{
            bazinga: now
        }
    },
    created() {
         setInterval(() => {
            console.log(this.bazinga)
            this.bazinga = this.now
            console.log(this.bazinga)
        }, 1000)
    },
    destroyed() {
        clearInterval(this.now)
    }
}
</script>
  

Комментарии:

1. this.now не определено, потому что вы не включили это свойство ни в один data из или computed prop, поэтому this.bazinga = this.now оно будет this.bazinga неопределенным.

Ответ №1:

Все ваши const переменные внутри data свойства не зарегистрированы как данные компонента, это просто переменные, доступные в data блоке.

Я полагаю, вы хотите получать обновленную new Date() информацию при каждом вызове this.now ?

Я бы предложил что-то вроде этого:

 <script>
export default {
    data(){
        return{
            now: new Date();
        }
    },
    computed {
      hours: function() {
          return this.now.getHours()
      }
      minutes: function() {
          return this.now.getMinutes()
      },
      seconds: function() {
          return this.now.getSeconds()
      }
    },
    created() {
         setInterval(() => {
            console.log(this.bazinga)
            this.updateNow()
            console.log(this.bazinga)
        }, 1000)
    },
    updateNow() {
       this.now = new Date()
    }
    destroyed() {
        clearInterval(this.now)
    }
}
</script>
  

Каждый вызов updateNow() будет получать новую дату, а также обновлять все вычисленные данные. 🙂

Комментарии:

1. Ну ладно, спасибо! Почему переменные не зарегистрированы как данные для моего компонента, даже если они находятся в блоке data()? В чем разница между переменными, определенными в блоке данных, и данными компонента в блоке данных?

2. data Свойство — это функция, которая должна возвращать объект, содержащий все свойства, которые вам нужны в вашем компоненте (и их начальные значения). Из вашего кода вы вернули только объект с bazinga в качестве свойства, поэтому он единственный зарегистрированный!

3. Помимо синтаксической ошибки, вам нужно определить updateNow() как метод, тогда он работает

4. О, да, извините. Я привык к компоненту на основе класса Typescript, поэтому мне не нужно указывать methods объект. Извините за это!

Ответ №2:

 <template>
    <div id="clock">
        The Time is Now {{bazinga}}
    </div>

</template>

<script>
export default {
    data(){
        return {
            hours: 0,
            minutes: 0,
            seconds: 0,
            hoursDisplay: 0,
            secondIterator: 1000,
            hourTime: 12,
        }
    },
    mounted() {
        this.$options.timer = window.setTimeout(this.updateDateTime, this.secondIterator);
    },
    destroyed() {
        window.clearTimeout(this.$options.timer);
    },
    methods: {
        updateDateTime() {
            const now = new Date();
            this.hours = now.getHours();
            this.minutes = this.zeroPad(now.getMinutes());
            this.seconds = this.zeroPad(now.getSeconds());
            this.hoursDisplay = this.hours % this.hourTime || this.hours;
            this.$options.timer = window.setTimeout(this.updateDateTime, this.secondIterator);
        },
        zeroPad: function (time) {
            return (parseInt(time, 10) >= 10 ? '' : '0')   time;
        }
    },
    computed: {
        amPm: function () {
            if (this.hours) {
                return this.hours >= 12 ? 'PM' : 'AM';
            }
        },
        bazinga: function () {
            if (this.amPm) {
                return [this.hoursDisplay, this.minutes, this.seconds].join(':')   ' '   this.amPm;
            }

        },
    }
}
</script>
  

Я создал здесь компонент clock, но в основном вы всегда хотите использовать реквизиты данных внутри своих компонентов и получать к ним доступ с помощью this.someproperty . Вы также можете использовать наблюдатели или вычисляемые свойства, чтобы возвращать их обработанными, как я сделал здесь .