路由管理
在路由切换中添加逻辑处理
整体代码
// Some code
const { location, history } = window
const createHistoryStateStore = (state = location.href)=>{
const getState = ()=>{
if (listenerSet.size === 0) throw new Error('should subscribe before getState')
return state
}
const setState = (nextState, shouldPushState) =>{ //新路由和状态
if (typeof (nextState) !== 'string') throw new Error(`non-string href: ${nextState}`)
if (nextState === state) return state //新路由和当前路由一样 不做处理
console.log('do set nextState:',nextState, 'shouldPushState:',shouldPushState,'state:',state)
const prevState = state //把当前存储的路由状态当做旧路由
state = nextState//传入的新路由为当前路由状态
shouldPushState !== 'skip' && history.pushState(null, '', state) //判断操作性质,决定是否需要手动更新histroy栈
listenerSet.forEach((listener) => listener(state, prevState)) //执行路由变更处理逻辑
return state
}
const listenerPopState = () => { setState(location.href, 'skip') } //原生浏览器操作时才触发
const listenerHashChange = () => { setState(location.href) } // js调用history.pushState()或history.replaceState() 或者直接改地址框地址 记录
const listenerSet = new Set() //存储路由变更时执行逻辑的函数集合
const subscribe = (listener) => { //绑定事件监听
listenerSet.add(listener) //存储处理函数
if (listenerSet.size !== 1) return //如果以前已经添加过监听处理,无需重复绑定
window.addEventListener('popstate', listenerPopState) //原生流量器操作
window.addEventListener('hashchange', listenerHashChange) // js操作
}
const unsubscribe = (listener) => {
listenerSet.delete(listener)// 删除存储处理函数
if (listenerSet.size !== 0) return //如果删除某个处理函数后仍存在其他处理逻辑则不需解绑
window.removeEventListener('popstate', listenerPopState)
window.removeEventListener('hashchange', listenerHashChange)
}
return { getState, setState, subscribe, unsubscribe }
}
export { createHistoryStateStore }
// e.g:
var his = createHistoryStateStore()
his.subscribe((state, prevState)=>{ console.log('state:',state, 'prevState:',prevState)})
popstate
History.pushState()
最后更新于