Open tunnckoCore opened 7 years ago
basic prototype, but probably something similar would work (declarative routing)
the snippet is from React Router v4, a bit adapted
let router = null
const Router = ({ children }) => {
router = gibon()
return <div>{children}</div>
}
const Link = ({ to, children }) => {
return (
<a href={to}>
{children}
</a>
)
}
const Route = ({ path, state, exact, component }) => {
router.addRoute(path, (ctx) =>
component(
Object.assign(
{},
{
state,
match: {
path: path,
isExact: exact,
url: window.location.href,
params: ctx.params
}
}
)
)
)
}
const BasicExample = () => (
<Router>
<div>
<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>
</Router>
)
const Home = () => (
<div>
<h2>Home</h2>
</div>
)
const About = () => (
<div>
<h2>About</h2>
</div>
)
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Route path={`${match.url}/:topicId`} component={Topic} />
<Route
exact
path={match.url}
render={() => <h3>Please select a topic.</h3>}
/>
</div>
)
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
)
some chika
with latest #85 and #84
const html = require('bel')
const dush = require('dush')
const router = require('dush-router')
const nanomorph = require('nanomorph')
const actions = require('./dush-actions-plugin')
// const app = dush().use(
// actions({
// state: {
// text: 'Hello',
// name: 'Charlike'
// },
// effects: {
// changeBoth: function ({ actions }, data, arg2) {
// actions.changeText({ welcome: data.text })
// actions.changeName(data.name, arg2)
// }
// },
// reducers: {
// changeText: ({ emit, state }, data) => ({ text: data.welcome }),
// changeName: ({ actions, state }, name, arg2) => ({ name, arg2 })
// }
// })
// )
function chika (model) {
const app = dush().use(router()).use(actions(model))
let tree = null
let data = {}
app.off('route')
app.on('route', (view, ctx) => {
const match = {
pathname: ctx.pathname,
params: ctx.params,
route: ctx.route
}
// allows:
// ({ state, actions, emit, params, match })
// ({ state, actions, emit }, params)
// ({ state, actions, emit }, params, { route, pathname })
// ({ state, actions, emit }, { userId, photoId })
const likeProps = {
actions: app.emit,
emit: app.emit,
state: app.state,
params: match.params,
match: match
}
// each route will have signature: ({ state, actions }, params, match)
// so it is easy to destruct `params` and `match`
return (tree = nanomorph(tree, view(likeProps, ctx.params, match)))
})
app.start = function start () {
tree = app.navigate(window.location.pathname, app.state)
app.on('render', (node, hist) => {
if (hist) {
window.history.replaceState(data, '', node.pathname)
} else {
window.history.pushState(data, '', node.pathname)
}
app.navigate(node.pathname, app.state)
})
app.on('historyChange', (node) => {
app.emit('render', node, true)
})
app.on('hrefChange', (node) => {
if (node.href === window.location.href) return
app.emit('render', node)
})
return tree
}
app.mount = function mount (sel) {
let main = typeof sel === 'string' ? document.querySelector(sel) : sel
let newTree = app.start()
tree = nanomorph(main, newTree)
}
return app
}
const app = chika({
state: {
title: 'Hello',
name: 'Charlike'
},
effects: {
changeBoth ({ actions, emit }, data, arg2) {
actions.changeText({ welcome: data.text })
actions.changeName(data.name, arg2)
}
},
reducers: {
changeText: ({ actions, emit, state }, data) => ({ title: data.welcome }),
changeName: ({ actions, emit, state }, name, arg2) => ({ name, arg2 })
}
})
// let routes = {
// '/': ({ actions, emit, state }, params, match) =>
// html`<div><h1>home</h1><h2>${state.title}</h2></div>`,
// '/about': ({ actions, emit, state }, params, match) =>
// html`<div><h1>about</h1><h2>${state.title}</h2></div>`,
// '/users/:user': ({ actions, emit, state }, params, match) => html`<div>
// <h1>user</h1>
// <h2>${params.user}</h2>
// <h3>${state.title}</h3>
// </div>`,
// '/users/:user/edit': ({ actions, emit, state }, params, match) => html`<div>
// <h1>user edit</h1>
// <h2>${params.user}</h2>
// <h3>${state.title}</h3>
// </div>`,
// '/groups/:group/users/:user/edit': ({ actions, params, state }) => html`<div>
// <h1>edit user from group: ${JSON.stringify(params)}</h1>
// <h2>user: ${params.user}</h2>
// <h3>title: ${state.title}</h3>
// </div>`
// }
// Object.keys(routes).forEach((route) => {
// app.addRoute(route, routes[route])
// })
// app.use((app) => {
// console.log('state:', app.state)
// })
app.mount('#app')
Not considered yet, because it will got to 1kb, not 500bytes.
But it is more smaller and more stable, based on
dush-router
and just 2 events forhrefChange
andhistoryChange
. A lot more easier to build app on top of it.sample app built on it, using
nanomorph