Nodejs Express官网API文档那种展现方式如何实现?

Nodejs Express官网API文档那种展现方式如何实现?

因为不知道那种方式叫什么,不知道自己表达的是不是清楚,就是随着你看文档,侧边目录会显示你看的位置以及自动展开相应子节点,效果: Express API 请问有没有轮子可以用?如果没有,大概实现思路是什么样的?

7 回复

当然可以!你提到的效果通常被称为滚动同步导航或者滚动同步侧边栏。这种功能可以帮助用户更好地浏览文档,因为它可以根据用户的滚动位置动态更新侧边栏的导航。

实现思路

  1. 监听滚动事件:首先需要监听窗口的滚动事件。
  2. 计算当前滚动位置:通过滚动事件获取当前滚动的位置。
  3. 确定当前活跃的导航项:根据滚动位置确定当前应该高亮显示的导航项。
  4. 更新导航栏:根据当前活跃的导航项更新导航栏的状态(例如展开子节点)。

示例代码

以下是一个简单的示例代码,展示了如何使用JavaScript实现上述功能:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Scroll Sync Sidebar</title>
    <style>
        /* 基本样式 */
        .sidebar {
            position: fixed;
            top: 0;
            left: 0;
            height: 100%;
            width: 200px;
            background-color: #f8f9fa;
            padding: 20px;
        }
        .content {
            margin-left: 220px;
            padding: 20px;
        }
        .nav-item {
            cursor: pointer;
        }
        .active {
            font-weight: bold;
            color: blue;
        }
    </style>
</head>
<body>
    <div class="sidebar">
        <div class="nav-item" data-target="#section1">Section 1</div>
        <div class="nav-item" data-target="#section2">Section 2</div>
        <div class="nav-item" data-target="#section3">Section 3</div>
    </div>
    <div class="content">
        <h2 id="section1">Section 1</h2>
        <p>Content for Section 1</p>
        <h2 id="section2">Section 2</h2>
        <p>Content for Section 2</p>
        <h2 id="section3">Section 3</h2>
        <p>Content for Section 3</p>
    </div>

    <script>
        // 获取所有导航项
        const navItems = document.querySelectorAll('.nav-item');
        
        // 监听滚动事件
        window.addEventListener('scroll', () => {
            const scrollPosition = window.scrollY;

            // 遍历所有导航项
            navItems.forEach(item => {
                const targetId = item.getAttribute('data-target');
                const targetElement = document.querySelector(targetId);
                
                if (targetElement) {
                    const targetTop = targetElement.offsetTop - 50; // 50 是顶部偏移量
                    if (scrollPosition >= targetTop && scrollPosition < targetTop + targetElement.offsetHeight) {
                        // 设置当前导航项为激活状态
                        item.classList.add('active');
                        
                        // 展开当前导航项的父级节点
                        item.parentElement.classList.add('open');
                    } else {
                        item.classList.remove('active');
                        item.parentElement.classList.remove('open');
                    }
                }
            });
        });

        // 初始化时设置第一个导航项为激活状态
        navItems[0].classList.add('active');
    </script>
</body>
</html>

解释

  • HTML结构:包含一个固定的侧边栏和一个主要内容区域。侧边栏中的每个导航项都有一个 data-target 属性,指向文档中相应部分的ID。
  • CSS样式:定义了基本的样式,包括侧边栏的固定位置和激活状态的样式。
  • JavaScript逻辑
    • 监听窗口的滚动事件。
    • 计算当前滚动位置。
    • 根据滚动位置确定当前应该高亮显示的导航项,并更新导航栏的状态。

这样就可以实现类似于Express官网文档那样的滚动同步导航效果。


BT也有这个功能插件,很常见的。

思路:提取文章中的标题标签(h1,h2,…h6),然后创建一个div,将标签内容依次插入进去。至于高亮,则是提取标签的scrollTop值,然后监视body的scroll事件,分析body的scrollTop在哪个区间则给对应的导航链接高亮。

这个应该是 affix 吧。 Bootstrap doc

看不懂。。

要实现类似于 Express 官方文档中那种随着浏览滚动,侧边目录能够显示当前阅读位置并且自动展开相应子节点的效果,可以利用 JavaScript(包括 Node.js 和前端技术)来完成。主要涉及两个方面:后端数据结构和前端交互。

实现思路

  1. 后端数据结构

    • 首先,你需要一个包含所有文档结构的数据源,通常是一个 JSON 文件或数据库表。
    • 数据源应包含每个文档的标题、URL、子文档等信息,以便能够动态生成侧边栏。
  2. 前端逻辑

    • 利用 JavaScript 监听滚动事件,确定当前用户所处的文档位置。
    • 根据当前滚动位置更新侧边栏的高亮状态。
    • 自动展开当前节及其上级目录。

示例代码

以下是一个简单的 Node.js + Express 后端示例和一个前端简单实现:

后端 (Node.js + Express)

// server.js
const express = require('express');
const app = express();
app.use(express.json());

let docs = [
    { title: 'Getting Started', url: '/getting-started', children: [] },
    { title: 'Routing', url: '/routing', children: [
        { title: 'Route Parameters', url: '/routing/params' }
    ]},
    // 其他文档...
];

app.get('/api/docs', (req, res) => {
    res.json(docs);
});

app.listen(3000, () => console.log('Server running on port 3000'));

前端 (HTML + JavaScript)

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Document</title>
</head>
<body>
    <div id="sidebar">
        <ul id="toc"></ul>
    </div>
    <div id="content"></div>

    <script>
        const sidebar = document.getElementById('toc');
        const contentDiv = document.getElementById('content');

        fetch('/api/docs')
            .then(res => res.json())
            .then(data => generateSidebar(data));

        function generateSidebar(data) {
            data.forEach(item => {
                const li = document.createElement('li');
                li.textContent = item.title;
                li.addEventListener('click', () => scrollTo(item.url));
                if (item.children.length > 0) {
                    const ul = document.createElement('ul');
                    generateSidebar(item.children);
                    li.appendChild(ul);
                }
                sidebar.appendChild(li);
            });
        }

        function scrollTo(url) {
            window.location.href = url;
        }

        window.addEventListener('scroll', updateSidebar);
        
        function updateSidebar() {
            const currentSection = getCurrentSection();
            updateHighlight(currentSection);
        }

        function getCurrentSection() {
            // 简化实现,实际项目中需要更复杂的逻辑来计算当前可见的 section
            return docs.find(doc => doc.url === window.location.hash.slice(1)) || docs[0];
        }

        function updateHighlight(section) {
            // 更新侧边栏高亮和展开部分
            const tocItems = document.querySelectorAll('#toc li');
            tocItems.forEach(item => item.classList.remove('active'));
            tocItems.forEach(item => {
                if (item.textContent === section.title) {
                    item.classList.add('active');
                }
            });

            let parent = section;
            while (parent) {
                const parentItem = document.querySelector(`#toc li:contains("${parent.title}")`);
                if (parentItem) {
                    parentItem.classList.add('active');
                    parentItem.parentElement.style.display = 'block';
                }
                parent = findParent(parent, docs);
            }
        }

        function findParent(child, list) {
            for (let item of list) {
                if (item.children.includes(child)) {
                    return item;
                }
                let found = findParent(child, item.children);
                if (found) return found;
            }
            return null;
        }
    </script>
</body>
</html>

总结

上述代码展示了如何使用 Express 提供一个简单的文档数据接口,并且使用前端监听滚动事件并更新侧边栏的高亮状态。实际项目中可能需要根据具体需求进行更多的定制和优化。

回到顶部