Added proper demo incl. vue-router

This commit is contained in:
lstoeferle 2021-02-26 23:12:33 +01:00
parent 2d22e7b59b
commit 42b6229dfe
31 changed files with 410 additions and 196 deletions

View File

@ -1,9 +1,33 @@
# vite-vue2-example
# Vite ⚡ - Vue 2 starter template
Example project for a Vue 2 SPA using Vite and composition API
This starter template will help you to easily create a Vue2 application bundled by the lightning fast build tool called [Vite](https://github.com/vitejs/vite). Besides Vite this template also provides:
* Typescript support
* Vue Router
* Vue Composition-API
* WindiCSS (TailwindCSS) + Dark Mode
## :package: Vite plugins
* [`vite-plugin-vue2`](https://github.com/underfin/vite-plugin-vue2) -
Vue 2 support for Vite
* [`vite-plugin-components`](https://github.com/antfu/vite-plugin-components) -
On demand components auto importing for Vite
* [`vite-plugin-windicss`](https://github.com/windicss/vite-plugin-windicss) -
WindiCSS/TailwindCSS for Vite
## :rocket: Getting started
1. Install dependencies
```bash
npm install
```
2. Start dev server
```bash
npm run dev
```
3. Visit the page
<a href="http://localhost:8080" target="_blank">http://localhost:8080</a>
## Vite plugins
* [`vite-plugin-vue2`](https://github.com/underfin/vite-plugin-vue2)
* [`vite-plugin-components`](https://github.com/antfu/vite-plugin-components)
* [` vite-plugin-windicss`](https://github.com/windicss/vite-plugin-windicss)

View File

@ -7,7 +7,7 @@
<link rel="icon" href="/favicon.ico">
<title>Example</title>
</head>
<body>
<body class="dark:bg-gray-800">
<noscript>
<strong>We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>

13
package-lock.json generated
View File

@ -12,7 +12,8 @@
"@vueuse/core": "4.2.2",
"core-js": "3.9.0",
"typescript": "4.1.5",
"vue": "2.6.12"
"vue": "2.6.12",
"vue-router": "3.5.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "4.15.2",
@ -4844,6 +4845,11 @@
"node": ">=6.0.0"
}
},
"node_modules/vue-router": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.1.tgz",
"integrity": "sha512-RRQNLT8Mzr8z7eL4p7BtKvRaTSGdCbTy2+Mm5HTJvLGYSSeG9gDzNasJPP/yOYKLy+/cLG/ftrqq5fvkFwBJEw=="
},
"node_modules/vue-template-compiler": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz",
@ -8770,6 +8776,11 @@
}
}
},
"vue-router": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.1.tgz",
"integrity": "sha512-RRQNLT8Mzr8z7eL4p7BtKvRaTSGdCbTy2+Mm5HTJvLGYSSeG9gDzNasJPP/yOYKLy+/cLG/ftrqq5fvkFwBJEw=="
},
"vue-template-compiler": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz",

View File

@ -14,7 +14,8 @@
"@vueuse/core": "4.2.2",
"core-js": "3.9.0",
"typescript": "4.1.5",
"vue": "2.6.12"
"vue": "2.6.12",
"vue-router": "3.5.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "4.15.2",

View File

@ -1,8 +1,8 @@
<template>
<div id="app" class="pt-15 flex flex-col items-center dark:bg-gray-800">
<HeroSection />
<FeatureSection />
<EnvSection />
<CompositionSection />
<div id="app">
<Navbar />
<main id="app">
<router-view />
</main>
</div>
</template>

1
src/assets/not-found.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

2
src/assets/vue-logo.svg Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 261.76 226.69" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 -76.311 313.34)"><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-75.491l98.16-170.02 98.16 170.02z" fill="#41b883"/></g><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-36.227l58.896-102.01 58.896 102.01z" fill="#34495e"/></g></g></svg>

After

Width:  |  Height:  |  Size: 467 B

View File

@ -1,24 +0,0 @@
<template>
<section
class="flex flex-col items-center text-gray-600 body-font container px-5 py-12 mx-auto"
>
<Heading2> Composition API </Heading2>
<p class="mt-8 dark:text-gray-400">
Switch to the dark side
<ButtonPrimary class="ml-4" @click.native="toggle">Toggle</ButtonPrimary>
</p>
</section>
</template>
<script lang="ts">
import { useDark, useToggle } from "@vueuse/core";
import { defineComponent } from "vue-demi";
export default defineComponent({
name: "CompositionSection",
setup: () => {
const toggle = useToggle(useDark());
return { toggle };
},
});
</script>

