feat: js基础知识导航

master
LCJ-MinYa 3 days ago
parent a27184c9bb
commit 0e8a5440ed

@ -5,6 +5,21 @@
## 对话记录
### 本次会话总结 (2026年2月6日)
本次会话完成了 `jsCoreNav.vue` 导航页面的开发任务:
1. **创建 Vue 页面**:
* 在 `src/views/tool/` 目录下创建了 `jsCoreNav.vue` 单文件组件。
* 实现了响应式的网格布局,展示 JavaScript 核心基础知识点卡片。
* 集成了 **搜索过滤** 功能,支持根据标题和描述实时筛选导航项。
* 页面采用 **配置驱动** 模式,通过修改内部的 `navList` 常量即可轻松增删导航内容。
2. **交互与视觉设计**:
* 使用 `Element Plus``el-card``TailwindCSS` 构建,支持悬浮动效。
* 集成 `Iconify` 图标库,为每个知识点提供直观的图标标识。
* 统一处理了内部路由跳转和外部链接跳转的逻辑。
### 本次会话总结 (2025年10月30日)
本次会话完成了 `computedWithEnumList` 示例页面的开发任务,主要包含以下步骤:
@ -69,7 +84,13 @@
### 任务列表
* 项目首页/welcome这个路由下是默认的的首页介绍页面但是现在这个页面是一个静态的页面是由一些模拟数据渲染的我现在希望完成功能如下
* [x] 在 `src/views/tool/` 目录下创建 `jsCoreNav.vue` 导航跳转页面。
* 项目首页/welcome这个路由下是默认的的首页介绍页面
,但是现在这个页面是一个静态的页面,是由一些模拟数据渲染的,我现在希望完成功能如下:
- 在package.json中添加一个命令当执行这个命令的时候可以本地统计/src/views下的/demo/python/utils/screen这四个模块下分别有多少个页面页面维度请按照router路由来统计例如/python文件夹有五个文件夹这就是5个页面。当统计完成后在/src/views/welcome中创建或者更新config.json文件以便后续页面可以直接读取json配置文件
- 请读取/src/view/welcome中页面其中页面的数据来源为/scripts/statistics.mjs请更新该脚本以便获得更多的信息来满足/src/view/welcome页面所需数据的渲染
- 将/src/view/welcome/config.json作为数据源渲染到/src/view/welcome的vue组件中

@ -19,5 +19,13 @@ export default {
title: '工具导航',
},
},
{
path: '/tool/jsCore',
name: 'JsCore',
component: () => import('@/views/tool/jsCoreNav.vue'),
meta: {
title: 'js核心基础知识导航',
},
},
],
} satisfies RouteConfigsTable;

