mirror of https://github.com/vuejs/core.git
feat(playground): todo mvc
This commit is contained in:
parent
359a5dab19
commit
0255505b5d
|
@ -7,6 +7,7 @@
|
||||||
"build": "node ./setup/vite.js build"
|
"build": "node ./setup/vite.js build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@vueuse/core": "^10.7.2",
|
||||||
"vue": "workspace:*"
|
"vue": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue/vapor'
|
import { computed } from 'vue/vapor'
|
||||||
|
import { useLocalStorage } from '@vueuse/core'
|
||||||
interface Task {
|
interface Task {
|
||||||
title: string
|
title: string
|
||||||
completed: boolean
|
completed: boolean
|
||||||
}
|
}
|
||||||
const tasks = ref<Task[]>([])
|
|
||||||
const value = ref('hello')
|
const tasks = useLocalStorage<Task[]>('tasks', [])
|
||||||
|
const value = useLocalStorage('value', '')
|
||||||
|
|
||||||
|
const remaining = computed(() => {
|
||||||
|
return tasks.value.filter(task => !task.completed).length
|
||||||
|
})
|
||||||
|
|
||||||
function handleAdd() {
|
function handleAdd() {
|
||||||
tasks.value.push({
|
tasks.value.push({
|
||||||
|
@ -16,31 +21,76 @@ function handleAdd() {
|
||||||
// TODO: clear input
|
// TODO: clear input
|
||||||
value.value = ''
|
value.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleComplete(index: number, evt: Event) {
|
||||||
|
tasks.value[index].completed = (evt.target as HTMLInputElement).checked
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClearComplete() {
|
||||||
|
tasks.value = tasks.value.filter(task => !task.completed)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClearAll() {
|
||||||
|
tasks.value = []
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<h1>todos</h1>
|
||||||
<ul>
|
<ul>
|
||||||
<!-- TODO: v-for -->
|
<!-- TODO: v-for -->
|
||||||
<li>
|
<li v-show="tasks[0]" :class="{ del: tasks[0]?.completed }">
|
||||||
<!-- TODO checked=false -->
|
<input
|
||||||
<input type="checkbox" :checked="tasks[0]?.completed" />
|
type="checkbox"
|
||||||
|
:checked="tasks[0]?.completed"
|
||||||
|
@change="handleComplete(0, $event)"
|
||||||
|
/>
|
||||||
{{ tasks[0]?.title }}
|
{{ tasks[0]?.title }}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li v-show="tasks[1]" :class="{ del: tasks[1]?.completed }">
|
||||||
<input type="checkbox" :checked="tasks[1]?.completed" />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
:checked="tasks[1]?.completed"
|
||||||
|
@change="handleComplete(1, $event)"
|
||||||
|
/>
|
||||||
{{ tasks[1]?.title }}
|
{{ tasks[1]?.title }}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li v-show="tasks[2]" :class="{ del: tasks[2]?.completed }">
|
||||||
<input type="checkbox" :checked="tasks[2]?.completed" />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
:checked="tasks[2]?.completed"
|
||||||
|
@change="handleComplete(2, $event)"
|
||||||
|
/>
|
||||||
{{ tasks[2]?.title }}
|
{{ tasks[2]?.title }}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li v-show="tasks[3]" :class="{ del: tasks[3]?.completed }">
|
||||||
<input type="checkbox" :checked="tasks[3]?.completed" />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
:checked="tasks[3]?.completed"
|
||||||
|
@change="handleComplete(3, $event)"
|
||||||
|
/>
|
||||||
{{ tasks[3]?.title }}
|
{{ tasks[3]?.title }}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
<input type="text" v-model="value" />
|
|
||||||
<button @click="handleAdd">Add</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
<p>
|
||||||
|
{{ remaining }} item{{ remaining !== 1 ? 's' : '' }} left /
|
||||||
|
{{ tasks.length }} item{{ tasks.length !== 1 ? 's' : '' }} in total
|
||||||
|
</p>
|
||||||
|
<div style="display: flex; gap: 8px">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="value"
|
||||||
|
@keydown.enter="handleAdd"
|
||||||
|
placeholder="What need to be done?"
|
||||||
|
/>
|
||||||
|
<button @click="handleAdd">Add</button>
|
||||||
|
<button @click="handleClearComplete">Clear completed</button>
|
||||||
|
<button @click="handleClearAll">Clear all</button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.del {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -6,6 +6,9 @@ import * as CompilerVapor from '@vue/compiler-vapor'
|
||||||
import * as CompilerSFC from '@vue/compiler-sfc'
|
import * as CompilerSFC from '@vue/compiler-sfc'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
resolve: {
|
||||||
|
alias: [{ find: /^vue$/, replacement: 'vue/vapor' }],
|
||||||
|
},
|
||||||
build: {
|
build: {
|
||||||
target: 'esnext',
|
target: 'esnext',
|
||||||
},
|
},
|
||||||
|
@ -20,4 +23,7 @@ export default defineConfig({
|
||||||
DevPlugin(),
|
DevPlugin(),
|
||||||
Inspect(),
|
Inspect(),
|
||||||
],
|
],
|
||||||
|
optimizeDeps: {
|
||||||
|
exclude: ['@vueuse/core'],
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -454,6 +454,9 @@ importers:
|
||||||
|
|
||||||
playground:
|
playground:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@vueuse/core':
|
||||||
|
specifier: ^10.7.2
|
||||||
|
version: 10.7.2(vue@packages+vue)
|
||||||
vue:
|
vue:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../packages/vue
|
version: link:../packages/vue
|
||||||
|
@ -1346,6 +1349,10 @@ packages:
|
||||||
resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==}
|
resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/web-bluetooth@0.0.20:
|
||||||
|
resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/yauzl@2.10.2:
|
/@types/yauzl@2.10.2:
|
||||||
resolution: {integrity: sha512-Km7XAtUIduROw7QPgvcft0lIupeG8a8rdKL8RiSyKvlE7dYY31fEn41HVuQsRFDuROA8tA4K2UVL+WdfFmErBA==}
|
resolution: {integrity: sha512-Km7XAtUIduROw7QPgvcft0lIupeG8a8rdKL8RiSyKvlE7dYY31fEn41HVuQsRFDuROA8tA4K2UVL+WdfFmErBA==}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
|
@ -1641,6 +1648,31 @@ packages:
|
||||||
resolution: {integrity: sha512-BK9D7AgpYAWVrtd7Kkc3CotU/ox8l+mPjsLgK16ZP+Ldj8jXPrJtzYQ2rTQNRJOxVSVx5acftDTLDLENFhQdDw==}
|
resolution: {integrity: sha512-BK9D7AgpYAWVrtd7Kkc3CotU/ox8l+mPjsLgK16ZP+Ldj8jXPrJtzYQ2rTQNRJOxVSVx5acftDTLDLENFhQdDw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@vueuse/core@10.7.2(vue@packages+vue):
|
||||||
|
resolution: {integrity: sha512-AOyAL2rK0By62Hm+iqQn6Rbu8bfmbgaIMXcE3TSr7BdQ42wnSFlwIdPjInO62onYsEMK/yDMU8C6oGfDAtZ2qQ==}
|
||||||
|
dependencies:
|
||||||
|
'@types/web-bluetooth': 0.0.20
|
||||||
|
'@vueuse/metadata': 10.7.2
|
||||||
|
'@vueuse/shared': 10.7.2(vue@packages+vue)
|
||||||
|
vue-demi: 0.14.6(vue@packages+vue)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@vue/composition-api'
|
||||||
|
- vue
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@vueuse/metadata@10.7.2:
|
||||||
|
resolution: {integrity: sha512-kCWPb4J2KGrwLtn1eJwaJD742u1k5h6v/St5wFe8Quih90+k2a0JP8BS4Zp34XUuJqS2AxFYMb1wjUL8HfhWsQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@vueuse/shared@10.7.2(vue@packages+vue):
|
||||||
|
resolution: {integrity: sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==}
|
||||||
|
dependencies:
|
||||||
|
vue-demi: 0.14.6(vue@packages+vue)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@vue/composition-api'
|
||||||
|
- vue
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@zeit/schemas@2.29.0:
|
/@zeit/schemas@2.29.0:
|
||||||
resolution: {integrity: sha512-g5QiLIfbg3pLuYUJPlisNKY+epQJTcMDsOnVNkscrDP1oi7vmJnzOANYJI/1pZcVJ6umUkBv3aFtlg1UvUHGzA==}
|
resolution: {integrity: sha512-g5QiLIfbg3pLuYUJPlisNKY+epQJTcMDsOnVNkscrDP1oi7vmJnzOANYJI/1pZcVJ6umUkBv3aFtlg1UvUHGzA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -6284,6 +6316,21 @@ packages:
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/vue-demi@0.14.6(vue@packages+vue):
|
||||||
|
resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
|
peerDependencies:
|
||||||
|
'@vue/composition-api': ^1.0.0-rc.1
|
||||||
|
vue: ^3.0.0-0 || ^2.6.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@vue/composition-api':
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
vue: link:packages/vue
|
||||||
|
dev: false
|
||||||
|
|
||||||
/w3c-xmlserializer@5.0.0:
|
/w3c-xmlserializer@5.0.0:
|
||||||
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
|
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
Loading…
Reference in New Issue