1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

client/router: create uid instead of displayName

This commit is contained in:
nkzawa 2016-10-06 10:20:48 +09:00
parent 0cc1ed0516
commit 2d8959d99c
2 changed files with 27 additions and 31 deletions

View file

@ -13,6 +13,6 @@ const Component = evalScript(component).default
const router = new Router({ Component, props }) const router = new Router({ Component, props })
const container = document.getElementById('__next') const container = document.getElementById('__next')
const appProps = { Component, props, router: {} } const appProps = { Component, props, router }
render(createElement(App, { ...appProps }), container) render(createElement(App, { ...appProps }), container)

View file

@ -6,21 +6,18 @@ export default class Router {
constructor (initialData) { constructor (initialData) {
this.subscriptions = [] this.subscriptions = []
const { Component } = initialData const id = createUid()
const { pathname } = location const route = toRoute(location.pathname)
const route = toRoute(pathname)
this.currentRoute = route this.currentRoute = route
this.currentComponent = Component.displayName this.currentComponentData = { ...initialData, id }
this.currentComponentData = initialData
// set up the component cache (by route keys) // set up the component cache (by route keys)
this.components = { [route]: initialData } this.components = { [route]: initialData }
// in order for `e.state` to work on the `onpopstate` event // in order for `e.state` to work on the `onpopstate` event
// we have to register the initial route upon initialization // we have to register the initial route upon initialization
const url = pathname + (location.search || '') + (location.hash || '') this.replace(id, getURL())
this.replace(Component, url)
this.onPopState = this.onPopState.bind(this) this.onPopState = this.onPopState.bind(this)
window.addEventListener('unload', () => {}) window.addEventListener('unload', () => {})
@ -30,8 +27,7 @@ export default class Router {
onPopState (e) { onPopState (e) {
this.abortComponentLoad() this.abortComponentLoad()
const cur = this.currentComponent const cur = this.currentComponent
const pathname = location.pathname const url = getURL()
const url = pathname + (location.search || '') + (location.hash || '')
const { fromComponent, route } = e.state || {} const { fromComponent, route } = e.state || {}
if (fromComponent && cur && fromComponent === cur) { if (fromComponent && cur && fromComponent === cur) {
// if the component has not changed due // if the component has not changed due
@ -47,7 +43,7 @@ export default class Router {
// since the URL has already changed // since the URL has already changed
location.reload() location.reload()
} else { } else {
this.currentRoute = route || toRoute(pathname) this.currentRoute = route || toRoute(location.pathname)
this.currentComponent = data.Component.displayName this.currentComponent = data.Component.displayName
this.currentComponentData = data this.currentComponentData = data
this.set(url) this.set(url)
@ -88,40 +84,31 @@ export default class Router {
this.change('pushState', fromComponent, url, fn) this.change('pushState', fromComponent, url, fn)
} }
replace (fromComponent, url, fn) { replace (id, url, fn) {
this.change('replaceState', fromComponent, url, fn) this.change('replaceState', id, url, fn)
} }
change (method, component, url, fn) { change (method, id, url, fn) {
this.abortComponentLoad() this.abortComponentLoad()
const set = (name) => { const set = (id) => {
this.currentComponent = name const state = id ? { fromComponent: id, route: this.currentRoute } : {}
const state = name
? { fromComponent: name, route: this.currentRoute }
: {}
history[method](state, null, url) history[method](state, null, url)
this.set(url) this.set(url)
if (fn) fn(null) if (fn) fn(null)
} }
const componentName = component && component.displayName if (this.currentComponentData && id !== this.currentComponentData.id) {
if (component && !componentName) {
throw new Error('Initial component must have a unique `displayName`')
}
if (this.currentComponent &&
componentName !== this.currentComponent) {
this.fetchComponent(url, (err, data) => { this.fetchComponent(url, (err, data) => {
if (!err) { if (!err) {
this.currentRoute = toRoute(url) this.currentRoute = toRoute(url)
this.currentComponentData = data this.currentComponentData = data
set(data.Component.displayName) set(data.id)
} }
if (fn) fn(err, data) if (fn) fn(err, data)
}) })
} else { } else {
set(componentName) set(id)
} }
} }
@ -139,7 +126,7 @@ export default class Router {
} }
fetchComponent (url, fn) { fetchComponent (url, fn) {
const pathname = parse(url, true) const { pathname } = parse(url)
const route = toRoute(pathname) const route = toRoute(pathname)
let cancelled = false let cancelled = false
@ -174,11 +161,12 @@ export default class Router {
if (err) { if (err) {
if (!cancelled) fn(err) if (!cancelled) fn(err)
} else { } else {
const d = { data, id: createUid() }
// we update the cache even if cancelled // we update the cache even if cancelled
if (!this.components[route]) { if (!this.components[route]) {
this.components[route] = data this.components[route] = d
} }
if (!cancelled) fn(null, data) if (!cancelled) fn(null, d)
} }
}) })
@ -224,6 +212,14 @@ export function loadComponent (url, fn) {
}) })
} }
function getURL () {
return location.pathname + (location.search || '') + (location.hash || '')
}
function createUid () {
return Math.floor(Math.random() * 1e16)
}
function loadJSON (url, fn) { function loadJSON (url, fn) {
const xhr = new XMLHttpRequest() const xhr = new XMLHttpRequest()
xhr.onload = () => { xhr.onload = () => {