View File

@ -1,42 +0,0 @@
<template>
<section
class="flex flex-col items-center text-gray-600body-font container px-5 py-12 mx-auto"
>
<Heading2> Environment Variables </Heading2>
<p class="dark:text-gray-400">
To learn more about env variablels in Vite click
<a
class="text-purple-500"
target="_blank"
href="https://vitejs.dev/guide/env-and-mode.html"
>here</a
>
</p>
<div class="flex flex-row items-center mt-8">
<select
v-model="selectedKey"
class="bg-purple-500 text-white rounded-lg p-2 focus:outline-none"
>
<option v-for="key in Object.keys(env)" :key="key" :value="key">
{{ key }}
</option>
</select>
<p class="ml-8 dark:text-white">
{{ env[selectedKey] }}
</p>
</div>
</section>
</template>
<script lang="ts">
import { ref, defineComponent } from "vue-demi";
export default defineComponent({
name: "EnvComponent",
setup: () => {
const env = import.meta.env;
const selectedKey = ref(Object.keys(env)[0] || "");
return { env, selectedKey };
},
});
</script>

View File

@ -0,0 +1,36 @@
<template>
<div
class="flex flex-col h-full p-8 bg-gray-100 rounded-lg items dark:bg-gray-700"
>
<Heading2>
{{ title }}
</Heading2>
<div class="flex flex-col flex-grow">
<p class="flex-grow text-base leading-relaxed dark:text-gray-300">
{{ text }}
</p>
<a
:href="url"
target="_blank"
class="inline-flex items-center mt-3 text-green-500"
>
Learn More
<IconArrow />
</a>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue-demi";
export default defineComponent({
name: "Feature",
props: {
title: { type: String, required: true },
text: { type: String, required: true },
url: { type: String, required: true },
},
});
</script>

View File

@ -1,30 +0,0 @@
<template>
<section class="text-gray-600 body-font container px-5 py-12 mx-auto">
<div class="flex flex-col text-center w-full mb-8">
<Heading2> Installed Vite plugins </Heading2>
</div>
<div class="flex flex-wrap -m-4">
<div class="pr-4 py-4 xs:pl-4 md:w-1/3 w-full">
<Feature
title="vite-plugin-vue2"
text="Vue 2 support for Vite"
url="https://github.com/underfin/vite-plugin-vue2"
/>
</div>
<div class="p-4 md:w-1/3 w-full">
<Feature
title="vite-plugin-components"
text="On demand components auto importing for Vite"
url="https://github.com/antfu/vite-plugin-components"
/>
</div>
<div class="pl-4 py-4 xs:pr-4 md:w-1/3 w-full">
<Feature
title="vite-plugin-windicss"
text="Windi CSS for Vit"
url="https://github.com/windicss/vite-plugin-windicss"
/>
</div>
</div>
</section>
</template>

View File

@ -0,0 +1,40 @@
<template>
<section class="container px-5 py-12 mx-auto text-gray-600 body-font">
<div class="flex flex-col w-full mb-8 text-center">
<Heading1> Installed Vite plugins 📦 </Heading1>
<p class="dark:text-gray-300">
You can even find more awesome Vite plugins
<a
href="https://github.com/vitejs/awesome-vite"
target="_blank"
class="text-green-500"
>
here
</a>
</p>
</div>
<div class="flex flex-wrap -m-4">
<div class="w-full py-4 pr-4 xs:pl-4 md:w-1/3">
<Feature
title="vite-plugin-vue2"
text="Vue 2 support for Vite"
url="https://github.com/underfin/vite-plugin-vue2"
/>
</div>
<div class="w-full p-4 md:w-1/3">
<Feature
title="vite-plugin-components"
text="On demand components auto importing for Vite"
url="https://github.com/antfu/vite-plugin-components"
/>
</div>
<div class="w-full py-4 pl-4 xs:pr-4 md:w-1/3">
<Feature
title="vite-plugin-windicss"
text="Windi CSS for Vite"
url="https://github.com/windicss/vite-plugin-windicss"
/>
</div>
</div>
</section>
</template>

