⚠️ 提示
文章发布较早,内容可能过时,阅读注意甄别。

实现友链页面功能

本教程将指导你如何在 VitePress 主题中实现一个功能丰富的友链页面,包括随机访问、申请友链、头像滚动等功能,并集成 Twikoo 评论系统。

1. 准备工作

确保你已经完成以下步骤:

  1. 安装 VitePress 主题并配置好基础项目。
  2. 注册 Twikoo 服务并获取 envId(环境 ID)。

2. 创建友链组件

在主题的组件目录中创建一个 Vue 文件(如 SLink/index.vue),并添加以下代码:

  1<template>
  2  <div class="my-links-container">
  3    <!-- 页面主标题区域 -->
  4    <div class="my-links-title">
  5      <h1>{{ title }}</h1>
  6    </div>
  7    <!-- 顶部Banner区域 -->
  8    <div v-if="bannerShow" class="flink-banner" id="banners">
  9      <!-- 左上角smallTitle -->
 10      <div class="icon-heartbeat1 banners-small-title">
 11        {{ smallTitle }}
 12      </div>
 13
 14      <!-- 右上角功能按钮组 -->
 15      <div v-if="bannerButtonGroupShow" class="banner-button-group">
 16        <!-- 随机访问按钮 -->
 17        <button class="banner-button secondary" @click="handleRandomVisit" :disabled="allLinks.length === 0"
 18          aria-label="随机访问友链">
 19          <i class="icon-paper-plane" style="font-size: 18px;"></i>
 20          <span class="banner-button-text">随机访问</span>
 21        </button>
 22
 23        <!-- 申请友链按钮 -->
 24        <a class="banner-button primary" href="#post-comment" :disabled="!shouldShow" aria-label="申请友链">
 25          <i class="icon-link" style="font-size: 18px;"></i>
 26          <span class="banner-button-text">申请友链</span>
 27        </a>
 28      </div>
 29
 30      <!-- 两行头像横向无限滚动区域(错位排列) -->
 31      <div class="tags-group-all" ref="scrollContainer">
 32        <div class="tags-group-wrapper">
 33          <!-- 第一行 -->
 34          <div class="tags-group-row" :class="{ 'offset-start': index % 2 === 0 }" v-for="(row, index) in avatarRows"
 35            :key="index">
 36            <div class="tags-group-content">
 37              <a v-for="(link, linkIndex) in row" :key="linkIndex" class="tags-group-icon" target="_blank"
 38                :href="link.link" :title="link.name" rel="external nofollow noopener">
 39                <img :src="link.avatar" :alt="link.name" loading="lazy" :class="{ irregular: link.irregular }">
 40              </a>
 41            </div>
 42          </div>
 43        </div>
 44      </div>
 45    </div>
 46    <!-- 友链分组列表,每个分组包含标题、描述和友链列表 -->
 47    <div v-for="(group, index) in linksData" :key="index" class="my-links-group">
 48      <!-- 分组标题容器 -->
 49      <div class="title-wrapper">
 50        <h3>{{ group.title }}</h3>
 51      </div>
 52
 53      <!-- 分组描述文本 -->
 54      <p class="group-desc">{{ group.desc }}</p>
 55
 56      <!-- 友链列表容器 -->
 57      <div class="links-grid">
 58        <!-- 每个友链项使用LinkItem子组件展示,通过:data传递友链信息 -->
 59        <div v-for="link in group.list" :key="link.link" class="links-grid__item">
 60          <LinkItem :data="link" />
 61        </div>
 62      </div>
 63    </div>
 64
 65    <!-- 留言/评论区域,默认显示,可通过frontmatter隐藏 -->
 66    <div v-if="commentShow" class="my-message-section" id="post-comment">
 67      <div class="title-wrapper">
 68        <h3>申请友链</h3>
 69      </div>
 70      <p>想要和我交换友链?请在评论区按以下格式留言 💞</p>
 71
 72      <!-- 留言卡片容器 -->
 73      <div class="message-card">
 74        <p>留言格式:</p>
 75        <!-- 示例格式 -->
 76        <pre>
 77名称: 时光笔记
 78链接: https://notes.ksah.cn
 79头像: https://notes.ksah.cn/logo.png
 80描述: 干货满满的技术笔记</pre>
 81        <!-- 评论区插槽 -->
 82        <!-- 默认为Twikoo评论组件,可通过插槽自定义其他评论系统 -->
 83        <slot name="comments">
 84          <Twikoo />
 85        </slot>
 86      </div>
 87    </div>
 88  </div>
 89</template>
 90
 91<script setup>
 92import { useData } from "vitepress";
 93import LinkItem from "./LinkItem.vue";
 94// 导入Twikoo评论组件
 95import Twikoo from "../Twikoo.vue";
 96import { computed } from "vue";
 97
 98// 从页面frontmatter中获取配置数据
 99const { frontmatter } = useData();
