Open ziwei3749 opened 6 years ago
经过几天的研究,对以下问题做了一些探究:
本质上前端路由: 前端监听和解析url的变化,并匹配url对应的页面
我觉得最起码需要有2个功能
打开动作
如果是模拟的话,div的显示隐藏就可以了。 实际上vue-router用起来,有router-view组件,这里渲染的内容,可以通过routes配置 routes是一个数组,里面写着path和components的映射关系
历史记录操作单
那hash变化自动就会有一个历史记录 html5新增加的history.pushState也增加历史记录。
所以这2个api都具备实现前端路由的能力
hash 和 history的区别
history模式的话需要后端做一个配置,如果这个url匹配到任何路由,那不要返回404,而是返回Index.html 但是这样,你如果url不匹配,也永远没有404了,vue为例子的话,routes里需要配置path:* 对应一个404页面
html
<ul> <a href="#/"></a> <a href="#/about"></a> <a href="#/topics"></a> </ul> <div id="router-view"></div>
调用方式
var router = new Router() var routerView = document.querySelector('#router-view') router.init() // 这里是注册路由,指定url对应做什么事情。有点routes里指定path和component的对应关系 router.route('/',() => { routerView.innerHTML = 'home' }) router.route('/about',() => { routerView.innerHTML = 'about' }) router.route('/topics',() => { routerView.innerHTML = 'topics' })
实现hash路由
class Router{ construtor() { this.routes = {} // 存放path和 fn的映射关系 } route(path,fn){ this.routes[path] = fn } updateView(){ // 获取hash就知道执行哪个fn,显示哪个页面了 var url = window.location.hash.substr(1) this.routes[url]() } init(){ window.addEventListenr('hashchange',() => { this.updateView() }) window.addEventListenr('load',() => { this.updateView() }) } }
梳理一下过程
那为什么不用history实现呢,因为History要多考虑一些地方,pushState并不能触发popstate的变化
既然通过popstate监听不太靠谱,那如何拦截各种情况下路由的变化的
其实路由的变化,就3个情况
在点击a标签或者pushState时去updateView一下,在源码中其实有一个render,需要用这个方法去更新页面
基本就是这一个思路,(注意history跳转时跨域问题)
我是看的v2.03版本,后来有看了一眼vue-router@3.01的版本,目录结构和写法也不一样
目录结构
技巧1.mian.js入口文件,我们一般引入vue-router后,需要Vue.use(VueRouter)
这个是Vue提供的插件机制,这个机制就是Vue会调用插件的install方法(如果没有的话就把插件自身作为函数调用)
技巧2.插件打包时肯定不希望把整个Vue打包进去,但是又希望使用Vue对象的方法,所以就可以在install时赋值
去看index.js的话,vue-rotuer这个插件是有install方法,单独写install.js文件里
_Vue = Vue
技巧3: Object.defineProperty给Vue.prototype添加$router和$route,这样可以让所有Vue都有这2个属性 技巧4: 有一些嘈杂哦判断你的 mode和fallback
技巧3: Object.defineProperty给Vue.prototype添加$router和$route,这样可以让所有Vue都有这2个属性
技巧4: 有一些嘈杂哦判断你的 mode和fallback
let mode = options.mode || 'hash'
this.fallback = mode === 'history' && !supportsHistory if (this.fallback) { mode = 'hash' }
switch (mode) { case 'history': this.history = new HTML5History(this, options.base) break case 'hash': this.history = new HashHistory(this, options.base, this.fallback) break case 'abstract': this.history = new AbstractHistory(this) break default: assert(false, invalid mode: ${mode}) }
invalid mode: ${mode}
写的不错,学习一下
vue-router学习成果
经过几天的研究,对以下问题做了一些探究:
1.前端路由是什么?
本质上前端路由: 前端监听和解析url的变化,并匹配url对应的页面
2.思考实现一个前端路由需要具备哪些功能
我觉得最起码需要有2个功能
所以这2个api都具备实现前端路由的能力
3.前端路由2种实现方式的区别和注意事项
hash 和 history的区别
4.【代码实现】基础路由实现代码,以hash
html
调用方式
实现hash路由
梳理一下过程
那为什么不用history实现呢,因为History要多考虑一些地方,pushState并不能触发popstate的变化
既然通过popstate监听不太靠谱,那如何拦截各种情况下路由的变化的
其实路由的变化,就3个情况
在点击a标签或者pushState时去updateView一下,在源码中其实有一个render,需要用这个方法去更新页面
基本就是这一个思路,(注意history跳转时跨域问题)
5.【vue-router源码学习】vue-router源码中学习到的技巧
我是看的v2.03版本,后来有看了一眼vue-router@3.01的版本,目录结构和写法也不一样
目录结构
这个是Vue提供的插件机制,这个机制就是Vue会调用插件的install方法(如果没有的话就把插件自身作为函数调用)
去看index.js的话,vue-rotuer这个插件是有install方法,单独写install.js文件里
this.fallback = mode === 'history' && !supportsHistory if (this.fallback) { mode = 'hash' }
switch (mode) { case 'history': this.history = new HTML5History(this, options.base) break case 'hash': this.history = new HashHistory(this, options.base, this.fallback) break case 'abstract': this.history = new AbstractHistory(this) break default: assert(false,
invalid mode: ${mode}
) }