Next.js(10.0.4)引入antd组件
首先,前端页面开发我使用了nextJS框架构建应用,但是我整了一个上午都没配置出来,搞得我下午学车心不在焉唉,晚上回家一试,就欧克了!赶紧总结一下!
由于以前Next.js是不支持在文件里import样式的,所以我在网上查找的很多方法是通过下载@zeit/next-css
包来让Next支持CSS文件。不过,看@zeit/next-css
包的npm文档以及[Next文档] 知道,现在已经不需要这么麻烦了,而是直接可以在js文件里import。要求css文件后缀名是.module.css,再提前配合好按需加载(babel-plugin-import),就可以完美使用了。
import detailedStyles from'../styles/pages/detailed.module.css'
<div className={styles.listTitle}>{props.title}</div>
dangerouslySetInnerHTML
在博客中,需要动态和正确展示markdown格式的文章。但是我们把写好的的文章数据放在innerHtml里渲染,发现它把html标签打出来了。解决办法是加dangerouslySetInnerHTML这个属性,就会正确渲染出来,具体使用如下:
<div dangerouslySetInnerHTML={{ __html: html }} ></div>
// <div innerHtml={ html } ></div> ×
原因很简单,这是提醒react开发者要尽量避免 cross-site scripting (XSS) 攻击,想一想,也许坏人会通过HTTP劫持你的文章文件,被修改文件来实现恶意代码的注入。所以react官方推荐使用dangerouslySetInnerHTML
和向其传递包含 key 为 __html
的对象。
不管怎样,它在数据中还是呈现所有HTML,不管代码是良性的还是危险的。文档也没给出解决xss的办法(还是我没看见),只是起名:这很危险!如果我们使用dangerouslySetinnerHTML进行代码安全审查并将其放到页面中,就不会引起跨站点脚本问题。而DOMPurify是一个轻量级的、安全的HTML安全审查工具,由一个德国的XSS专家团队构建。它可以检测出和去除危险代码,又不影响节点的渲染。当然,我们要下载npm包才可以使用。净化html代码,避免xss应该会有很多很多办法,这个需要不断学习和了解~
<div dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(html)}}></div>);
数据库连接
连接数据库和编写接口使用了基于koa框架的egg.js。在egg.js中使用mysql数据库,需要安装egg-mysql
模块并进行如下配置就可以了。我的数据库部署在远程服务器上。
将UTC格式转为本地时间
编写接口、请求数据方法只要正确编写都不会有什么问题,但是我发现我的日期数据的传递很有问题。
首先,数据库的addTime字段的数据类型是date类型,并且添加的记录值是:2021-01-20,直接拿到页面来显示却变成了这个样子,在20号凌晨零点的基础上减少了8个小时(往西8跑个时区到伦敦去了),所以页面显示的是格林尼治标准时间(Greenwich Mean Time,GMT),但现在的标准时间更多的是说:协调世界时(UTC)——由原子钟提供。
所以 ①用JavaScript的Date的方法,将UTC格式转化为我们本地时间的操作可以这样:
<span ><EditOutlined /> {new Date(item.addTime).toDateString()}</span>
//或者
{new Date(item.addTime).toLocaleDateString()}
或者,②从sql语句里做更改:DATE_FORMAT(article.addTime,’%Y-%c-%d’),直接返回正确格式的时间数据给前端:
'SELECT article.id as id,' +
........
"DATE_FORMAT(article.addTime,'%Y-%c-%d') as addTime," +
........
'FROM article LEFT JOIN type ON article.type_id = type.Id '
跨域问题
第一次(自己给自己)担任后端,遇到跨域问题是又激动又心慌的。
非同源请求,均为跨域。名词解释:同源 —— 如果两个页面拥有相同的协议(protocol),端口(port)和主机(host),那么这两个页面就属于同一个源(origin)。我的跨域问题是由于端口问题不同而造成的。
解决跨域问题主要采取的方法有:JSONP、CORS、postMessage、proxy代理等等。这里通过使用egg-cors插件来完成CORS方法的跨域。
egg-cors
模块是专门用来解决egg.js
跨域问题的,只要简单的配置就可以完成跨域的设置。
config.security = {
csrf: {
enable: false
},
domainWhiteList: [ '*' ]
};
config.cors = {
origin: 'http://localhost:3000', //服务器名称
credentials: true,//允许cookie跨域
withCredentials: true,
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS'
};
react-router-dom(5.x)使用
编写后台管理应用页面,是直接使用了create-react-app去构建的,所以路由部分当然用起了react-router-dom。不过使用的过程,还是遇到很多问题的,比如说传递url的参数问题。不过,看文档啊!!!
在在React Router v4中,我们可以从props中获得history对象、url参数……比如:
let tmpId = props.match.params.id
<button type="button" onClick={() => props.history.goBack()}>
然而从5.1版开始,React Router将包括四个有用的钩子,这也是此次项目实践中学习到的。你可以用它们来编写更干净整洁的代码,让人赏心悦目~
UseParams
useParams钩子将从你的应用URL返回一个键/值对对象。在一个复杂的应用程序中,通常会有许多动态的导航链接。
<Route path="/adminIndex/addArticle/:id">
……
//addArticle.js
let {id} = useParams();
UseLocation
可以访问location对象
let location = useLocation();
useHistory
通过使用useHistory钩子,你不需要Route组件来传递它就获得history对象。
function Users() {
let history = useHistory();
return (
<div>
<button type="button" onClick={() => history.goBack()}>
Go back
</button>
</div>
);
}
useRouteMatch
省去了编写<Route>组件就可以让组件去访问匹配数据。
// before
import { Route } from 'react-router-dom'
function App() {
return (
<div>
{/* ... */}
<Route
path="/BLOG/:slug/"
strict
sensitive
render={({ match }) => {
return match ? <BlogPost match={match} /> : <NotFound />
}}
/>
</div>
)
}
// after
import { useRouteMatch } from 'react-router-dom'
function App() {
let match = useRouteMatch({
path: '/BLOG/:slug/',
strict: true,
sensitive: true
})
return (
<div>
{/* ... */}
{match ? <BlogPost match={match} /> : <NotFound />}
</div>
)
}
总结
其实写这个小项目的过程会遇到许许多多的errors,但是经过反复地审查代码,总归一一解决。最大的收获是,尝试和学会使用了很多有用方便的库、更理解了整个前台后台怎么交互的、不断看文档和学习巩固知识等等……最大的感受是:前端技术迭代太快了,1年前的用法可能就过时了,突然就有点疲惫……还有好多东西没学呢呜呜呜呜呜呜呜
参考和学习链接:
① 跨域