抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

在 22 年刚创建个人主页的时候,由于我的技术水平不够,只能用一些 wordpress typecho 这种直观的工具,后来因为换域名等等一系列的问题就被搁置了…再后来为了过备案,用图形化工具和 bootstrap 糊了一个,而如今熟练掌握 Vue 和 React 等框架之后,也到了完全重写的时候了,于是就有了这段记录。

关键词:Vue SSR,Nuxt.js

网页的开发一直在持续哇…本文章会持续跟进更新

最后链接:https://www.grtsinry43.com/

框架选择

首先,对于这种主页类的网站,单纯的 Vue React SPA(单页面应用)肯定是不行的,比如说这里我们使用 pure-admin 模板创建的一个后台系统(Vue3),对于搜索引擎来说不会等待页面完全加载和渲染,而抓到的这些内容无法分析网站的关键词和主题等,导致很难被搜索引擎排名考前,因此我们不得不从历史中汲取经验,从服务端生成静态网页,到了客户端渲染的单页面应用,又回到了服务端渲染

这样是很难做好 SEO 的

对于个人主页这种比较小的项目,我更喜欢使用 Vue 来完成开发,也就是其对应的 SSR 框架——Nuxt.js

快速上手

由于要使用 NuxtUI,我们便可以使用官方的创建工程的脚手架

1
npx nuxi@latest init -t ui [项目名称]

创建好项目之后,我们便可以像正常写 Vue 一样来进行开发啦

前置准备工作

在代码块以及项目名称中,我们选用一个等宽而且适用于代码的字体 JetBrains Mono,于是我们可以在 assets/fonts.css 中这样进行引入

1
2
3
4
5
6
7
8
9
10
11
@font-face {
font-family: 'JetBrains Mono';
src: url('https://gcore.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Medium.woff2') format('woff2');
font-weight: 500;
font-style: normal;
}

.font-jb-mono {
/* 设置fallback防止出现宋体 */
font-family: 'JetBrains Mono', 'Courier New', Courier, 'Lucida Sans Typewriter', 'Lucida Console', 'Microsoft YaHei', 'WenQuanYi Micro Hei', monospace;
}

注意这里要设置好 fallback 字体,因为某些 Windows 系统(雾)默认会回落到宋体,导致中文字体不堪入目

以后当我们需要使用的时候只需要挂上这个类名就好

防止掉头发

经典防止掉头发几件套:assets/global.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

a {
text-decoration: none;
color: inherit;
}

ul {
list-style: none;
}

疑难解决方案与创新点

桌面与移动端导航栏适配

为了达到最完美的使用效果,我直接写了 NavBarNavBarMobile 两个组件,通过简单的媒体查询来进行切换

1
2
3
4
5
6
7
8
9
@media (max-width: 800px) {
.nav-bar-desktop {
display: none;
}

.nav-bar-mobile {
display: block;
}
}

对于移动段的 Navbar,我选择了可收起菜单来优化体验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
const toggleMenu = () => {
isMenuOpen.value = !isMenuOpen.value
}

const toggleLocale = () => {
locale.value = locale.value === 'en' ? 'zh' : 'en';
};
</script>

<template>
<div
class="nav-container fixed w-full bg-opacity-80 bg-blue-50 text-blue-950 dark:bg-opacity-80 dark:bg-black dark:text-white">
<UContainer class="flex flex-row items-center justify-between nav-inner">
<div class="nav-logo">
<NuxtLink :to="localePath('/')" class="font-bold">{{ $t('homePageTitle') }}</NuxtLink>
</div>
<!-- Toggle Button for Mobile Menu -->
<UButton class="lg:hidden bg-opacity-0 dark:bg-opacity-0" @click="toggleMenu"
icon="i-heroicons:bars-3-bottom-right"
square
color="gray"
>
</UButton>
<!-- Theme Toggle Button -->
<div class="theme-option lg:block">
<UToggle
on-icon="i-heroicons-moon-20-solid"
off-icon="i-heroicons-sun-20-solid"
:model-value="colorMode.preference === 'dark'"
@change="toggleTheme"
/>
</div>
<!-- Icons Container -->
<div class="actions-container hidden lg:grid">
<Icon class="language-toggle-icon hover:text-blue-400 dark:hover:text-blue-600" name="i-heroicons-language" @click="toggleLocale"/>
<Icon class="rss-icon hover:text-blue-400 dark:hover:text-blue-600" name="i-heroicons-rss"/>
<a href="https://github.com/grtsinry43/home-web" target="_blank">
<Icon class="github-icon hover:text-blue-400 dark:hover:text-blue-600" name="i-grommet-icons:github"/>
</a>
</div>
</UContainer>

<!-- Mobile Navigation Menu -->
<div v-show="isMenuOpen"
class="nav-extend-container flex flex-col items-center bg-blue-50 bg-opacity-85 dark:bg-black dark:bg-opacity-80 backdrop-blur-lg">
这里就是菜单项目啦
</div>
</div>
</template>

深浅色模式的极不优雅解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import {onMounted} from "vue";
const colorMode = useColorMode();

const toggleTheme = () => {
if (colorMode.preference === 'system') {
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark';
buttonState.value = colorMode.preference === 'dark';
} else {
colorMode.preference = colorMode.preference === 'dark' ? 'light' : 'dark';
buttonState.value = colorMode.preference === 'dark';
}
};

const buttonState = ref(false);

onMounted(() => {
// 根据最开始的主题设置按钮的图标
buttonState.value = colorMode.value === 'dark';
})

这里深色模式的实现有点太不优雅了,我发现 NuxtUI 官网确实有一个跟随主题的开关,但是自己实现起来就是很奇怪,对于输出的 colorMode 有两个用的上的属性,一个是 preference 对应偏好主题(light dark system),一个是 value 对应当前主题(light dark),由于偏好能被保存下来,于是选择在切换按钮时改变 preference 的对应的值

当组件被挂载(onMounted),首先根据 value 设置初始的状态,当点击切换时,对于当前是否偏好系统要采取不同的方式来切换,不知道大佬们有没有什么好办法,或者过几天我再看看 Nuxt 源码

评论

在这里留下你的评论吧~