31
src/components/Hero.vue Normal file
View File

@ -0,0 +1,31 @@
<template>
<section
class="container flex flex-col items-center px-5 py-12 mx-auto text-gray-600 body-font md:flex-row"
>
<div class="w-5/6 mb-10 lg:max-w-lg lg:w-full md:w-1/2 md:mb-0">
<img
class="object-cover object-center rounded"
alt="Vue logo"
src="@/assets/vue-logo.svg"
/>
</div>
<div
class="flex flex-col items-center text-center lg:flex-grow md:w-1/2 lg:pl-24 md:pl-16 md:items-start md:text-left"
>
<Heading1> Vite - Vue 2 starter template </Heading1>
<p class="mb-8 leading-relaxed dark:text-gray-300">
This example project shows how to speed up your Vue 2 application with
the next generation frontend tooling Vite.
</p>
<div class="flex justify-center">
<a href="https://vuejs.org/v2/guide/" target="_blank">
<ButtonPrimary> Vue docs </ButtonPrimary>
</a>
<router-link :to="{ name: 'About' }">
<ButtonSecondary> About </ButtonSecondary>
</router-link>
</div>
</div>
</section>
</template>

View File

@ -1,31 +0,0 @@
<template>
<section
class="text-gray-600 body-font container mx-auto flex py-12 md:flex-row flex-col items-center px-5"
>
<div class="lg:max-w-lg lg:w-full md:w-1/2 w-5/6 mb-10 md:mb-0">
<img
class="object-cover object-center rounded"
alt="Vite logo"
src="@/assets/logo.svg"
/>
</div>
<div
class="lg:flex-grow md:w-1/2 lg:pl-24 md:pl-16 flex flex-col md:items-start md:text-left items-center text-center"
>
<Heading1> Vite - Vue 2 example </Heading1>
<p class="mb-8 leading-relaxed dark:text-gray-400">
This example project shows how to speed up your Vue 2 application with
the next generation frontend tooling Vite.
</p>
<div class="flex justify-center">
<a href="https://vitejs.dev/guide/" target="_blank">
<ButtonPrimary> Vite docs </ButtonPrimary>
</a>
<a href="https://vuejs.org/v2/guide/" target="_blank">
<ButtonSecondary> Vue docs </ButtonSecondary>
</a>
</div>
</div>
</section>
</template>

78
src/components/Navbar.vue Normal file
View File

@ -0,0 +1,78 @@
<template>
<header class="text-gray-600 body-font dark:bg-gray-800">
<div
class="container flex flex-col flex-wrap items-center p-5 mx-auto md:flex-row"
>
<router-link
:to="{ name: 'Home' }"
class="flex items-center mb-4 font-medium text-gray-900 title-font md:mb-0"
>
<img alt="Vite logo" src="@/assets/vite-logo.svg" width="36px" />
<span class="ml-3 text-xl dark:text-white">
{{ appName }}
</span>
</router-link>
<nav
class="flex flex-wrap items-center justify-center text-base md:ml-auto"
>
<router-link
v-for="(route, index) in routes"
:key="index"
class="mr-5 font-semibold cursor-pointer"
:class="{
'text-green-500 hover:green-500 dark:text-green-500 dark:hover:text-green-500 underline':
route.name === currentRoute,
'hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-200':
route.name != currentRoute,
}"
:to="{ name: route.name }"
>
{{ route.name }}
</router-link>
<router-link
class="flex items-center justify-center mr-2 text-black w-9 h-9 dark:text-white"
to="/aliens"
>
<IconAlien />
</router-link>
<a
href="https://github.com/lstoeferle/vite-vue2-windicss-starter"
target="_blank"
class="flex items-center justify-center mr-2 text-black w-9 h-9 dark:text-white"
>
<IconGithub />
</a>
<button
@click="toggle"
class="flex items-center justify-center w-9 h-9 focus:outline-none"
:class="{ 'text-yellow-500': isDark, 'text-gray-800': !isDark }"
>
<IconSun v-if="isDark" />
<IconMoon v-else />
</button>
</nav>
<div></div>
</div>
</header>
</template>
<script lang="ts">
import { computed, defineComponent } from "vue-demi";
import { routes } from "@/router";
import { useDark, useToggle } from "@vueuse/core";
export default defineComponent({
setup: (_, ctx) => {
// Import config from .evn
const appName = import.meta.env.VITE_APP_NAME;
const availableRoutes = routes.filter((route) => route.name != "NotFound");
const currentRoute = computed(() => ctx.root.$route.name);
const isDark = useDark();
const toggle = useToggle(isDark);
return { appName, routes: availableRoutes, currentRoute, toggle, isDark };
},
});
</script>

