Skip to main content

vue 挑战

热身

1、你好!

https://cn-vuejs-challenges.netlify.app/questions/1-hello-word/README.zh-CN.html

将 msg 增加模版括号

<script setup>
import { ref } from "vue";
const msg = ref("Hello World");
</script>

<template>
<div>
<h1>{{msg}}</h1>
</div>
</template>

简单

1、生命周期钩子

问题:修复切换子组件后正常显示时间器

答案:因为销毁子组件后,时间器都没有清除。导致重新加载了子组件后,时间器又创建了新的,导致每次都会重叠多个时间器。所以,我们将每次销毁的时候,清除时间器即可。

// 修改 Child.vue
<script setup lang="ts">
import { onUnmounted, onMounted, inject } 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、下一次 DOM 更新

问题:能够获取到 dom 更新的真实元素

答案:因为值的更新是异步的,使用 nextTick 触发微任务。

详情查看官网:https://cn.vuejs.org/api/general.html#nexttick

<script setup>
import { nextTick, onMounted, ref } from "vue";

const count = ref(0);
const counter = ref(null);

function increment() {
count.value++;

/**
* DOM is not yet updated, how can we make sure that the DOM gets updated
* Make the output be true
*/
nextTick(() => {
console.log(+counter.value.textContent === 1);
});
}
</script>

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

3、DOM 传送门

问题:将插槽内容渲染到另一个 DOM 中

答案:使用 teleport,https://cn.vuejs.org/guide/built-ins/teleport.html

<script setup>
const msg = "Hello World";
</script>

<template>
<!-- Renders it to a child element of the `body` -->
<teleport to="body">
<span>{{ msg }}</span>
</teleport>
</template>

4、动态 CSS

问题:<style>  模块支持给 CSS 绑定动态值

答案:使用 v-bind 将 css 值动态绑定,https://cn.vuejs.org/api/sfc-css-features.html#v-bind-in-css

<script setup>
import { ref } from "vue";
const theme = ref("red");

const colors = ["blue", "yellow", "red", "green"];

setInterval(() => {
theme.value = colors[Math.floor(Math.random() * 4)];
}, 1000);
</script>

<template>
<p>hello</p>
</template>

<style scoped>
/* Modify the code to bind the dynamic color */
p {
color: v-bind(theme);
}
</style>

5、ref 全家桶

问题:通过 ref 实现数值的加减

答案:ref 的基本用法,https://cn.vuejs.org/api/reactivity-utilities.html#toref

<script setup lang="ts">
import { isRef, ref, Ref, reactive, toRef } from "vue";

const initial = ref(10);
const count = ref(0);

// Challenge 1: Update ref
function update(value) {
// impl...
count.value = value;
}

/**
* Challenge 2: Check if the `count` is a ref object.
* Make the output be 1
*/
console.log(
// impl ? 1 : 0
isRef(count) ? 1 : 0
);

/**
* Challenge 3: Unwrap ref
* Make the output be true
*/
function initialCount(value: number | Ref<number>) {
// Make the output be true
console.log(value === 10);
}

initialCount(initial.value);

/**
* Challenge 4:
* create a ref for a property on a source reactive object.
* The created ref is synced with its source property:
* mutating the source property will update the ref, and vice-versa.
* Make the output be true
*/
const state = reactive({
foo: 1,
bar: 2,
});
const fooRef = toRef(state, "foo"); // change the impl...

// mutating the ref updates the original
fooRef.value++;
console.log(state.foo === 2);

// mutating the original also updates the ref
state.foo++;
console.log(fooRef.value === 3);
</script>

<template>
<div>
<p>
<span @click="update(count - 1)">-</span>
{{ count }}
<span @click="update(count + 1)">+</span>
</p>
</div>
</template>

6、阻止事件冒泡

问题:点击了 click2,不要触发 click1

答案:https://cn.vuejs.org/guide/essentials/event-handling.html#event-modifiers

<script setup lang="ts">
const click1 = () => {
console.log("click1");
};

const click2 = () => {
console.log("click2");
};
</script>

<template>
<div @click="click1()">
<div @click.stop="click2()">click me</div>
</div>
</template>

7、响应性丟失

问题:如何在解构之后依旧保持响应性

答案:toRefs 包裹,https://cn.vuejs.org/api/reactivity-utilities.html#toref

<script setup lang="ts">
import { reactive, toRefs } from "vue";

function useCount() {
const state = reactive({
count: 0,
});

function update(value: number) {
state.count = value;
}

return {
state: toRefs(state),
update,
};
}
</script>

8、大写

问题:自定义修饰符 capitalize,实现输入的字符串首字母转成大写

答案:自定义指令,官网的案例,可以参考https://cn.vuejs.org/guide/components/v-model.html#handling-v-model-modifiers