feat: Reusable Navbar Component (#63)

This commit is contained in:
CharleeWa 2024-03-05 00:18:46 +08:00
parent 8201254b5d
commit ef7f4cb5fc
15 changed files with 99 additions and 136 deletions

View File

@ -33,6 +33,7 @@ onMounted(() => {
<template>
<VanConfigProvider :theme="mode">
<NavBar />
<router-view v-slot="{ Component, route }">
<transition :name="routeTransitionName">
<div :key="route.name" class="app-wrapper">
@ -45,11 +46,11 @@ onMounted(() => {
<style scoped>
.app-wrapper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
position: absolute;
top: 46px;
left: 0;
overflow-y: auto;
}
</style>

2
src/components.d.ts vendored
View File

@ -8,7 +8,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
Chart: typeof import('./components/chart/index.vue')['default']
Container: typeof import('./components/container/index.vue')['default']
NavBar: typeof import('./components/NavBar.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
VanButton: typeof import('vant/es')['Button']

26
src/components/NavBar.vue Normal file
View File

@ -0,0 +1,26 @@
<script setup lang="ts">
const route = useRoute()
const router = useRouter()
function onBack() {
if (history.length > 1)
history.back()
else
router.replace('/')
}
const title = computed(() => {
const { title } = (route.meta as { title?: string }) || {}
return title || ''
})
</script>
<template>
<VanNavBar
v-show="title"
:title="title"
:fixed="true"
left-arrow clickable
@click-left="onBack"
/>
</template>

View File

@ -1,15 +0,0 @@
export interface SeriesDataItem {
x: any
y: any
}
export interface RadarDataItem {
label: string
name: string
value: string | number
}
export interface RadarIndicatorItem {
name: string
max: number
}

View File

@ -1,5 +0,0 @@
<template>
<div class="p-16 py-60">
<slot />
</div>
</template>

View File

@ -1,5 +0,0 @@
export { default as Container } from './container/index.vue'
// charts
export { default as Chart } from './chart/index.vue'
export type { SeriesDataItem, RadarDataItem, RadarIndicatorItem } from './chart/typing'

View File

@ -15,7 +15,3 @@ const router = useRouter()
</div>
</main>
</template>
<style scoped>
</style>

View File

@ -1,8 +1,8 @@
<template>
<main text="gray-700 dark:gray-200">
<main p="16" text="gray-700 dark:gray-200">
<RouterView />
<div mx-auto mt-15 text-center text-14 opacity-50>
<div mx-auto py-15 text-center text-14 opacity-50>
Default Layout
</div>
</main>

View File

@ -1,5 +1,5 @@
<template>
<main py-20 text="gray-700 dark:gray-200">
<main text="gray-700 dark:gray-200">
<RouterView />
<div mx-auto mt-15 text-center text-14 opacity-50>

View File

@ -3,6 +3,7 @@ definePage({
name: 'charts',
meta: {
level: 2,
title: '📊 Echarts 演示',
},
})
@ -62,38 +63,12 @@ const scoreOption = {
const refBarOption = ref(barOption)
const refLineOption = ref(lineOption)
const refScoreOption = ref(scoreOption)
// back
const onClickLeft = () => history.back()
</script>
<template>
<div>
<VanNavBar title="📊 Echarts" left-arrow fixed @click-left="onClickLeft" />
<Container>
<div class="chart">
<Chart :option="refBarOption" :style="{ height: '330px' }" />
</div>
<div class="chart item">
<Chart :option="refLineOption" :style="{ height: '330px' }" />
</div>
<div class="chart item">
<Chart :option="refScoreOption" :style="{ height: '330px' }" />
</div>
</Container>
<Chart :option="refBarOption" :style="{ height: '330px' }" />
<Chart :option="refLineOption" :style="{ height: '330px' }" />
<Chart :option="refScoreOption" :style="{ height: '330px' }" />
</div>
</template>
<style lang="less" scoped>
.chart {
width: 100%;
height: 300px;
}
.chart.item {
margin-top: 15px;
}
</style>

View File

@ -6,6 +6,7 @@ definePage({
name: 'counter',
meta: {
level: 2,
title: '🍍 持久化 Pinia 状态',
},
})
@ -15,29 +16,25 @@ const { counter } = storeToRefs(counterStore)
function add() {
counterStore.increment()
}
// back
const onClickLeft = () => history.back()
</script>
<template>
<div>
<VanNavBar title="🍍 持久化 Pinia 状态" left-arrow fixed @click-left="onClickLeft" />
<h1 class="text-6xl color-pink font-semibold">
Hello, Pinia!
</h1>
<Container>
<h1 class="text-6xl color-pink font-semibold">
Hello, Pinia!
</h1>
<p class="mt-4 text-gray-700 dark:text-white">
This is a simple example of persisting Pinia state.
To verify its effectiveness, you can refresh the interface and observe it.
</p>
<p class="mt-4">
number<strong class="text-green-500"> {{ counter }} </strong>
</p>
<button class="btn" @click="add">
Add
</button>
</Container>
<p class="mt-4 text-gray-700 dark:text-white">
This is a simple example of persisting Pinia state.
To verify its effectiveness, you can refresh the interface and observe it.
</p>
<p class="mt-4">
number<strong class="text-green-500"> {{ counter }} </strong>
</p>
<button class="btn" @click="add">
Add
</button>
</div>
</template>

View File

@ -23,6 +23,14 @@ function toggle() {
toggleDark()
appStore.swithMode(isDark.value ? 'dark' : 'light')
}
const menuItems = [
{ title: '💿 Mock 指南', route: 'mock' },
{ title: '📊 Echarts 演示', route: 'charts' },
{ title: '🎨 Unocss 示例', route: 'unocss' },
{ title: '🍍 持久化 Pinia 状态', route: 'counter' },
{ title: '🙅 404页 演示', route: 'unknown' },
]
</script>
<template>
@ -33,20 +41,9 @@ function toggle() {
</template>
</VanCell>
<VanCell title="💿 Mock 指南" to="mock" is-link />
<VanCell title="📊 Echarts 演示" to="charts" is-link />
<VanCell title="🎨 Unocss 示例" to="unocss" is-link />
<VanCell title="🍍 持久化 Pinia 状态" to="counter" is-link />
<VanCell title="🙅 404 演示" to="unknown" is-link />
<VanCell center>
<template #title>
<span class="mr-4 v-middle">🚀 欢迎补充</span>
<VanTag type="primary">
PR
</VanTag>
</template>
</VanCell>
<template v-for="item in menuItems" :key="item.route">
<VanCell :title="item.title" :to="item.route" is-link />
</template>
</VanCellGroup>
</template>

View File

@ -5,6 +5,7 @@ definePage({
name: 'mock',
meta: {
level: 2,
title: '💿 Mock 指南',
},
})
@ -18,36 +19,29 @@ function pull() {
// reset data
const reset = () => messages.value = ''
// back
const onClickLeft = () => history.back()
</script>
<template>
<div>
<VanNavBar title="💿 Mock 指南" left-arrow fixed @click-left="onClickLeft" />
<div class="data-label">
来自异步请求的数据
</div>
<Container>
<div class="data-label">
来自异步请求的数据
<div class="data-content bg-white dark:bg-[--van-background-2]">
<div v-if="messages">
{{ messages }}
</div>
<VanEmpty v-else description="暂无数据" />
</div>
<div class="data-content bg-white dark:bg-[--van-background-2]">
<div v-if="messages">
{{ messages }}
</div>
<VanEmpty v-else description="暂无数据" />
</div>
<van-space class="m-10" direction="vertical" fill>
<VanButton type="primary" round block @click="pull">
请求
</VanButton>
<VanButton type="default" round block @click="reset">
清空
</VanButton>
</van-space>
</Container>
<van-space class="m-10" direction="vertical" fill>
<VanButton type="primary" round block @click="pull">
请求
</VanButton>
<VanButton type="default" round block @click="reset">
清空
</VanButton>
</van-space>
</div>
</template>
@ -64,6 +58,7 @@ const onClickLeft = () => history.back()
padding: 20px;
line-height: 30px;
margin-top: 20px;
font-size: 16px;
border-radius: 15px;
display: flex;
align-items: center;

View File

@ -3,27 +3,23 @@ definePage({
name: 'unocss',
meta: {
level: 2,
title: '🎨 Unocss 示例',
},
})
// back
const onClickLeft = () => history.back()
</script>
<template>
<div>
<VanNavBar title="🎨 Unocss" left-arrow fixed @click-left="onClickLeft" />
<h1 class="text-6xl color-pink font-semibold">
Hello, Unocss!
</h1>
<Container>
<h1 class="text-6xl color-pink font-semibold">
Hello, Unocss!
</h1>
<p class="mt-4 text-gray-700 dark:text-white">
This is a simple example of Unocss in action.
</p>
<button class="btn">
Button
</button>
</Container>
<p class="mt-4 text-gray-700 dark:text-white">
This is a simple example of Unocss in action.
</p>
<button class="btn">
Button
</button>
</div>
</template>

View File

@ -20,6 +20,11 @@ html.dark {
box-sizing: border-box;
}
::-webkit-scrollbar {
width: 0;
background: transparent;
}
.slide-fadein-left-enter-active,
.slide-fadein-left-leave-active,
.slide-fadein-right-enter-active,