托管平台:gitee
项目地址:khigh.gitee.io/#/
初心:一直想要做一个自己的一个作品——博客,可奈何某宝买的服务器经常出问题,域名需要钱,服务器需要钱。于是想出用gitee page来托管站点。可gitee托管只能是静态站点,该如何实现这么多的文章数据管理呢~ 于是,老夫用json来管理文章列表,异步请求json来生成网站的分类、文章列表、文章统计等等,通过不同路由来实现访问不同的文章。
聊聊技术:
整体使用了react with typescript
路由:使用了hash路由,由于只生成一个html,不能为每个路由自动生成html!!!,页面部分使用require.context
来读取文件,这样就不用手动来引用新写的页面
// ./src/App.tsx
import React from "react";
import { Switch, Route, HashRouter as Router } from "react-router-dom";
// import Layout from './Layout';
import { store } from "./util";
import { Provider } from "react-redux";
const context: any = (require as any).context("./page", true, /index\.tsx/);
const keys: string[] = context.keys();
const page404: any = (require as any).context("./page", false, /404\.tsx/);
const keys404: string[] = page404.keys();
export default class App extends React.Component<any, any> {
render() {
return (
<Provider store={store}>
<Router>
{/* <Layout> */}
<Switch>
{keys.map((key: string) => {
const pathArr: string[] = key
.replace(/^\./, "")
.replace(/\/index\.tsx$/, "")
.split("/");
const path: string = pathArr.join("/") || "/";
return (
<Route
key={path}
path={path}
exact
component={context(key).default}
/>
);
})}
{keys404.map((key: string) => {
return <Route key={key} component={page404(key).default} />
})}
</Switch>
{/* </Layout> */}
</Router>
</Provider>
);
}
}
复制代码
数据流部分:使用了rematch,是真的好用啊!!
页面connect连接数据流使用了高阶组件来包裹。
/**
* @description:用以connect组件和model的装饰器函数
*/
type IConnectFunc = (payload: any) => any;
export const connectModel = (
stateFunc?: IConnectFunc,
dispatchFunc?: IConnectFunc
): any => {
const mapState: any = stateFunc ? stateFunc : (state: any) => ({});
const mapDispatch: any = dispatchFunc ? dispatchFunc : (dispatch: any) => { };
return (WrapperComponent: any) => {
class App extends React.Component<any, any> {
public static displayName =
"@connect" +
(WrapperComponent.displayName
? `(${WrapperComponent.displayName})`
: "");
public render() {
return <WrapperComponent {...this.props} />;
}
}
const connected: any = connect(
mapState,
mapDispatch
)(App);
return connected;
};
};
/**
* @description:获取store
*/
export const store: any = (() => {
const context: any = (require as any).context("../models", true, /\.ts$/);
const keys: string[] = context.keys();
let models: {[propName:string]:any} = {};
keys.forEach((key: string) => {
const name: string = key.replace(/^\.\//, "").replace(/\.ts$/, "");
let mdl: any = context(key);
mdl[name] = _.cloneDeep(mdl.default);
delete mdl.default;
models = {
...models,
...mdl
};
});
const store = init({
models
});
return store;
})();
复制代码
这样在使用的时候只要装饰下,就能根据文件名读取store
//用类来当接口的好处是既可以当接口,也可以new来当初始值
class Props{}
class State{}
@connectModel(
(state: any) => ({
location: state.globalData.location,
articles: state.globalData.articles,
siteInfo: state.globalData.siteInfo,
}),
(dispatch: any) => ({
setData: dispatch.globalData.setData
})
)
export default class Component extends React.Component<Props,State>{
public static defaultProps=new Props();
public state=new State();
public render(){
return <div>app</div>
}
}
复制代码
动态运行代码:khigh.gitee.io/#/codeRunne…
目前支持动态运行js代码和简单的react代码,通过动态写入iframe来实现代码运行:
详情见:./src/util/index.tsx
$("body").append(`
<div class="code-preview-wrapper" id="code-preview-wrapper">
<iframe></iframe>
</div>
`);
const iframe: HTMLIFrameElement = $("#code-preview-wrapper iframe")[0];
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
iframeDoc.open();
iframeDoc.write(html);//html部分需要将要运行的代码封装成一个html string来装入iframe达到动态运行效果
iframeDoc.close();
复制代码
文章统计:khigh.gitee.io/#/artSummar…
使用g2,根据获取的文章列表数据来动态生成饼图和矩形树图。
支持插入在md中插入iframe并且展示:khigh.gitee.io/#/aboutme
功能原型就是动态运行代码的那几段函数: