P18:重构前台博客详细页面的文章导航
AI 概述
重构后前台详细页的文章导航部分出现了错误提示,这个主要是我们选择的markdown-navbar模块的坑,这里为大家推荐一个这方面的插件叫 tocify.tsx,比较好用,所以我们直接拿来使用。
tocify.tsx 文件简介
tocify.tsx文件,用这个扩展名的含义是他使用了typeScript语法来编写jsx的部分,为了更好的和普通的是jsx文件区分,...
重构后前台详细页的文章导航部分出现了错误提示,这个主要是我们选择的markdown-navbar模块的坑,这里为大家推荐一个这方面的插件叫 tocify.tsx,比较好用,所以我们直接拿来使用。
tocify.tsx 文件简介
tocify.tsx文件,用这个扩展名的含义是他使用了typeScript语法来编写jsx的部分,为了更好的和普通的是jsx文件区分,所以这里使用了tsx的扩展名。
使用这个文件的两个必要条件
- 你的程序员中使用了
Ant DesignUI 库,因为它里边的导航部分,使用了antd的Anchor组件 - 安装
lodash模块,这个可以直接使用yarn add lodash来安装或者使用npm install --save lodash
上面两个条件满足后,你可以把文件tocify.tsx拷贝到你的项目里了,我这里放到了/blog/components文件夹下了,把它视为一种自定义组件。
tocify.tsx 文件
import React from 'react';
import { Anchor } from 'antd';
import { last } from 'lodash';
const { Link } = Anchor;
export interface TocItem {
anchor: string;
level: number;
text: string;
children?: TocItem[];
}
export type TocItems = TocItem[]; // TOC 目录树结构
export default class Tocify {
tocItems: TocItems = [];
index: number = 0;
constructor() {
this.tocItems = [];
this.index = 0;
}
add(text: string, level: number) {
const anchor = `toc${level}${++this.index}`;
const item = { anchor, level, text };
const items = this.tocItems;
if (items.length === 0) { // 第一个 item 直接 push
items.push(item);
} else {
let lastItem = last(items) as TocItem; // 最后一个 item
if (item.level > lastItem.level) { // item 是 lastItem 的 children
for (let i = lastItem.level + 1; i <= 2; i++) {
const { children } = lastItem;
if (!children) { // 如果 children 不存在
lastItem.children = [item];
break;
}
lastItem = last(children) as TocItem; // 重置 lastItem 为 children 的最后一个 item
if (item.level <= lastItem.level) { // item level 小于或等于 lastItem level 都视为与 children 同级
children.push(item);
break;
}
}
} else { // 置于最顶级
items.push(item);
}
}
return anchor;
}
reset = () => {
this.tocItems = [];
this.index = 0;
};
renderToc(items: TocItem[]) { // 递归 render
return items.map(item => (
<Link key={item.anchor} href={`#${item.anchor}`} title={item.text}>
{item.children && this.renderToc(item.children)}
</Link>
));
}
render() {
return (
<Anchor affix showInkInFixed>
{this.renderToc(this.tocItems)}
</Anchor>
);
}
}
其实这个文件也很简单,如果 JavaScript 基础没问题是完全可以看明白的。
使用tocify.tsx生成文章目录
接下来就可以利用tocify.tsx文件生成目录了,在/blog/pages/detailed.js引入。
import Tocify from '../components/tocify.tsx'
引入后,需要对marked的渲染进行自定义,这时候需要设置renderer.heading,就是写一个方法们重新定义对#这种标签的解析。代码如下:
renderer.heading = function(text, level, raw) {
const anchor = tocify.add(text, level);
return `<a id="${anchor}" href="#${anchor}" class="anchor-fix"><h${level}>${text}</h${level}></a>\n`;
};
最后在需要显示文章导航的地方,写下面的代码:
<div className="toc-list">
{tocify && tocify.render()}
</div>
为了方便大家学习,给出detailed.js全部代码。
import React,{useState} from 'react'
import Head from 'next/head'
import {Row, Col, Space, Breadcrumb, Affix} from 'antd'
import {ClockCircleOutlined,VideoCameraOutlined,FireOutlined} from '@ant-design/icons'
import Header from '../components/Header'
import Author from '../components/Author'
import Advert from '../components/Advert'
import Footer from '../components/Footer'
import MarkNav from 'markdown-navbar';
import 'markdown-navbar/dist/navbar.css';
import axios from 'axios'
import marked from 'marked'
import hljs from "highlight.js";
import 'highlight.js/styles/monokai-sublime.css';
import Tocify from '../components/tocify.tsx'
const Detailed = (props) => {
const IconText = ({ icon, text }) => (
<Space>
{React.createElement(icon)}
{text}
</Space>
);
const tocify = new Tocify()
renderer.heading = function(text, level, raw) {
const anchor = tocify.add(text, level);
return `<a id="${anchor}" href="#${anchor}" class="anchor-fix"><h${level}>${text}</h${level}></a>\n`;
};
const renderer = new marked.Renderer();
marked.setOptions({
renderer: renderer,
gfm: true,
pedantic: false,
sanitize: false,
tables: true,
breaks: false,
smartLists: true,
smartypants: false,
highlight: function (code) {
return hljs.highlightAuto(code).value;
}
});
let html = marked(props.article_content);
return (
<>
<Head>
<title>博客详细页</title>
</Head>
<Header />
<Row className="comm-main" type="flex" justify="center">
<Col className="comm-left" xs={24} sm={24} md={16} lg={18} xl={14} >
<div>
<div className="bread-div">
<Breadcrumb>
<Breadcrumb.Item><a href="/">首页</a></Breadcrumb.Item>
<Breadcrumb.Item>教程列表</Breadcrumb.Item>
<Breadcrumb.Item>xxxx</Breadcrumb.Item>
</Breadcrumb>
</div>
<div>
<div className="detailed-title">
React 实战教程笔记-码云笔记开发
</div>
<div className="list-icon center">
<IconText icon={ClockCircleOutlined} text="2020-12-01" key="list-vertical-star-o" />
<IconText icon={VideoCameraOutlined} text="前端教程" key="list-vertical-like-o" />
<IconText icon={FireOutlined} text="5498 人" key="list-vertical-message" />
</div>
<div className="detailed-content"
dangerouslySetInnerHTML={{__html:html}}
>
</div>
</div>
</div>
</Col>
<Col className="comm-right" xs={0} sm={0} md={7} lg={5} xl={4}>
<Author />
<Advert />
<Affix offsetTop={5}>
<div className="detailed-nav comm-box">
<div className="nav-title">文章目录</div>
<div className="toc-list">
{tocify && tocify.render()}
</div>
</div>
</Affix>
</Col>
</Row>
<Footer/>
</>
)
}
Detailed.getInitialProps = async(context) => {
let id = context.query.id;
const promise = new Promise((resolve)=>{
axios('http://127.0.0.1:7001/default/getArticleById/' + id).then((res) => {
console.log(res)
resolve(res.data.data[0])
})
})
return await promise
}
export default Detailed
这样就完成了前端详细文章页面的文章导航,可以预览一下效果。
以上关于P18:重构前台博客详细页面的文章导航的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » P18:重构前台博客详细页面的文章导航
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » P18:重构前台博客详细页面的文章导航
微信
支付宝