babel-plugin-import

webpack 就不会默认把整个的包都进行打包到生产环境了,而是我们使用那个组件就打包那个组件,同样 CSS 也是按需打包的。

配置举例:

1
2
3
4
5
6
7
8
9
10
11
12
13

{
"presets":["next/babel"], //Next.js的总配置文件,相当于继承了它本身的所有配置
"plugins":[ //增加新的插件,这个插件就是让antd可以按需引入,包括CSS
[
"import",
{
"libraryName":"antd",
"style":"css"
}
]
]
}

next.js 引入 css

先用 yarn 命令来安装@zeit/next-css 包,它的主要功能就是让 Next.js 可以加载 CSS 文件,有了这个包才可以进行配置。

1
yarn add @zeit/next-css

包安装好以后就可以进行配置文件的编写了,建立一个 next.config.js.这个就是 Next.js 的总配置文件。

1
2
3
4
5
6
7
const withCss = require('@zeit/next-css')

if(typeof require !== 'undefined'){
require.extensions['.css']=file=>{}
}

module.exports = withCss({})

这段代码你有兴趣是可以看看的,其实我对配置文件基本不记忆的,因为配置文件就是别人规定的配置,你写就好。比如要使用 CSS 就可以把上面这段代码输入到放入到里边的就好了。

修改配置文件需要重新启一下服务(yarn dev ),重启服务可以让配置生效,这时候你到浏览器中可以发现 CSS 文件已经生效了。

1.markdown 解析组件

react-markdown 是 react 专用的 markdown 解析组件

可以直接使用 yarn add 来进行安装,代码如下:

yarn add react-markdown
安装好后,使用 import 进行引入,代码如下:

import ReactMarkdown from 'react-markdown'

准备 md 相关数据
因为目前还没有后端程序,所以需要伪造一个 md 数据,让 web 页面可以渲染。

这里声明一个 markdown 变量,当然内容全部是我胡乱写的,为的就是可以顺利渲染出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
let markdown='# P01:课程介绍和环境搭建\n' +
'[ **M** ] arkdown + E [ **ditor** ] = **Mditor** \n' +
'> Mditor 是一个简洁、易于集成、方便扩展、期望舒服的编写 markdown 的编辑器,仅此而已... \n\n' +
'**这是加粗的文字**\n\n' +
'*这是倾斜的文字*`\n\n' +
'***这是斜体加粗的文字***\n\n' +
'~~这是加删除线的文字~~ \n\n'+
'\`console.log(111)\` \n\n'+
'# p02:来个Hello World 初始Vue3.0\n' +
'> aaaaaaaaa\n' +
'>> bbbbbbbbb\n' +
'>>> cccccccccc\n'+
'***\n\n\n' +
'# p03:Vue3.0基础知识讲解\n' +
'> aaaaaaaaa\n' +
'>> bbbbbbbbb\n' +
'>>> cccccccccc\n\n'+
'# p04:Vue3.0基础知识讲解\n' +
'> aaaaaaaaa\n' +
'>> bbbbbbbbb\n' +
'>>> cccccccccc\n\n'+
'#5 p05:Vue3.0基础知识讲解\n' +
'> aaaaaaaaa\n' +
'>> bbbbbbbbb\n' +
'>>> cccccccccc\n\n'+
'# p06:Vue3.0基础知识讲解\n' +
'> aaaaaaaaa\n' +
'>> bbbbbbbbb\n' +
'>>> cccccccccc\n\n'+
'# p07:Vue3.0基础知识讲解\n' +
'> aaaaaaaaa\n' +
'>> bbbbbbbbb\n' +
'>>> cccccccccc\n\n'+
'``` var a=11; ```'

使用 react-markdown 渲染 markdown

现在组件和 markdown 文件都准备好了,可以进行渲染了。代码如下:

1
2
3
4
5
6
<div className="detailed-content" >
<ReactMarkdown
source={markdown}
escapeHtml={false}
/>
</div>

现在可以到浏览器中预览一下了,如果一切正常,应该可以正常使用 markdown 语法了。

2.markdown 解析组件

前面介紹的 react-markdown,但是这个插件的配置项还是太少了,现在介绍的是 marked+highlight.js。这个方案是比较成熟的,目前公司的开发文档程序就是基于这个开发的。

安装 marked 和 highlight

这两个模块需要先安装,这里我们就使用 yarn 来进行安装。打开终端,进入到 blog 目录下,然后使用下面命令进行安装。

1
yarn add marked highlight.js

我目前的版本是 marked 是 0.7.0,highlight 是 9.15.10。如果版本有变化,导致代码没法运行,可自行查看 API 进行修改。

引入模块

1
2
3
import marked from 'marked'
import hljs from "highlight.js";
import 'highlight.js/styles/monokai-sublime.css';

引入设置一下 marked.setOptions,里边的属性比较多,我在这里详细的介绍一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)
  • renderer: 这个是必须填写的,你可以通过自定义的 Renderer 渲染出自定义的格式

  • gfm:启动类似 Github 样式的 Markdown,填写 true 或者 false

  • pedatic:只解析符合 Markdown 定义的,不修正 Markdown 的错误。填写 true 或者 false

  • sanitize: 原始输出,忽略 HTML 标签,这个作为一个开发人员,一定要写 flase

  • tables: 支持 Github 形式的表格,必须打开 gfm 选项

  • breaks: 支持 Github 换行符,必须打开 gfm 选项,填写 true 或者 false

  • smartLists:优化列表输出,这个填写 ture 之后,你的样式会好看很多,所以建议设置成 ture

  • highlight: 高亮显示规则 ,这里我们将使用 highlight.js 来完成

** 增加 Code 的高亮显示 **