View File

@ -0,0 +1,8 @@
<template>
<svg focusable="false" width="1em" height="1em" viewBox="0 0 24 24">
<path
d="M12 3c4.97 0 9 3.58 9 8s-6 10-9 10s-9-5.58-9-10s4.03-8 9-8m-1.69 7.93C9.29 9.29 7.47 8.58 6.25 9.34c-1.22.76-1.38 2.71-.36 4.35c1.03 1.64 2.85 2.35 4.07 1.59c1.22-.78 1.37-2.71.35-4.35m3.38 0c-1.02 1.64-.87 3.57.35 4.35c1.22.76 3.04.05 4.07-1.59c1.02-1.64.86-3.59-.36-4.35c-1.22-.76-3.04-.05-4.06 1.59M12 17.75c-2 0-2.5-.75-2.5-.75c0 .03.5 2 2.5 2s2.5-2 2.5-2s-.5.75-2.5.75z"
fill="currentColor"
></path>
</svg>
</template>

View File

@ -0,0 +1,13 @@
<template>
<svg
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
class="w-4 h-4 ml-2"
viewBox="0 0 24 24"
>
<path d="M5 12h14M12 5l7 7-7 7"></path>
</svg>
</template>

View File

@ -0,0 +1,8 @@
<template>
<svg focusable="false" width="1em" height="1em" viewBox="0 0 24 24">
<path
d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33c.85 0 1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2z"
fill="currentColor"
></path>
</svg>
</template>

View File

@ -0,0 +1,20 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
focusable="false"
role="img"
class="iconify iconify--mdi"
width="1em"
height="1em"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 24 24"
style="transform: rotate(360deg)"
>
<path
d="M2 12a10 10 0 0 0 13 9.54a10 10 0 0 1 0-19.08A10 10 0 0 0 2 12z"
fill="currentColor"
></path>
</svg>
</template>

View File

@ -0,0 +1,20 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
focusable="false"
role="img"
class="iconify iconify--mdi"
width="1em"
height="1em"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 24 24"
style="transform: rotate(360deg)"
>
<path
d="M3.55 18.54l1.41 1.41l1.8-1.79l-1.42-1.42M11 22.45h2V19.5h-2m1-14a6 6 0 0 0-6 6a6 6 0 0 0 6 6a6 6 0 0 0 6-6c0-3.32-2.69-6-6-6m8 7h3v-2h-3m-2.76 7.66l1.8 1.79l1.41-1.41l-1.79-1.8m1.79-12.28l-1.41-1.41l-1.8 1.79l1.42 1.42M13 .55h-2V3.5h2m-9 7H1v2h3m2.76-7.66l-1.8-1.79l-1.41 1.41l1.79 1.8l1.42-1.42z"
fill="currentColor"
></path>
</svg>
</template>

View File

@ -1,6 +1,6 @@
<template>
<button
class="inline-flex text-white bg-purple-500 border-0 py-2 px-6 focus:outline-none hover:bg-purple-600 rounded text-lg"
class="inline-flex px-6 py-2 text-lg text-white bg-green-500 border-0 rounded focus:outline-none hover:bg-green-400"
>
<slot />
</button>

View File

@ -1,6 +1,6 @@
<template>
<button
class="ml-4 inline-flex text-gray-700 bg-gray-100 border-0 py-2 px-6 focus:outline-none hover:bg-gray-200 rounded text-lg"
class="inline-flex px-6 py-2 ml-4 text-lg text-gray-700 bg-gray-200 border-0 rounded focus:outline-none hover:bg-gray-100"
>
<slot />
</button>

View File

