# 使用 Vue 3 + Element Plus 从头开始写一个数据库网站 - 08 - 使用动态配置编写组件:以页脚美化为例
由于 PrismJS 尚不支持 Vue 的语法高亮,因此 Vue 代码块均先使用 HTML 的高亮
2024-09-23
在前面,我们为了方便,在根组件 ADDB/src/App.vue
中简单写了一个页脚
<el-footer class="footer"> | |
<p>© 2024 Alzheimer's Disease Biomarker Database. All rights reserved.</p> | |
</el-footer> |
现在,我们来美化这个页脚
布局上,我们仍然参考 PubChem 的多列布局,第一列包含组织 Logo、地点、版权声明等信息,其他列包含关于、导航、联系等信息,并为每列添加小标题
# 编写页脚组件
为了方便以后复用,我们以组件的形式来编写一个 PageFooter.vue
文件
新建 ADDB/src/components/PageFooter.vue
文件
<template> | |
<el-footer class="footer"> | |
<div class="footer-container"> | |
<!-- 第一列:组织信息 --> | |
<div class="footer-column"> | |
<img src="/gdph.png" alt="Organization Logo" class="footer-logo" /> | |
<p>Address: No. 106, Zhongshan 2nd Road, Guangzhou</p> | |
<p>© 2024 ADDB. ALL RIGHTS RESERVED</p> | |
</div> | |
<!-- 第二列:关于 --> | |
<div class="footer-column"> | |
<h3>About</h3> | |
<ul> | |
<li><a href="/about">Our Mission</a></li> | |
<li><a href="/about/team">Our Team</a></li> | |
<li><a href="/about/careers">Careers</a></li> | |
</ul> | |
</div> | |
<!-- 第三列:导航 --> | |
<div class="footer-column"> | |
<h3>Navigation</h3> | |
<ul> | |
<li><a href="/">Home</a></li> | |
<li><a href="/biomarkers">Biomarkers</a></li> | |
<li><a href="/test">Test</a></li> | |
</ul> | |
</div> | |
<!-- 第四列:联系 --> | |
<div class="footer-column"> | |
<h3>Contact</h3> | |
<p>Email: <a href="mailto:support@addb.com">support@addb.com</a></p> | |
<p>Phone: +1 (234) 567-890</p> | |
<p>Twitter: <a href="https://twitter.com" target="_blank">@addb</a></p> | |
</div> | |
</div> | |
</el-footer> | |
</template> | |
<script setup> | |
// 引入所需资源(如图标库或其他样式可在此引入) | |
</script> | |
<style scoped> | |
.footer { | |
background-color: #333; | |
color: #fff; | |
padding: 40px 20px; | |
height: auto; | |
} | |
.footer-container { | |
display: flex; | |
flex-wrap: wrap; | |
justify-content: space-between; | |
max-width: 1200px; | |
margin: 0 auto; | |
} | |
.footer-column { | |
flex: 1; | |
min-width: 200px; | |
/* 最小列宽,方便响应式 */ | |
margin: 0 20px; | |
} | |
.footer-column h3 { | |
margin-bottom: 15px; | |
font-size: 18px; | |
font-weight: bold; | |
color: #f1f1f1; | |
} | |
.footer-column ul { | |
list-style: none; | |
padding: 0; | |
margin: 0; | |
} | |
.footer-column ul li { | |
margin-bottom: 10px; | |
} | |
.footer-column ul li a { | |
color: #ddd; | |
text-decoration: none; | |
} | |
.footer-column ul li a:hover { | |
text-decoration: underline; | |
} | |
.footer-logo { | |
height: 55px; | |
margin-bottom: 10px; | |
} | |
@media (max-width: 768px) { | |
.footer-container { | |
flex-direction: column; | |
text-align: center; | |
} | |
.footer-column { | |
margin-bottom: 30px; | |
} | |
} | |
</style> |
# 实现细节
- 列划分:
- 使用
flex
布局,flex: 1
让每列平均分布。 - 设置
min-width: 200px
确保在小屏幕时列不会太窄。
- 使用
- 第一列:组织信息
- 包括
Logo
图片、地址、版权声明。 - Logo 样式通过
.footer-logo
控制。
- 包括
- 其他列:关于、导航、联系
- 每列用
h3
标题表示功能区名称。 - 链接用
<ul><li><a></a></li></ul>
结构实现,易于扩展。
- 每列用
- 样式优化:
- 在桌面端,列均分排列;在移动端,通过
@media
查询切换为垂直布局。
- 在桌面端,列均分排列;在移动端,通过
- 响应式设计:
- 在小屏幕(宽度 <768px)下,列堆叠显示,保证可读性。
# 使用组件
在根组件 ADDB/src/App.vue
中的 <script setup>
中添加
import PageFooter from '@/components/PageFooter.vue'; |
或者
import PageFooter from './components/PageFooter.vue'; |
@
表示别名,通常指向项目的 src
目录。在我们项目的 vite.config.js
中通过 resolve.alias
定义:
import { fileURLToPath, URL } from 'node:url' | |
import { defineConfig } from 'vite' | |
import vue from '@vitejs/plugin-vue' | |
// https://vitejs.dev/config/ | |
export default defineConfig({ | |
plugins: [ | |
vue(), | |
], | |
resolve: { | |
alias: { | |
'@': fileURLToPath(new URL('./src', import.meta.url)) | |
} | |
}, | |
}) |
这样做的优点是,即使文件被深层嵌套,不需要写长长的相对路径(如 ../../../
)。此外,当路径修改时,可以避免维护复杂的相对路径。
然后将原来的页脚
<el-footer class="footer"> | |
<p>© 2024 Alzheimer's Disease Biomarker Database. All rights reserved.</p> | |
</el-footer> |
替换为
<PageFooter /> |
并删去原来的页脚样式,即可看到我们新编写的页脚
# 动态配置形式的实现
除了第一列,我们的页脚格式都是相似的,因此对于后几列,我们可以共用一个模板,然后通过传入数据来填充
首先修改 PageFooter.vue
文件
<template> | |
<el-footer class="footer"> | |
<div class="footer-container"> | |
<!-- 静态列 --> | |
<div class="footer-column"> | |
<img src="/gdph.png" alt="Organization Logo" class="footer-logo" /> | |
<p>Address: No. 106, Zhongshan 2nd Road, Guangzhou</p> | |
<p>© 2024 ADDB. ALL RIGHTS RESERVED</p> | |
</div> | |
<!-- 动态生成列 --> | |
<div v-for="column in props.columns" :key="column.title" class="footer-column"> | |
<!-- 动态渲染标题 --> | |
<h3 v-if="column.title">{{ column.title }}</h3> | |
<!-- 动态渲染内容 --> | |
<template v-if="column.type === 'text'"> | |
<p v-for="(text, idx) in column.content" :key="idx">{{ text }}</p> | |
</template> | |
<template v-else-if="column.type === 'links'"> | |
<ul> | |
<li v-for="(link, idx) in column.content" :key="idx"> | |
<a :href="link.href" :target="link.target || '_self'"></a> | |
</li> | |
</ul> | |
</template> | |
<template v-else-if="column.type === 'image'"> | |
<img :src="column.content.src" :alt="column.content.alt" class="footer-logo" /> | |
</template> | |
</div> | |
</div> | |
</el-footer> | |
</template> |
在 <script setup>
中定义列的类型
<script setup> | |
import { defineProps } from "vue"; | |
// 定义列的默认类型 | |
const props = defineProps({ | |
columns: { | |
type: Array, | |
required: true, | |
}, | |
}); | |
</script> |
在根组件 App.vue
中,我们在 <script setup>
中传入数据
const footerColumns = [ | |
{ | |
title: "About", | |
type: "links", | |
content: [ | |
{ text: "Our Mission", href: "/about" }, | |
{ text: "Our Team", href: "/about/team" }, | |
{ text: "Careers", href: "/about/careers" }, | |
], | |
}, | |
{ | |
title: "Navigation", | |
type: "links", | |
content: [ | |
{ text: "Home", href: "/" }, | |
{ text: "Biomarkers", href: "/biomarkers" }, | |
{ text: "Test", href: "/test" }, | |
], | |
}, | |
{ | |
title: "Contact", | |
type: "text", | |
content: [ | |
"Email: support@addb.com", | |
"Phone: +1 (234) 567-890", | |
"Twitter: @addb", | |
], | |
}, | |
]; |
至此,我们已经完成了一个数据库网站的框架。
🌸完结撒花🌸