@ -0,0 +1,183 @@
<template>
<div class="p-6 min-h-full bg-white">
<!-- 顶部区域扁平化标题与搜索 -->
<div class="flex flex-col md:flex-row md:items-center justify-between mb-8 pb-6 border-b-2 border-gray-100">
<div class="mb-4 md:mb-0">
<h1 class="text-2xl font-black text-gray-900 tracking-tight">JS <span class="text-primary">CORE</span> NAV</h1>
<p class="text-sm text-gray-500 mt-1 font-medium">JavaScript 核心基础知识点速查</p>
</div>
<div class="relative">
<el-input
v-model="searchText"
placeholder="输入关键字过滤..."
class="custom-search !w-full md:!w-80"
clearable
>
<template #prefix>
<iconify-icon-online
icon="ep:search"
class="text-gray-400"
/>
</template>
</el-input>
</div>
</div>
<!-- 导航网格扁平化高对比度设计 -->
<div
v-if="filteredList.length > 0"
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4"
>
<div
v-for="(item, index) in filteredList"
:key="item.path"
class="nav-card group cursor-pointer relative overflow-hidden border-2 transition-all duration-200"
:style="{ borderColor: getThemeColor(index, 'border') }"
@click="handleNav(item)"
>
<!-- 左侧色条对比 -->
<div
class="absolute left-0 top-0 bottom-0 w-1.5"
:style="{ backgroundColor: getThemeColor(index, 'main') }"
></div>
<div class="p-5 pl-7">
<!-- 标题高对比度加粗 -->
<h3
class="text-lg font-bold mb-2 transition-colors duration-200"
:style="{ color: getThemeColor(index, 'text') }"
>
{{ item.title }}
</h3>
<!-- 描述简洁明了 -->
<p class="text-sm text-gray-600 leading-relaxed font-medium line-clamp-2">
{{ item.desc }}
</p>
<!-- 底部装饰线 -->
<div
class="mt-4 w-8 h-1 transition-all duration-300 group-hover:w-full"
:style="{ backgroundColor: getThemeColor(index, 'main') }"
></div>
</div>
</div>
</div>
<!-- 空状态 -->
<el-empty
v-else
description="未找到相关内容"
/>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { useRouter } from 'vue-router';
defineOptions({
name: 'JsCoreNav',
});
const router = useRouter();
const searchText = ref('');
interface NavItem {
title: string;
path: string;
desc: string;
}
/**
* 预设高对比度色彩库 (扁平化风格)
*/
const THEME_COLORS = [
{ main: '#3B82F6', border: '#DBEafe', text: '#1E40AF' }, //
{ main: '#EF4444', border: '#FEE2E2', text: '#991B1B' }, //
{ main: '#10B981', border: '#D1FAE5', text: '#065F46' }, // 绿
{ main: '#F59E0B', border: '#FEF3C7', text: '#92400E' }, //
{ main: '#8B5CF6', border: '#EDE9FE', text: '#5B21B6' }, //
{ main: '#EC4899', border: '#FCE7F3', text: '#9D174D' }, //
{ main: '#06B6D4', border: '#CFFAFE', text: '#155E75' }, //
];
const getThemeColor = (index: number, type: 'main' | 'border' | 'text') => {
const colorSet = THEME_COLORS[index % THEME_COLORS.length];
return colorSet[type];
};
/**
* 导航数据
*/
const navList = ref<NavItem[]>([
{
title: '变量提升与作用域',
path: '/js/scope-hoisting',
desc: '执行上下文、词法作用域与 var/let/const 的底层差异。',
},
{
title: '闭包与内存模型',
path: '/js/closures',
desc: '函数作用域链的延续、私有变量实现与内存泄漏规避。',
},
{
title: '原型继承链',
path: '/demo/prototype',
desc: '从 __proto__ 到 prototype构建 JavaScript 的对象继承大厦。',
},
{
title: 'This 上下文绑定',
path: '/js/this-context',
desc: '默认绑定、隐式绑定、显式绑定与箭头函数的静态指向。',
},
{
title: '事件循环模型',
path: '/js/event-loop',
desc: '宏任务与微任务的交替执行,浏览器渲染帧的调度机制。',
},
]);
const filteredList = computed(() => {
const keyword = searchText.value.trim().toLowerCase();
if (!keyword) return navList.value;
return navList.value.filter((item) => item.title.toLowerCase().includes(keyword) || item.desc.toLowerCase().includes(keyword));
});
const handleNav = (item: NavItem) => {
if (item.path.startsWith('http')) {
window.open(item.path, '_blank');
} else {
router.push(item.path).catch(() => {});
}
};
</script>
<style lang="scss" scoped>
.nav-card {
background-color: #fff;
&:hover {
transform: translateX(4px);
background-color: #f9fafb;
}
}
.custom-search {
:deep(.el-input__wrapper) {
box-shadow: none !important;
border: 2px solid #f3f4f6;
border-radius: 0;
padding: 8px 12px;
&.is-focus {
border-color: var(--el-color-primary);
}
}
}
.text-primary {
color: var(--el-color-primary);
}
</style>
Loading…
Cancel
Save