@ -1,45 +0,0 @@
<template>
<div
class="flex rounded-lg h-full bg-gray-100 p-8 flex-col items dark:bg-gray-700"
>
<Heading3>
{{ title }}
</Heading3>
<div class="flex flex-col flex-grow">
<p class="flex-grow leading-relaxed text-base dark:text-gray-400">
{{ text }}
</p>
<a
:href="url"
target="_blank"
class="mt-3 text-indigo-500 inline-flex items-center"
>Learn More
<svg
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
class="w-4 h-4 ml-2"
viewBox="0 0 24 24"
>
<path d="M5 12h14M12 5l7 7-7 7"></path>
</svg>
</a>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue-demi";
export default defineComponent({
name: "Feature",
props: {
title: { type: String, required: true },
text: { type: String, required: true },
url: { type: String, required: true },
},
});
</script>

View File

@ -1,6 +1,6 @@
<template>
<h2
class="sm:text-3xl text-2xl font-medium title-font text-gray-900 dark:text-white"
class="text-lg font-medium text-gray-900 sm:text-xl title-font dark:text-white"
>
<slot />
</h2>

View File

@ -1,7 +0,0 @@
<template>
<h3
class="sm:text-xl text-lg font-medium title-font text-gray-900 dark:text-white"
>
<slot />
</h3>
</template>

View File

@ -3,11 +3,13 @@ import App from "@/App.vue";
import { createApp, h } from "vue-demi";
import "windi.css";
import router from "@/router";
Vue.config.productionTip = false;
Vue.config.devtools = true;
const app = createApp({
router,
render: () => h(App),
});

37
src/router/index.ts Normal file
View File

@ -0,0 +1,37 @@
import Vue from "vue";
import VueRouter, { RouteConfig } from "vue-router";
import Home from "@/views/Home.vue";
import About from "@/views/About.vue";
import NotFound from "@/views/NotFound.vue";
Vue.use(VueRouter);
export const routes: RouteConfig[] = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/about",
name: "About",
// NOTE: you can also apply meta information
// meta: {authRequired: false }
component: About,
// NOTE: you can also lazy-load the component
// component: () => import("@/views/About.vue")
},
{
path: "/:path(.*)",
name: "NotFound",
component: NotFound,
},
];
const router = new VueRouter({
base: "/",
mode: "history",
routes,
});
export default router;

29
src/views/About.vue Normal file
View File

@ -0,0 +1,29 @@
<template>
<section class="text-gray-600 body-font">
<div
class="container flex flex-col items-center justify-center px-5 py-24 mx-auto"
>
<div class="w-full text-center lg:w-2/3">
<Heading1> About: Vite - Vue 2 starter template </Heading1>
<p class="mb-8 leading-relaxed dark:text-gray-300">
This starter template will help you to easily create a Vue2
application bundled by the lightning fast build tool called Vite.
Besides Vite this template also provides typescript support,
TailwindCSS, vue-router and the vue composition-api for Vue2.
</p>
<div class="flex justify-center">
<a
href="https://github.com/lstoeferle/vite-vue2-windicss-starter"
target="_blank"
>
<button
class="inline-flex items-center px-6 py-2 text-lg text-white bg-black border-0 rounded focus:outline-none hover:bg-gray-900"
>
<IconGithub /> &nbsp;GitHub
</button>
</a>
</div>
</div>
</div>
</section>
</template>

6
src/views/Home.vue Normal file
View File

@ -0,0 +1,6 @@
<template>
<div>
<Hero />
<Features />
</div>
</template>

26
src/views/NotFound.vue Normal file
View File

@ -0,0 +1,26 @@
<template>
<section class="text-gray-600 body-font">
<div
class="container flex flex-col items-center justify-center px-5 py-24 mx-auto"
>
<img
class="object-cover object-center w-5/6 mb-10 rounded lg:w-2/6 md:w-3/6"
alt="hero"
src="@/assets/not-found.svg"
/>
<div class="w-full text-center lg:w-2/3">
<Heading1 class="text-red-500 dark:text-red-500"
>404 NOT FOUND</Heading1
>
<p class="mb-8 leading-relaxed dark:text-gray-300">
Oops, looks like you got kidnapped by aliens.
</p>
<div class="flex justify-center">
<router-link :to="{ name: 'Home' }">
<ButtonPrimary> Bring me back Home </ButtonPrimary>
</router-link>
</div>
</div>
</div>
</section>
</template>