amis/examples/components/App.tsx

863 lines
23 KiB
TypeScript
Raw Normal View History

2019-06-11 17:00:02 +08:00
import React from 'react';
2019-04-30 11:11:25 +08:00
import NotFound from '../../src/components/404';
import Layout from '../../src/components/Layout';
import AsideNav from '../../src/components/AsideNav';
2020-10-22 20:04:52 +08:00
import {
AlertComponent,
Button,
2020-10-22 20:04:52 +08:00
Drawer,
Spinner,
2020-10-22 20:04:52 +08:00
ToastComponent
} from '../../src/components/index';
2020-12-29 13:06:53 +08:00
import {eachTree, mapTree} from '../../src/utils/helper';
import {Icon} from '../../src/components/icons';
import '../../src/locale/en-US';
import {withRouter} from 'react-router';
2019-04-30 11:11:25 +08:00
import Select from '../../src/components/Select';
import InputBox from '../../src/components/InputBox';
2019-06-04 16:24:09 +08:00
import DocSearch from './DocSearch';
2021-01-04 20:10:08 +08:00
import Doc from './Doc';
import DocNavCN from './DocNavCN';
2020-07-24 17:20:08 +08:00
import Example, {examples} from './Example';
import CSSDocs, {cssDocs} from './CssDocs';
import Components, {components} from './Components';
import {
BrowserRouter as Router,
Route,
Redirect,
Switch,
Link,
NavLink
} from 'react-router-dom';
2020-12-29 13:06:53 +08:00
declare const _hmt: any;
2019-06-04 20:13:40 +08:00
let ContextPath = '';
2019-04-30 11:11:25 +08:00
2019-05-09 19:40:59 +08:00
if (process.env.NODE_ENV === 'production') {
2019-11-07 10:41:14 +08:00
ContextPath = '/amis';
2019-05-09 19:40:59 +08:00
}
2020-11-30 00:37:09 +08:00
export function getContextPath() {
return ContextPath;
}
2019-04-30 11:11:25 +08:00
const themes = [
2019-11-07 10:41:14 +08:00
{
label: '云舍',
2019-11-07 10:41:14 +08:00
ns: 'cxd-',
value: 'cxd'
},
{
label: '仿 AntD',
ns: 'antd-',
value: 'antd'
},
{
label: 'ang',
ns: 'a-',
value: 'ang'
},
{
label: 'Dark',
ns: 'dark-',
value: 'dark'
2019-11-07 10:41:14 +08:00
}
2019-04-30 11:11:25 +08:00
];
2020-06-02 20:41:51 +08:00
const locales = [
{
2020-07-23 20:31:51 +08:00
label: '中文',
value: 'zh-CN'
2020-06-02 20:41:51 +08:00
},
{
label: 'English',
value: 'en-US'
2020-06-02 20:41:51 +08:00
}
];
const viewModes = [
{
label: '桌面端',
value: 'pc'
},
{
label: '移动端',
value: 'mobile'
}
];
2021-06-03 22:09:30 +08:00
const docVersions = [
{
label: '主干版本',
value: '',
url: '/zh-CN/docs/start/1-2-0'
2021-06-03 22:09:30 +08:00
},
{
label: '1.1.x 文档',
value: '1.1.7',
url: 'https://aisuda.github.io/amis-1.1.7/zh-CN/docs/index'
}
];
function getPath(path: string) {
2020-07-30 22:21:03 +08:00
return path
? path[0] === '/'
? ContextPath + path
: `${ContextPath}/${path}`
: '';
}
2020-10-23 17:17:19 +08:00
class BackTop extends React.PureComponent {
state = {
show: false
};
componentDidMount() {
document.addEventListener('scroll', this.handleScroll);
2020-10-23 17:17:19 +08:00
}
componentWillUnmount() {
document.removeEventListener('scroll', this.handleScroll);
2020-10-23 17:17:19 +08:00
}
handleScroll = (e: any) => {
2020-10-23 17:17:19 +08:00
this.setState({
show: e.target.scrollingElement?.scrollTop > 350
2020-10-23 17:17:19 +08:00
});
};
2020-10-23 17:17:19 +08:00
render() {
return (
<div
className={`Backtop ${this.state.show ? 'visible' : ''}`}
onClick={() => scrollTo({top: 0})}
>
<i className="fa fa-rocket"></i>
</div>
);
}
}
// @ts-ignore
@withRouter // @ts-ignore
export class App extends React.PureComponent<{
location: Location;
}> {
2019-11-07 10:41:14 +08:00
state = {
viewMode: localStorage.getItem('amis-viewMode') || 'pc',
2019-11-07 10:41:14 +08:00
offScreen: false,
folded: false,
2019-11-07 10:41:14 +08:00
headerVisible: true,
themes: themes,
theme:
themes.find(item => item?.value === localStorage.getItem('amis-theme')) ||
themes[0],
locale: localStorage.getItem('amis-locale')
? localStorage.getItem('amis-locale')?.replace('zh-cn', 'zh-CN')
: '',
navigations: [],
filter: '' // 导航过滤,方便找组件
2019-11-07 10:41:14 +08:00
};
constructor(props: any) {
2019-11-07 10:41:14 +08:00
super(props);
2020-07-24 17:20:08 +08:00
this.setNavigations = this.setNavigations.bind(this);
this.setNavigationFilter = this.setNavigationFilter.bind(this);
document.querySelector('body')?.classList.add(this.state.theme.value);
2019-11-07 10:41:14 +08:00
}
componentDidUpdate(preProps: any, preState: any) {
2019-11-07 10:41:14 +08:00
const props = this.props;
if (preState.theme.value !== this.state.theme.value) {
2020-12-29 13:06:53 +08:00
[].slice
.call(document.querySelectorAll('link[title]'))
.forEach((item: HTMLLinkElement) => {
const theme = item.getAttribute('title');
item.disabled = theme !== this.state.theme.value;
2020-11-27 17:29:49 +08:00
});
const body = document.body;
2020-12-29 13:06:53 +08:00
body.classList.remove(preState.theme.value);
body.classList.add(this.state.theme.value);
2019-09-09 00:53:39 +08:00
}
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
if (props.location.pathname !== preProps.location.pathname) {
this.setState(
{
offScreen: false
},
() => window.scrollTo(0, 0)
);
2020-10-23 17:17:19 +08:00
_hmt && _hmt.push(['_trackPageview', props.location.pathname]);
2019-09-09 00:53:39 +08:00
}
2019-11-07 10:41:14 +08:00
}
2019-04-30 11:11:25 +08:00
setNavigations(items: any, resetFilter = true) {
2020-07-24 17:20:08 +08:00
this.setState({
2021-04-16 15:09:13 +08:00
navigations: items,
filter: resetFilter ? '' : this.state.filter
2020-07-24 17:20:08 +08:00
});
}
renderHeader(docPage = true) {
2019-11-07 10:41:14 +08:00
const location = this.props.location;
const theme = this.state.theme;
if (location.pathname === '/edit') {
return (
<div id="headerBar" className="box-shadow bg-dark">
<div className={`${theme.ns}Layout-brand`}>amis </div>
2019-11-07 10:41:14 +08:00
</div>
);
2019-09-09 00:53:39 +08:00
}
2019-11-07 10:41:14 +08:00
return (
2020-07-23 20:31:51 +08:00
<>
<div
className={`${theme.ns}Layout-brandBar ${
docPage ? 'DocLayout-brandBar' : ''
}`}
>
2020-10-22 20:04:52 +08:00
<div
2019-11-07 10:41:14 +08:00
onClick={() => this.setState({offScreen: !this.state.offScreen})}
className={`${theme.ns}Layout-offScreen-btn ${
docPage ? 'DocLayout-offScreen-btn' : ''
2020-12-24 22:26:45 +08:00
} pull-right visible-xs`}
2019-11-07 10:41:14 +08:00
>
2020-10-22 20:04:52 +08:00
<i className="bui-icon iconfont icon-collapse"></i>
</div>
2020-07-23 20:31:51 +08:00
{docPage ? (
<div
className={`${theme.ns}Layout-brand ${
docPage ? 'DocLayout-brand' : ''
}`}
>
<Link to={`${ContextPath}/docs`}>
<div className="logo"></div>
</Link>
</div>
) : (
<div className={`${theme.ns}Layout-brand text-ellipsis`}>
<i className="fa fa-paw" />
<span className="hidden-folded m-l-sm">AMIS </span>
</div>
)}
2019-11-07 10:41:14 +08:00
</div>
2019-09-09 00:53:39 +08:00
<div
className={`${theme.ns}Layout-headerBar ${
docPage ? 'DocLayout-headerBar pc:inline-flex' : 'pc:flex'
} items-center`}
>
{docPage ? null : (
<Button
onClick={() => this.setState({folded: !this.state.folded})}
type="button"
level="link"
className="navbar-btn"
>
<i
className={`fa fa-${
this.state.folded ? 'indent' : 'dedent'
} fa-fw`}
></i>
</Button>
)}
<ul className={`HeaderLinks`}>
<NavLink
to={`${ContextPath}/zh-CN/docs`}
activeClassName="is-active"
>
2020-07-24 17:20:08 +08:00
</NavLink>
<NavLink
to={`${ContextPath}/zh-CN/components`}
activeClassName="is-active"
>
</NavLink>
<NavLink
to={`${ContextPath}/zh-CN/style`}
activeClassName="is-active"
>
2020-11-30 00:37:09 +08:00
</NavLink>
<NavLink
to={`${ContextPath}/examples/index`}
activeClassName="is-active"
>
</NavLink>
2020-10-22 15:28:24 +08:00
<a
href="https://github.com/fex-team/amis-editor-demo"
target="_blank"
>
2020-07-31 12:40:04 +08:00
</a>
2020-07-31 13:02:48 +08:00
{/* <a href="https://suda.bce.baidu.com" target="_blank">
2020-07-31 12:40:04 +08:00
2020-07-31 13:02:48 +08:00
</a> */}
2020-07-23 20:31:51 +08:00
</ul>
2021-06-04 10:27:19 +08:00
<div className="hidden-xs ml-auto">
2020-07-23 20:31:51 +08:00
<Select
2021-06-03 22:09:30 +08:00
overlayPlacement="right-bottom-right-top"
2020-07-23 20:31:51 +08:00
clearable={false}
theme={this.state.theme.value}
value={this.state.locale || 'zh-CN'}
2020-07-23 20:31:51 +08:00
options={locales}
onChange={locale => {
this.setState({locale: (locale as any).value});
localStorage.setItem('amis-locale', (locale as any).value);
window.location.reload();
2020-07-23 20:31:51 +08:00
}}
/>
2020-06-02 20:41:51 +08:00
</div>
<div className="hidden-xs ml-2">
2020-07-23 20:31:51 +08:00
<Select
2021-06-03 22:09:30 +08:00
overlayPlacement="right-bottom-right-top"
2020-07-23 20:31:51 +08:00
clearable={false}
theme={this.state.theme.value}
value={this.state.theme}
options={this.state.themes}
onChange={theme => {
this.setState({theme});
localStorage.setItem('amis-theme', `${(theme as any).value}`);
2020-07-29 20:25:04 +08:00
document
.querySelector('body')
?.classList[
(theme as any).value === 'dark' ? 'add' : 'remove'
]('dark');
2020-07-23 20:31:51 +08:00
}}
/>
2019-11-07 10:41:14 +08:00
</div>
<div className="hidden-xs ml-2">
<Select
2021-06-03 22:09:30 +08:00
overlayPlacement="right-bottom-right-top"
clearable={false}
theme={this.state.theme.value}
value={this.state.viewMode || 'pc'}
options={viewModes}
onChange={viewMode => {
this.setState({viewMode: (viewMode as any).value});
localStorage.setItem('amis-viewMode', (viewMode as any).value);
window.location.reload();
}}
/>
</div>
2021-06-03 22:09:30 +08:00
<div className="hidden-xs ml-2">
<Select
overlayPlacement="right-bottom-right-top"
clearable={false}
theme={this.state.theme.value}
value={docVersions[0].value}
options={docVersions}
onChange={(doc: any) => {
if (doc.url && /^https?\:\/\//.test(doc.url)) {
2021-06-03 22:09:30 +08:00
window.open(doc.url);
} else {
window.location.href = doc.url;
2021-06-03 22:09:30 +08:00
}
}}
/>
</div>
<div id="Header-toolbar"></div>
2020-08-21 17:33:31 +08:00
</div>
2020-08-21 12:54:47 +08:00
{docPage ? (
2020-12-28 12:27:28 +08:00
<>
<div
className={`${theme.ns}Layout-searchBar ${
docPage ? 'DocLayout-searchBar' : ''
} hidden-xs hidden-sm`}
>
<DocSearch theme={theme} />
</div>
<a
className="gh-icon"
href="https://github.com/baidu/amis"
target="_blank"
>
<i className="fa fa-github" />
</a>
2020-12-28 12:27:28 +08:00
</>
) : null}
2020-07-23 20:31:51 +08:00
</>
2019-11-07 10:41:14 +08:00
);
}
2019-04-30 11:11:25 +08:00
setNavigationFilter(value: string) {
this.setState({
filter: value
});
}
2020-10-22 20:04:52 +08:00
renderNavigation() {
return (
<div className="Doc-navigation">
<InputBox
theme={this.state.theme.value}
placeholder={'过滤...'}
2021-04-16 15:09:13 +08:00
value={this.state.filter || ''}
onChange={this.setNavigationFilter}
2021-03-05 10:53:10 +08:00
className="m-b m-r-md"
2021-04-16 15:09:13 +08:00
clearable={false}
/>
{this.renderAsideNav()}
</div>
);
}
renderAsideNav() {
const filterReg = new RegExp(
this.state.filter.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&'),
'i'
);
2020-10-22 20:04:52 +08:00
return (
<AsideNav
navigations={this.state.navigations.map((item: any) => ({
...item,
children: item.children
? item.children
.filter((item: any) => {
if (item.label) {
return filterReg.exec(item.label);
}
return true;
})
.map((item: any) => ({
...item,
className: 'is-top'
}))
: []
}))}
renderLink={({
link,
active,
toggleExpand,
classnames: cx,
depth
}: any) => {
let children = [];
if (link.children && link.children.length) {
children.push(
<span
key="expand-toggle"
className={cx('AsideNav-itemArrow')}
onClick={e => toggleExpand(link, e)}
></span>
);
}
2020-10-22 20:04:52 +08:00
link.badge &&
2020-10-22 20:04:52 +08:00
children.push(
<b
key="badge"
className={cx(
`AsideNav-itemBadge`,
link.badgeClassName || 'bg-info'
)}
>
{link.badge}
</b>
2020-10-22 20:04:52 +08:00
);
if (link.icon) {
children.push(
<i key="icon" className={cx(`AsideNav-itemIcon`, link.icon)} />
);
} else if (this.state.folded && depth === 1) {
children.push(
<i
key="icon"
className={cx(
`AsideNav-itemIcon`,
link.children ? 'fa fa-folder' : 'fa fa-info'
)}
/>
);
}
children.push(
<span className={cx('AsideNav-itemLabel')} key="label">
{link.label}
</span>
);
return link.path ? (
/^https?\:/.test(link.path) ? (
<a target="_blank" href={link.path} rel="noopener">
2020-10-22 20:04:52 +08:00
{children}
</a>
) : (
<Link
to={
getPath(link.path) ||
(link.children && getPath(link.children[0].path))
}
>
{children}
</Link>
)
) : (
<a onClick={link.children ? () => toggleExpand(link) : undefined}>
{children}
</a>
);
}}
isActive={(link: any) => isActive(link, location)}
/>
);
}
renderExamples() {
const theme = this.state.theme;
return (
<Layout
theme={theme.value}
offScreen={this.state.offScreen}
folded={this.state.folded}
header={this.renderHeader(false)}
aside={this.renderAsideNav()}
>
<ToastComponent theme={theme.value} locale={this.state.locale} />
<AlertComponent theme={theme.value} locale={this.state.locale} />
{/* {React.cloneElement(this.props.children as any, {
key: theme.value,
...(this.props.children as any).props,
setNavigations: this.setNavigations,
theme: theme.value,
classPrefix: theme.ns,
viewMode: this.state.viewMode,
locale: this.state.locale,
offScreen: this.state.offScreen,
ContextPath
})} */}
{this.renderContent()}
</Layout>
2020-10-22 20:04:52 +08:00
);
2020-07-23 20:31:51 +08:00
}
renderContent() {
const locale = 'zh-CN'; // 暂时不支持切换,因为目前只有中文文档
const theme = this.state.theme;
return (
<React.Suspense
fallback={<Spinner overlay spinnerClassName="m-t-lg" size="lg" />}
>
<Switch>
<Redirect
from={`${ContextPath}/`}
to={`${ContextPath}/${locale}/docs/index`}
exact
/>
{/* docs */}
<Redirect
from={`${ContextPath}/docs`}
to={`${ContextPath}/${locale}/docs/index`}
exact
/>
<Redirect
from={`${ContextPath}/docs/index`}
to={`${ContextPath}/${locale}/docs/index`}
exact
/>
<Redirect
from={`${ContextPath}/docs/*`}
to={`${ContextPath}/${locale}/docs/*`}
/>
<Redirect
from={`${ContextPath}/${locale}/docs`}
to={`${ContextPath}/${locale}/docs/index`}
exact
/>
{/* components */}
<Redirect
from={`${ContextPath}/components`}
to={`${ContextPath}/${locale}/components/page`}
exact
/>
<Redirect
from={`${ContextPath}/components/page`}
to={`${ContextPath}/${locale}/components/page`}
exact
/>
<Redirect
from={`${ContextPath}/components/*`}
to={`${ContextPath}/${locale}/components/*`}
exact
/>
<Redirect
from={`${ContextPath}/${locale}/components`}
to={`${ContextPath}/${locale}/components/page`}
exact
/>
{/* expamles */}
<Redirect
from={`${ContextPath}/examples`}
to={`${ContextPath}/examples/index`}
exact
/>
<Redirect
from={`${ContextPath}/${locale}/style`}
to={`${ContextPath}/${locale}/style/index`}
exact
/>
<Route
path={`${ContextPath}/${locale}/docs`}
render={(props: any) => (
<Doc
{...{
setNavigations: this.setNavigations,
theme: theme.value,
classPrefix: theme.ns,
viewMode: this.state.viewMode,
locale: this.state.locale,
offScreen: this.state.offScreen,
ContextPath,
showCode: false
}}
{...props}
/>
)}
/>
<Route
path={`${ContextPath}/${locale}/components`}
render={(props: any) => (
<Components
{...{
setNavigations: this.setNavigations,
theme: theme.value,
classPrefix: theme.ns,
viewMode: this.state.viewMode,
locale: this.state.locale,
offScreen: this.state.offScreen,
ContextPath,
showCode: false
}}
{...props}
/>
)}
/>
<Route
path={`${ContextPath}/examples`}
render={(props: any) => (
<Example
{...{
setNavigations: this.setNavigations,
theme: theme.value,
classPrefix: theme.ns,
viewMode: this.state.viewMode,
locale: this.state.locale,
offScreen: this.state.offScreen,
ContextPath,
showCode: false
}}
{...props}
/>
)}
/>
<Route
path={`${ContextPath}/${locale}/style`}
render={(props: any) => (
<CSSDocs
{...{
setNavigations: this.setNavigations,
theme: theme.value,
classPrefix: theme.ns,
viewMode: this.state.viewMode,
locale: this.state.locale,
offScreen: this.state.offScreen,
ContextPath,
showCode: false
}}
{...props}
/>
)}
/>
<Route
render={() => (
<div className="Doc-content">
<NotFound />
</div>
)}
/>
</Switch>
</React.Suspense>
);
}
2019-11-07 10:41:14 +08:00
render() {
const theme = this.state.theme;
const location = this.props.location;
2021-04-21 19:24:34 +08:00
if (/examples\/app/.test(location.pathname)) {
return (
<>
<ToastComponent theme={theme.value} locale={this.state.locale} />
<AlertComponent theme={theme.value} locale={this.state.locale} />
{/* {React.cloneElement(this.props.children as any, {
key: theme.value,
...(this.props.children as any).props,
setNavigations: this.setNavigations,
theme: theme.value,
classPrefix: theme.ns,
viewMode: this.state.viewMode,
locale: this.state.locale,
offScreen: this.state.offScreen,
ContextPath,
showCode: false
})} */}
{this.renderContent()}
</>
);
} else if (/examples/.test(location.pathname)) {
return this.renderExamples();
}
2020-07-23 20:31:51 +08:00
2019-11-07 10:41:14 +08:00
return (
<Layout
className={':DocLayout'}
2019-11-07 10:41:14 +08:00
theme={theme.value}
2020-07-23 20:31:51 +08:00
boxed={true}
2019-11-07 10:41:14 +08:00
offScreen={this.state.offScreen}
header={this.state.headerVisible ? this.renderHeader() : null}
headerClassName={':DocLayout-header'}
2019-11-07 10:41:14 +08:00
>
2020-06-02 20:41:51 +08:00
<ToastComponent theme={theme.value} locale={this.state.locale} />
<AlertComponent theme={theme.value} locale={this.state.locale} />
2020-07-23 20:31:51 +08:00
<div className="Doc">
2020-08-05 13:22:14 +08:00
<div className="Doc-nav hidden-xs hidden-sm">
2020-10-22 20:04:52 +08:00
{this.renderNavigation()}
2020-07-23 20:31:51 +08:00
</div>
2020-10-22 20:04:52 +08:00
<Drawer
size="xs"
className="Doc-navDrawer"
overlay
closeOnOutside
onHide={() => this.setState({offScreen: false})}
show={this.state.offScreen}
position="left"
>
2021-03-05 10:53:10 +08:00
<ul className={`HeaderLinks`}>
<NavLink
2021-03-05 10:53:10 +08:00
to={`${ContextPath}/zh-CN/docs`}
activeClassName="is-active"
>
</NavLink>
2021-03-05 10:53:10 +08:00
<NavLink
2021-03-05 10:53:10 +08:00
to={`${ContextPath}/zh-CN/components`}
activeClassName="is-active"
>
</NavLink>
<NavLink
2021-03-05 10:53:10 +08:00
to={`${ContextPath}/zh-CN/style`}
activeClassName="is-active"
>
</NavLink>
2021-03-05 10:53:10 +08:00
</ul>
2020-10-22 20:04:52 +08:00
{this.renderNavigation()}
</Drawer>
2020-10-23 17:17:19 +08:00
<BackTop />
2020-07-28 18:23:02 +08:00
{/* {React.cloneElement(this.props.children as any, {
2020-08-01 00:26:55 +08:00
key: theme.value,
2020-12-29 13:06:53 +08:00
...(this.props.children as any).props,
2020-07-24 17:20:08 +08:00
setNavigations: this.setNavigations,
2020-07-23 20:31:51 +08:00
theme: theme.value,
classPrefix: theme.ns,
viewMode: this.state.viewMode,
2020-07-31 13:18:44 +08:00
locale: this.state.locale,
2020-10-22 20:04:52 +08:00
offScreen: this.state.offScreen,
2020-07-31 13:18:44 +08:00
ContextPath
})} */}
{this.renderContent()}
2020-07-23 20:31:51 +08:00
</div>
2019-11-07 10:41:14 +08:00
</Layout>
);
}
2019-09-09 00:53:39 +08:00
}
2019-04-30 11:11:25 +08:00
2020-10-22 20:04:52 +08:00
function isActive(link: any, location: any) {
2020-10-22 20:36:01 +08:00
return !!(link.path && getPath(link.path) === location.pathname);
2020-10-22 20:04:52 +08:00
}
export function navigations2route(
navigations: any,
additionalProperties?: any
) {
let routes: any = [];
2019-11-07 10:41:14 +08:00
navigations.forEach((root: any) => {
2019-11-07 10:41:14 +08:00
root.children &&
2020-12-29 13:06:53 +08:00
eachTree(root.children, (item: any) => {
2019-11-07 10:41:14 +08:00
if (item.path && item.component) {
routes.push(
additionalProperties ? (
<Route
key={routes.length + 1}
path={
item.path[0] === '/'
? ContextPath + item.path
: `${ContextPath}/${item.path}`
}
render={(props: any) => (
<item.component {...additionalProperties} {...props} />
)}
/>
) : (
<Route
key={routes.length + 1}
path={
item.path[0] === '/'
? ContextPath + item.path
: `${ContextPath}/${item.path}`
}
component={item.component}
/>
)
2019-11-07 10:41:14 +08:00
);
}
});
});
2019-04-30 11:11:25 +08:00
2019-11-07 10:41:14 +08:00
return routes;
2019-09-09 00:53:39 +08:00
}
2019-04-30 11:11:25 +08:00
export default function entry() {
2020-07-30 22:21:03 +08:00
// PathPrefix = pathPrefix || DocPathPrefix;
return (
<Router>
<Switch>
<Route component={App}></Route>
<Route component={NotFound} />
</Switch>
2019-11-07 10:41:14 +08:00
</Router>
);
2019-09-09 00:53:39 +08:00
}