Skip to content

Instantly share code, notes, and snippets.

@guojianwei001
Created April 7, 2020 04:59
Show Gist options
  • Save guojianwei001/75a6a9f464449e8498ad90e82e2aaeac to your computer and use it in GitHub Desktop.
Save guojianwei001/75a6a9f464449e8498ad90e82e2aaeac to your computer and use it in GitHub Desktop.
MpexLL
<div id='app'></div>
let instances = []
const register = (comp) => instances.push(comp)
const unregister = (comp) => instances.splice(instances.indexOf(comp), 1)
const historyPush = (path) => {
history.pushState({}, null, path)
instances.forEach(instance => instance.forceUpdate())
}
const historyReplace = (path) => {
history.replaceState({}, null, path)
instances.forEach(instance => instance.forceUpdate())
}
const matchPath = (pathname, options) => {
const exact = options.exact || false
const path = options.path
if (!path) {
return {
path: null,
url: pathname,
isExact: true
}
}
const match = new RegExp(`^${path}`).exec(pathname)
if (!match)
return null
const url = match[0]
const isExact = pathname === url
if (exact && !isExact)
return null
return {
path,
url,
isExact,
}
}
const Route = React.createClass({
componentWillMount() {
addEventListener('popstate', this.handlePop)
register(this)
},
componentWillUnmount() {
unregister(this)
removeEventListener('popstate', this.handlePop)
},
handlePop() {
this.forceUpdate()
},
render() {
const {
path,
exact,
component,
render,
} = this.props
const match = matchPath(location.pathname, {
path,
exact
})
if (!match)
return null
if (component)
return React.createElement(component, {
match
})
if (render)
return render({
match
})
return null
}
})
const Link = React.createClass({
handleClick(event) {
const {
replace,
to
} = this.props
event.preventDefault()
replace ? historyReplace(to) : historyPush(to)
},
render() {
const {
to,
children
} = this.props
return (
<a href={to} onClick={this.handleClick}>
{children}
</a>
)
}
})
const Redirect = React.createClass({
componentDidMount() {
const {
to,
push
} = this.props
push ? historyPush(to) : historyReplace(to)
},
render() {
return null
}
})
// Implementation
const Home = () => (
<h2>Home</h2>
)
const About = () => (
<h2>About</h2>
)
const Topic = ({
topicId
}) => (
<h3>{topicId}</h3>
)
const Topics = ({
match
}) => {
const items = [{
name: 'Rendering with React',
slug: 'rendering'
}, {
name: 'Components',
slug: 'components'
}, {
name: 'Props v. State',
slug: 'props-v-state'
}, ]
return (
<div>
<h2>Topics</h2>
<ul>
{items.map(({ name, slug }) => (
<li key={name}>
<Link to={`${match.url}/${slug}`}>{name}</Link>
</li>
))}
</ul>
{items.map(({ name, slug }) => (
<Route key={name} path={`${match.path}/${slug}`} render={() => (
<Topic topicId={name} />
)} />
))}
<Route exact path={match.url} render={() => (
<h3>Please select a topic.</h3>
)}/>
</div>
)
}
const App = () => {
return (
<div>
<Route render={(props) => {
return <pre>URL: {JSON.stringify(props.match.url)}</pre>
}} />
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/topics" component={Topics} />
</div>
)
}
ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react-dom.min.js"></script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment