Skip to content

Commit 50d20f9

Browse files
committed
feat: add vue-3 app demo
1 parent 197cf8f commit 50d20f9

5 files changed

Lines changed: 128 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ steps.
88
* [Hono 4](./hono-4/)
99
* [Preact 10](./preact-10/)
1010
* [Solid 1](./solid-1/)
11+
* [Vue 3](./vue-3/)

deno.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
{
2-
"workspace": ["./angular-*", "./hono-*", "./preact-*", "./solid-*"],
2+
"workspace": [
3+
"./angular-*",
4+
"./hono-*",
5+
"./preact-*",
6+
"./solid-*",
7+
"./vue-*"
8+
],
39
"imports": {
410
"jsonplaceholder-types/": "https://esm.sh/*jsonplaceholder-types@1.0.2&dev/"
511
},

vue-3/App.vue

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<script setup lang="ts">
2+
import { onWatcherCleanup, ref, reactive, watchEffect } from "vue";
3+
4+
const urlBase = "https://jsonplaceholder.typicode.com";
5+
6+
const selectedUserId = ref();
7+
const users = reactive({ value: undefined, loading: false });
8+
const posts = reactive({ value: undefined, loading: false });
9+
10+
watchEffect(function fetchUsers() {
11+
users.loading = true;
12+
const controller = new AbortController();
13+
onWatcherCleanup(() => controller.abort());
14+
15+
fetch(`${urlBase}/users`, { signal: controller.signal })
16+
.then(async (response) => {
17+
users.value = await response.json();
18+
})
19+
.catch((error) => {
20+
if (!(error instanceof DOMException && error.name === "AbortError")) {
21+
throw error;
22+
}
23+
})
24+
.finally(() => {
25+
users.loading = false;
26+
});
27+
});
28+
29+
watchEffect(function fetchPosts() {
30+
if (selectedUserId.value === undefined) return;
31+
posts.loading = true;
32+
const controller = new AbortController();
33+
onWatcherCleanup(() => controller.abort());
34+
35+
fetch(`${urlBase}/posts?userId=${selectedUserId.value}`, {
36+
signal: controller.signal,
37+
})
38+
.then(async (response) => {
39+
posts.value = await response.json();
40+
})
41+
.catch((error) => {
42+
if (!(error instanceof DOMException && error.name === "AbortError")) {
43+
throw error;
44+
}
45+
})
46+
.finally(() => {
47+
posts.loading = false;
48+
});
49+
});
50+
</script>
51+
52+
<template>
53+
<h1>Buildless Vue 3 app</h1>
54+
<label v-if="users.value">
55+
Select User:
56+
<select v-model.number="selectedUserId">
57+
<option hidden selected></option>
58+
<option v-for="user in users.value" :key="user.id" :value="user.id">
59+
@{{ user.username }}: {{ user.name }}
60+
</option>
61+
</select>
62+
</label>
63+
<p v-else-if="users.loading">Loading Users...</p>
64+
<ul v-if="posts.value">
65+
<li v-for="post in posts.value" :key="post.id">{{ post.title }}</li>
66+
</ul>
67+
<p v-else-if="posts.loading">Loading Posts...</p>
68+
<p v-else-if="users.value">Select User to view posts</p>
69+
<p>
70+
Data Source:
71+
<a href="https://jsonplaceholder.typicode.com/" target="_blank">
72+
JSONPlaceholder
73+
</a>
74+
</p>
75+
</template>

vue-3/deno.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"imports": {
3+
"@vue/compiler-sfc": "https://esm.sh/*@vue/compiler-sfc@3.5.24?dev",
4+
"@vue/reactivity": "https://esm.sh/*@vue/reactivity@3.5.24?dev",
5+
"@vue/runtime-core": "https://esm.sh/*@vue/runtime-core@3.5.24?dev",
6+
"@vue/runtime-dom": "https://esm.sh/*@vue/runtime-dom@3.5.24?dev",
7+
"@vue/shared": "https://esm.sh/*@vue/shared@3.5.24?dev",
8+
"vue": "https://esm.sh/*vue@3.5.24?dev",
9+
"vue/": "https://esm.sh/*vue@3.5.24&dev/"
10+
}
11+
}

vue-3/index.html

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>Buildless Vue 3 app</title>
6+
<script type="importmap">
7+
{
8+
"imports": {
9+
"@vue/compiler-sfc": "https://esm.sh/*@vue/compiler-sfc@3.5.24?dev",
10+
"@vue/reactivity": "https://esm.sh/*@vue/reactivity@3.5.24?dev",
11+
"@vue/runtime-core": "https://esm.sh/*@vue/runtime-core@3.5.24?dev",
12+
"@vue/runtime-dom": "https://esm.sh/*@vue/runtime-dom@3.5.24?dev",
13+
"@vue/shared": "https://esm.sh/*@vue/shared@3.5.24?dev",
14+
"vue": "https://esm.sh/*vue@3.5.24?dev",
15+
"vue/": "https://esm.sh/*vue@3.5.24&dev/"
16+
}
17+
}
18+
</script>
19+
<script type="module">
20+
import { createApp, defineAsyncComponent } from "vue";
21+
import loadModule from "https://esm.sh/@vuebro/loader-sfc@2.3.31?external=vue";
22+
23+
Object.assign(globalThis, {
24+
__VUE_OPTIONS_API__: true,
25+
__VUE_PROD_DEVTOOLS__: false,
26+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
27+
});
28+
29+
const App = defineAsyncComponent(() => loadModule("./App.vue"));
30+
createApp(App).mount(document.body);
31+
</script>
32+
</head>
33+
<body></body>
34+
</html>

0 commit comments

Comments
 (0)