在设置 setOptions 属性时,可以直接设置高亮显示,代码如下:

1
2
3
highlight: function (code) {
return hljs.highlightAuto(code).value;
}

设置完成后,你在浏览器检查代码时就可以出现 hljs 的样式,说明你的效果加成功了,实现了高亮显示代码。

1.markdown 目录导航——markdown-navbar

markdown-navbar 组件是一款第三方提供的组件,因为这个是比较小众的需求,所以使用的人并不多。目前只有 18star,这个是国人开发的。

markdown-navbar 的基本属性:

  • className: 可以为导航定义一个 class 名称,从而进行 style 样式的定义。
  • source:要解析的内容,也就是你的 Markdown 内容。
  • headingTopOffset:描点距离页面顶部的位置,默认值是 0.
  • ordered: 显示数字编码,默认是显示的,也就是 true,设置为 false 就不显示了。

markdown-navbar 的安装和使用

npm install进行安装,命令如下:

npm install --save markdown-navbar

用 yarn add 进行安装,命令如下:

yarn add markdown-navbar

安装完成后,直接在要使用的页面用 import 进行引入,需要注意的是你还需要引入 css。

1
2
import MarkNav from 'markdown-navbar';
import 'markdown-navbar/dist/navbar.css';

这样就引入成功了,现在就可以制作导航了,代码如下:

1
2
3
4
5
6
7
8
<div className="detailed-nav comm-box">
<div className="nav-title">文章目录</div>
<MarkNav
className="article-menu"
source={markdown}
ordered={false}
/>
</div>

在浏览器中预览一下,可以看到效果了。但现在有一个需求,就是这个导航要一直在页面的右侧。我们经常叫这个需求为固钉。Ant Desgin 中提供了Affix.

先用 import 引入 Affix 组件。

1
import {Row, Col ,Affix, Icon ,Breadcrumb  } from 'antd'

引入后在需要固钉的外层加上 Affix 组件就可以了。

1
2
3
4
5
6
7
8
9
10
11
<Affix offsetTop={5}>
<div className="detailed-nav comm-box">
<div className="nav-title">文章目录</div>
<MarkNav
className="article-menu"
source={markdown}

ordered={false}
/>
</div>
</Affix>

写完这段代码,到浏览器中预览一下,就可以实现固钉的效果了。

2. markdown 目录导航——tocify.tsx 文件

你的程序中使用了 Ant DesignUI 库,因为它里边的导航部分,使用了 antd 的 Anchor 组件

安装 lodash 模块,这个可以直接使用 yarn add lodash 来安装

上面两个条件满足后,你可以把文件 tocify.tsx 拷贝到你的项目里了,我这里放到了/blog/components 文件夹下了,把它视为一种自定义组件。

tocify.tsx 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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 引入。

1
import Tocify from '../components/tocify.tsx'

引入后,需要对 marked 的渲染进行自定义,这时候需要设置 renderer.heading,就是写一个方法们重新定义对#这种标签的解析。代码如下:

1
2
3
4
5
6
7
8
9
10
11
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`;
};
最后在需要显示文章导航的地方,写下面的代码:

<div className="toc-list">
{tocify && tocify.render()}
</div>

egg.js 跨域问题

egg-cors模块是专门用来解决 egg.js 跨域问题的,只要简单的配置就可以完成跨域的设置,但是跨域一定要谨慎设置,很多安全问题,都是通过跨域进行攻击的。

安装我们使用yarn add进行安装,命令如下:

1
yarn add egg-cors

配置 config/plugin.js 文件

在安装完成后需要对/service/config/plugin.js 文件进行修改,加入 egg-cors 模块即可。

1
2
3
4
exports.cors= {
enable: true,
package: 'egg-cors'
}

配置 config.default.js

在配置完成 plugin.js 文件以后,还需要设置 config.default.js 文件。这个文件主要设置的是允许什么域名和请求方法可以进行跨域访问。配置代码如下。

1
2
3
4
5
6
7
8
9
10
  config.security = {
    csrf: {
      enable: false
    },
    domainWhiteList: [ '*' ]
  };
config.cors = {
origin: '*',
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS'
};

如果你只想让http://localhost:3000 来进行接口方案,就可以设置成下面的代码。

1
2
3
4
5
6
7
8
9
config.security = {
    csrf: {enable: false},
    domainWhiteList: [ '*' ]
  };
config.cors = {
origin: 'http://localhost:3000', //只允许这个域进行访问接口
credentials: true, // 开启认证
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS'
};

设置完成后,就可以在浏览器中进行预览了,如果能正常访问,说明跨域访问已经设置成功了。

vscode 好用插件

px-to-vw

在设置里面搜索 px-to-vw 可设置设计稿大小

1
2
3
4
Px-to-viewport: Viewport-width
The width of the viewport

350

选中 css 语句按 `ALT+Z’即可转换为 vw

此时

1
font-size: 16px;  //ALT+Z

变成

1
font-size: 4.444vw;

Vue 父调用子组件方法

1.使用ref

//父组件

//子组件

2.使用$emit

子组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

<div class="editBanner" @click="bannerClick">
<span>{{left}}</span>
<span><slot name='right'></slot></span>
</div>


<script >
export default {
props: ['left'],
methods:{
bannerClick(){
this.$emit('bannerClick')
}
}
}
</script>

父组件

1
2
3
4
5

<editBanner left="出生日期" class="dateView" @bannerClick="changeDateShow">
<a slot="right">{{date}}</a>
</editBanner>

this

匿名函数的 this 永远指向 window
this 永远指向最后调用它的那个对象

shuffle()

shuffle() 方法将序列的所有元素随机排序。

1
2
3
import random

random.shuffle (lst )