1.我们首先看看下面的代码
'use strict';
const chain =
require(
'ramda/src/chain');
const toReactComponent =
require(
'jsonml-to-react-component');
const exist =
require(
'exist.js');
const NotFound =
require(
'{{ themePath }}/template/NotFound');
function calcPropsPath(dataPath, params) {
return Object.keys(params).reduce(
(path, param) => path.replace(`:${param}`, params[param]),
dataPath
);
}
function hasParams(dataPath) {
return dataPath.split(
'/').some((snippet) => snippet.startsWith(
':'));
}
function defaultCollect(nextProps, callback) {
callback(
null, nextProps);
}
module.exports =
function getRoutes(data) {
const plugins = data.plugins;
const converters = chain((plugin) => plugin.converters || [], plugins);
const utils = {
get: exist.get,
toReactComponent(jsonml) {
return toReactComponent(jsonml, converters);
},
};
plugins.map((plugin) => plugin.utils || {})
.forEach((u) =>
Object.assign(utils, u));
function templateWrapper(template, dataPath = '') {
const Template =
require(
'{{ themePath }}/template' + template.replace(
/^\.\/template/,
''));
return (nextState, callback) => {
const propsPath = calcPropsPath(dataPath, nextState.params);
const pageData = exist.get(data.markdown, propsPath.replace(
/^\//,
'').split(
'/'));
const collect = Template.collect || defaultCollect;
collect(
Object.assign({}, nextState, {
data: data.markdown,
picked: data.picked,
pageData,
utils,
}), (err, nextProps) => {
const Comp = (hasParams(dataPath) || pageData) && err !==
404 ?
Template.default || Template : NotFound.default || NotFound;
const dynamicPropsKey = nextState.location.pathname;
Comp[dynamicPropsKey] = nextProps;
callback(err ===
404 ?
null : err, Comp);
});
};
}
const theme =
require(
'{{ themePath }}');
const routes =
Array.isArray(theme.routes) ? theme.routes : [theme.routes];
function processRoutes(route) {
if (
Array.isArray(route)) {
return route.map(processRoutes);
}
return Object.assign({}, route, {
onEnter: () => {
if (
typeof document !==
'undefined') {
}
},
component:
undefined,
getComponent: templateWrapper(route.component, route.dataPath || route.path),
indexRoute: route.indexRoute &&
Object.assign({}, route.indexRoute, {
component:
undefined,
getComponent: templateWrapper(
route.indexRoute.component,
route.indexRoute.dataPath || route.indexRoute.path
),
}),
childRoutes: route.childRoutes && route.childRoutes.map(processRoutes),
});
}
const processedRoutes = processRoutes(routes);
processedRoutes.push({
path:
'*',
getComponents: templateWrapper(
'./template/NotFound'),
});
return processedRoutes;
};
2.可以学到的内容
2.1 动态加载的方法getComponents,getIndexRoute,getChildRoutes等,可以参考react-router
function processRoutes(route) {
if (
Array.isArray(route)) {
return route.map(processRoutes);
}
return Object.assign({}, route, {
onEnter: () => {
if (
typeof document !==
'undefined') {
}
},
component:
undefined,
getComponent: templateWrapper(route.component, route.dataPath || route.path),
indexRoute: route.indexRoute &&
Object.assign({}, route.indexRoute, {
component:
undefined,
getComponent: templateWrapper(
route.indexRoute.component,
route.indexRoute.dataPath || route.indexRoute.path
),
}),
childRoutes: route.childRoutes && route.childRoutes.map(processRoutes),
});
}
2.2 传入默认的路由方式
processedRoutes.push({
path:
'*',
getComponents: templateWrapper(
'./template/NotFound'),
});
2.3 react-router的createElement配置
ReactRouter.match({ routes, location, basename }, () => {
const router =
<ReactRouter.Router
history={ReactRouter.useRouterHistory(history.createHistory)({ basename })}
routes={routes}
createElement={createElement}
/>;
ReactDOM.render(
router,
document.getElementById(
'react-content')
);
});
其中这里我们采用的是下面的函数,这个函数指定了当访问一个url的时候如何为我们的Component组件添加props:
module.exports =
function createElement(Component, props) {
const dynamicPropsKey = props.location.pathname;
return <Component {...props} {...Component[dynamicPropsKey]} />;
};
之所以我们这样做是上面通过了Component[dynamicPropsKey]传入了需要的props
const Comp = (hasParams(dataPath) || pageData) && err !==
404 ?
Template.default || Template : NotFound.default || NotFound;
const dynamicPropsKey = nextState.location.pathname;
Comp[dynamicPropsKey] = nextProps;
2.4 React中ES6模式导出要通过.default完成,而Commonjs规范不需要
const Comp = (hasParams(dataPath) || pageData) && err !==
404 ?
Template.default || Template : NotFound.default || NotFound;
2.5 URL映射到组件实例化
function templateWrapper(template, dataPath = '') {
const Template =
require(
'{{ themePath }}/template' + template.replace(
/^\.\/template/,
''));
return (nextState, callback) => {
const propsPath = calcPropsPath(dataPath, nextState.params);
const pageData = exist.get(data.markdown, propsPath.replace(
/^\//,
'').split(
'/'));
const collect = Template.collect || defaultCollect;
collect(
Object.assign({}, nextState, {
data: data.markdown,
picked: data.picked,
pageData,
utils,
}), (err, nextProps) => {
const Comp = (hasParams(dataPath) || pageData) && err !==
404 ?
Template.default || Template : NotFound.default || NotFound;
const dynamicPropsKey = nextState.location.pathname;
Comp[dynamicPropsKey] = nextProps;
callback(err ===
404 ?
null : err, Comp);
});
};
}