100
101// 从frontmatter中读取links字段,如果未定义则使用空数组
102const linksData = computed(() => frontmatter.value.links || []);
103
104// 从frontmatter中读取title字段,默认值为"我的友链"
105const title = computed(() => frontmatter.value.title || "我的友链");
106
107// 当frontmatter中comments为false时隐藏,默认显示
108const commentShow = computed(() => frontmatter.value.comments !== false);
109// 当frontmatter中banner为false时隐藏,默认显示
110const bannerShow = computed(() => frontmatter.value.banner !== false);
111// 当frontmatter中bannerButtonGroup为false时隐藏,默认显示
112const bannerButtonGroupShow = computed(() => frontmatter.value.bannerButtonGroup !== false);
113// 可自定义frontmatter中的smallTitle,作为banner的小标题,默认值为"与各位博主一起成长进步"
114const smallTitle = computed(() => frontmatter.value.smallTitle || "与各位博主一起成长进步");
115
116const allLinks = computed(() => {
117  return linksData.value.reduce((acc, group) => {
118    const processedLinks = group.list.map(link => ({
119      ...link,
120      avatar: link.avatar
121    }));
122    acc.push(...processedLinks);
123    return acc;
124  }, []);
125});
126
127// 将头像平均分成两行,并复制内容以实现无缝滚动
128const avatarRows = computed(() => {
129  const avatars = allLinks.value;
130  if (avatars.length === 0) return [[], []];
131
132  const mid = Math.ceil(avatars.length / 2);
133  const row1 = avatars.slice(0, mid);
134  const row2 = avatars.slice(mid);
135
136  // 复制内容以实现无缝滚动
137  return [
138    [...row1, ...row1], // 第一行复制一份
139    [...row2, ...row2]  // 第二行复制一份
140  ];
141});
142
143// 随机访问友链
144const handleRandomVisit = () => {
145  if (allLinks.value.length === 0) return;
146  const randomIndex = Math.floor(Math.random() * allLinks.value.length);
147  const randomLink = allLinks.value[randomIndex];
148  window.open(randomLink.link, "_blank");
149};
150</script>
151
152<style scoped>
153/* 字体图标 */
154@import url("https://cdn.ksah.cn/fonts/icomoon/font.css");
155
156/* 主容器样式 */
157.my-links-container {
158  max-width: 1500px;
159  margin: 0 auto;
160  padding: 40px 10px;
161  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
162    Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
163}
164
165/* 标题区域样式 */
166.my-links-title {
167  margin-bottom: 50px;
168  padding: 0 10px;
169}
170
171/* 主标题样式 */
172.my-links-title h1 {
173  font-size: 2rem;
174  font-weight: 600;
175  background: -webkit-linear-gradient(10deg, #bd34fe 5%, #e43498 15%);
176  background-clip: text;
177  -webkit-background-clip: text;
178  -webkit-text-fill-color: transparent;
179  -webkit-font-smoothing: antialiased;
180  text-rendering: optimizeLegibility;
181  line-height: 1.2;
182  display: inline-block;
183}
184</style>

3. 配置友链数据

在页面的 frontmatter 中配置友链数据,例如:

 1---
 2title: 我的友链
 3banner: true
 4bannerButtonGroup: true
 5smallTitle: 与各位博主一起成长进步
 6comments: true
 7links:
 8  - title: 技术博客
 9    desc: 分享技术干货
10    list:
11      - name: 时光笔记
12        link: https://notes.ksah.cn
13        avatar: https://notes.ksah.cn/logo.png
14        descr: 干货满满的技术笔记
15  - title: 个人博客
16    desc: 记录生活点滴
17    list:
18      - name: One Blog
19        link: https://onedayxyy.cn
20        avatar: https://onedayxyy.cn/logo.png
21        descr: 记录生活与技术的博客
22---

4. 集成 Twikoo 评论系统

在友链页面的评论区插槽中,默认集成了 Twikoo 评论组件。确保你已经按照 Twikoo 集成教程 完成了 Twikoo 的配置。

5. 测试功能

启动项目并访问友链页面,确保以下功能正常工作:

  1. 随机访问:点击“随机访问”按钮,随机跳转到友链页面。
  2. 申请友链:点击“申请友链”按钮,跳转到评论区。
  3. 头像滚动:确保头像区域实现无缝滚动效果。
  4. 评论功能:确保 Twikoo 评论系统正常加载。

6. 常见问题

  1. 头像未显示:检查 avatar 链接是否正确,并确保图片资源可访问。
  2. 随机访问无效:检查 allLinks 是否为空,并确保 handleRandomVisit 逻辑正确。
  3. 评论未加载:检查 Twikoo 的 envId 配置是否正确。

7. 扩展功能

你可以进一步优化友链页面,例如:

  1. 自定义样式:修改 CSS 文件以适配你的主题风格。
  2. 动态加载友链:通过 API 动态加载友链数据。
  3. 更多交互功能:添加点赞、分享等功能。

通过以上步骤,你已经成功实现了一个功能丰富的友链页面。接下来,你可以继续优化其他页面或功能模块。

微信支付 支付宝