wxj 的 Vue Challenges题解

Easy

Lifecycle Hooks

For this challenge, you'll use the Composition API: Lifecycle Hooks to complete the challenge. Here's what you need to implement 👇:

// Child.vue

<script setup lang="ts">
import { onMounted, inject } from "vue"

const timer = inject('timer')
const count = inject('count')


onMounted(() => {
  // The timer will work abnormally when the child component is toggled. Lets fix it.
  timer.value = window.setInterval(() => {
    count.value++
  }, 1000)
})

</script>

<template>
  <div>
    <p>
      Child Component: {{ count }}
    </p>
  </div>
</template>

问题: 多次点击 toggle 按钮后, 计时显示错误(每秒多次增加) 原因: 使用v-if每次都会创建一个新实例新的 interval 会增加至之前存在的实例上, 造成异常快速增加计数

题解: 1): 在组件取消挂载时清除计数

<script setup lang="ts">
import { onMounted, inject, onUnmounted } from "vue"

const timer = inject("timer")
const count = inject("count")

onMounted(() => {
  timer.value = window.setInterval(() => {
    count.value++
  }, 1000)
})

onUnmounted(() => {
  window.clearInterval(timer.value);
})
</script>

<template>
  <div>
    <p>
      Child Component: {{ count }}
    </p>
  </div>
</template>

2): 将v-if改成v-show (v-show 使用 css 实现组件的显示, 不会创建新实例)

Next DOM update flush

When you mutate a reactive state in Vue.js, the resulting DOM updates are not applied synchronously.

<script setup>
import { ref } from "vue"

const count = ref(0)

function increment() {
  count.value++

  /**
   * DOM is not yet updated, how can we make sure that the DOM gets updated
   * Make the output be true
  */

  console.log(+document.getElementById("counter").textContent === 1)
}
</script>

<template>
  <button id="counter" @click="increment">
    {{ count }}
  </button>
</template>

题解: 调用nextTick(), 有两种写法

  1. async/await
  2. 将需要进行的操作作函数传入nextTick()
<script setup>
import { ref, nextTick } from "vue"

const count = ref(0)

async function increment() {
  count.value++
  await nextTick();
  console.log(+document.getElementById("counter").textContent === 1)
}
</script>

<template>
  <button id="counter" @click="increment">
    {{ count }}
  </button>
</template>