<template> <spanv-once> Make it never change: {{ count }}</span> </template>
1.2 切换器
这个挑战开始,我们将尝试编写可组合函数,让我们从 useToggle 开始 👇:
<scriptsetuplang="ts"> import { ref } from"vue"; /** * Implement a composable function that toggles the state * Make the function work correctly */ functionuseToggle(value) { const state = ref(value); consttoggle = () => { state.value = !state.value; }; return [state, toggle]; } const [state, toggle] = useToggle(false); </script>
<scriptsetuplang="ts"> import { ref, watchEffect } from"vue"; /** * Implement the composable function * Make sure the function works correctly */ functionuseLocalStorage(key: string, initialValue: any) { const value = ref(localStorage.getItem(key) ?? initialValue); watchEffect(() =>localStorage.setItem(key, value.value)); return value; } const counter = useLocalStorage("counter", 0); // We can get localStorage by triggering the getter: console.log(counter.value); // And we can also set localStorage by triggering the setter: constupdate = () => counter.value++; </script>
<scriptsetuplang="ts"> /** * Implement the custom directive * Make sure the `onClick` method only gets triggered once when clicked many times quickly * And you also need to support the debounce delay time option. e.g `v-debounce-click:ms` * */ constVDebounceClick = { mounted: (el: HTMLElement, binding: { value: Function; arg: number }) => { el.addEventListener("click", debounce(binding.value, binding.arg)); }, }; functiondebounce(fn: Function, delay: number) { let timer = null; let clickCount = 0; returnfunction () { clickCount++; if (clickCount === 1) returnvoidfn(); if (timer) clearTimeout(timer); timer = setTimeout(function () { fn(); }, delay); }; } functiononClick() { console.log("Only triggered once when clicked many times quickly"); } </script>
<template> <buttonv-debounce-click:200="onClick">Click on it many times quickly</button> </template>
1.8 函数式组件
在这个挑战中,我们将尝试实现一个函数式组件,让我们开始吧 👇:
<scriptsetuplang="ts"> import { ref, h } from"vue"; /** * Implement a functional component : * 1. Render the list elements (ul/li) with the list data * 2. Change the list item text color to red when clicked. */ constListComponent = (props, { emit }) => { // 使用 map 方法遍历列表数据,并为每个数据项创建一个 <li> 元素 returnh( "ul", {}, props.list.map((item, index) => h( "li", { style: index === props["active-index"] ? { color: "red" } : null, // 如果当前列表项是选中的,将其文本颜色设置为红色 onClick: () =>toggle(index), // 为 <li> 元素添加点击事件处理函数 }, item.name ) ) ); }; const list = [ { name: "John", }, { name: "Doe", }, { name: "Smith", }, ]; const activeIndex = ref(0); functiontoggle(index: number) { activeIndex.value = index; } </script>
<template> <!-- Add key modifiers made this will fire even if Alt or Shift is also pressed --> <button @click.alt="onClick1" @click.shift="onClick1">A</button>
<!-- Add key modifiers made this will only fire when Shift and no other keys are pressed --> <button @click.shift.exact="onCtrlClick">A</button>
<!-- Add key modifiers made this will only fire when no system modifiers are pressed --> <button @click.exact="onClick2">A</button> </template>
<stylescoped> p { font-size: 20px; color: red; text-align: center; line-height: 50px; } /* Make it work */ :global(body) { width: 100vw; height: 100vh; background-color: burlywood; } </style>
1.13 原始值 API
在这个挑战中,你将使用 响应式 API: [xx]Raw 来完成它。 以下是你要实现的内容 👇:
<scriptsetuplang="ts"> import { reactive, toRaw, isReactive, markRaw } from"vue"; const state = { count: 1 }; const reactiveState = reactive(state); /** * Modify the code so that we can make the output be true. */ console.log(toRaw(reactiveState) === state); /** * Modify the code so that we can make the output be false. */ const info = markRaw({ count: 1 }); const reactiveInfo = reactive(info); console.log(isReactive(reactiveInfo)); </script>