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:
parent
0cc1ed0516
commit
2d8959d99c
|
@ -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)
|
||||||
|
|
|
@ -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 = () => {
|
||||||
|
|
Loading…
Reference in a new issue