使用Nuxt3开发网址导航(下,完结)

上篇文章写完了后端接口的开发,本篇就开始写前端的开发了。

效果:www.zngg.net/nav 开源地址:github.com/ZN-GG/ZNGG-...

上篇文章传送门:juejin.cn/post/726030...

整理上回思路:

  1. 所有导航信息使用一个json

这就说明一个问题:所有分类相关的切换均由前端完成,一次请求后不再与后端交互。

页面制作

抛开逻辑不谈,静态的html展示肯定是要先做到位的,现在我直接拿成品图来展示:

1134031880924954624.png

根据这个图片来写前端,实际上并不难。看下这个页面结构:

  1. 顶部Toolbar
  2. 一个标题
  3. 分类条
  4. 网址条目

顶部Toolbar

1134102423489478656.png

其中顶部Toolbar和标题较为简单,我目前已经可以在已有的框架中开发了,我封装好了顶部Toolbar,并且外层默认layout已经带有Toolbar了,所以这步就省略了。 这是默认layout:

html 复制代码
<template>
    <div>
        <Toolbar />
        <NuxtLoadingIndicator />
        <NuxtPage class="mt-20" />
    </div>
</template>

其中已经有Toolbar了。

一个标题

这个使用tailwindcss的container和样式mx-auto,即可把文字放在中间容器的左侧,随后略微调整一下字体即可:

html 复制代码
<section class="bg-gray-100">
    <div class="container px-4 mx-auto">
        <div class="md:flex md:-mx-4 md:items-center py-8">
            <div class="md:w-1/2 px-4">
                <p class="text-2xl text-black">优质网址导航</p>
            </div>
        </div>
    </div>
</section>

轻松搞定!

分类条

页面制作

分类条的设计我使用flex布局,方便垂直居中对齐。第一步肯定还是需要创建一个container样式的div,这样可以把内容聚集到中间容器中来;第二步就是在里面写一个父布局(flex),并设置overflow-auto,方便右侧超出后可以出现滚动条。第三步就是在这个flex布局里填充分类按钮,并稍微来点样式: tailwind.css:

css 复制代码
  .btn-2 {
    @apply bg-gray-100 custom-font-12 leading-5 py-1 px-4 rounded-md whitespace-nowrap cursor-pointer hover:bg-blue-600 hover:text-white mx-1;
  }

页面:

html 复制代码
<div class="bg-white">
    <div class="container mx-auto px-4">
        <div class="flex py-3 space-x-4 flex-none overflow-auto">
            <div class="bg-blue-600 text-white btn-2">分类</div>
            <div class="btn-2">分类</div>
            <div class="btn-2">分类</div>
            <div class="btn-2">分类</div>
            <div class="btn-2">分类</div>
        </div>
    </div>
</div>

样式写好了就要开始写逻辑了,要用网络数据代替这些写死的数据。

逻辑

分类逻辑很简单:获取网络数据data ,使用v-for遍历这个data 即可。稍微需要思考一下的就是这个已选择的分类,我决定默认选择第一个分类为已选择分类,这里需要添加一个变量categoryId(不够严谨),这个变量默认为1,点击分类时修改categoryId的值即可。

首先使用Nuxt3获取网络数据:

typescript 复制代码
import { api } from "~/api/api";
let categoryId = ref(0)

const { data: navLinks, pending, refresh, error } = await useAsyncData("web_NavLinks", () => api.web.getNavInfo());
if (navLinks.value!.success) {
    console.log(navLinks.value);

}

async function selectCategoryId(id: number) {
    categoryId.value = id
}

这里我封装了一下网络请求,具体封装代码可以看:github.com/ZN-GG/ZNGG-...

上述代码中定义了一个navLinks常量存储json数据,并且将数据打印出来。这里定义了一个变量categoryId和一个函数selectCategoryId,下面会用到

随后将分类相关的html代码修改成动态的值:

html 复制代码
<div class="bg-white">
    <div class="container mx-auto px-4">
        <div 
            class="flex py-3 space-x-4 flex-none overflow-auto">
            <div v-for="(item, index) in navLinks?.data" :key="index" @click="selectCategoryId(index)"
                class="btn-2" :class="categoryId == index ? 'bg-blue-600 text-white' : ''">
                {{ item.name }}
            </div>
        </div>
    </div>
</div>

上面的代码中使用v-for循环遍历我们的内容navLinks,并且将index设置为索引,当categoryIdindex相等时,给按钮增加一个选中的样式(背景变蓝色,字变成白色),并且使用@click让分类被点击时调用selectCategoryId函数修改categoryId的值。

写到这里,分类相关功能就已经全部完成了,接下来只需要根据categoryId来展示网址即可。

网址条目

根据已选择分类展示网址,开始之前思考一个问题,就是如何才能根据选择的分类展示这个分类下的网址信息呢?我的答案是"categId",这里的categoryId是真正的categoryId,就是那个雪花算法生成的id,并不是上面说到的index索引,那么如果这样做的话,就会需要两层遍历(因为json只能遍历),首先在完成遍历出正确的categoryId==categoryId,之后在内部遍历itemList,这样会不会麻烦一点呢?或者有没有更简单的办法呢?这就是我想到的第二个办法:index。

json想要直接拿到某一条数据,那么只有一个办法,就是知道这个数据的位置(position),因此我上面代码里的categoryId其实代表的是position,分类的位置。这样我就可以直接通过json[xxx].itemList的方式拿到网址数据,具体请看代码:

ini 复制代码
<div class="container px-4 mx-auto">
    <div class="py-5">
        <ul class="w-full flex flex-wrap">
            <li v-for="item in navLinks?.data[categoryId].itemList" class="w-full md:w-4/12">
                <div class="transition duration-300 ease-in-out p-2">
                    <a :href="item.url" target="_blank">
                        <div class="bg-white rounded px-3 py-4 nav-item-anim">
                            <div class="flex">
                                <div class="w-2/12 flex items-center">
                                    <img class="w-8 h-8 mx-auto" :src="item.img" alt="" srcset="">
                                </div>
                                <div class="px-2">

                                    <div class="flex items-start">
                                        <div class="grow">
                                            <p class="text-gray-800 mb-1">{{ item.title }}</p>
                                            <p class="text-gray-400 text-xs">
                                                {{ item.description }}
                                            </p>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </a>
                </div>
            </li>
        </ul>
    </div>
</div>

归纳总结

这篇文章的categoryId意思表达的不算好,如果不理解的话只能多看看代码了。

完整代码地址:github.com/ZN-GG/ZNGG-...

到此,导航就已经制作完毕了,我将整个制作过程完完整整的记录了下来,也许几年以后再来看这些代码,就会觉得是一堆垃圾,但好在现在我觉得这代码可优化的地方并不算多。整个导航我大概花了一个下午的时间,这里很感谢我的女朋友可以在难得周末抽出一个下午的时间让我好好享受这写代码的过程,看一看时间,再不午休下午可就要犯困了~

相关推荐
滚雪球~28 分钟前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语29 分钟前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport31 分钟前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg32 分钟前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
胡西风_foxww39 分钟前
【es6复习笔记】rest参数(7)
前端·笔记·es6·参数·rest
m0_7482548840 分钟前
vue+elementui实现下拉表格多选+搜索+分页+回显+全选2.0
前端·vue.js·elementui
星就前端叭1 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234522 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js
Web阿成2 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript
jwensh2 小时前
【Jenkins】Declarative和Scripted两种脚本模式有什么具体的区别
运维·前端·jenkins