执行过程:当用户点击 router-link 标签时,会去寻找它的 to 属性, 它的 to 属性和 js 中配置的路径{ path: '/home', component: Home} path 一一对应,从而找到了匹配的组件, 最后把组件渲染到 标签所在的地方。
vue-router 是 vue.js 框架的路由插件,它是通过 mode 这一参数控制路由的实现模式的。
const router = new VueRouter({
// HTML5 history 模式
mode: 'history',
base: process.env.NODE_ENV === 'production' ? process.env.PROXY_PATH : '',
routes,
})
源码分析
var VueRouter = function VueRouter (options) {
if ( options === void 0 ) options = {};
this.app = null;
this.apps = [];
this.options = options;
this.beforeHooks = [];
this.resolveHooks = [];
this.afterHooks = [];
// 创建 matcher 匹配函数
this.matcher = createMatcher(options.routes || [], this);
// 根据 mode 实例化具体的 History,默认为'hash'模式
var mode = options.mode || 'hash';
// 通过 supportsPushState 判断浏览器是否支持'history'模式
// 如果设置的是'history'但是如果浏览器不支持的话,'history'模式会退回到'hash'模式
// fallback 是当浏览器不支持 history.pushState 控制路由是否应该回退到 hash 模式。默认值为 true。
this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false;
if (this.fallback) {
mode = 'hash';
}
if (!inBrowser) {
// 不在浏览器环境下运行需强制为'abstract'模式
mode = 'abstract';
}
this.mode = mode;
// 根据不同模式选择实例化对应的 History 类
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, options.base);
break
default:
{
assert(false, ("invalid mode: " + mode));
}
}
};
history 模式
VueRouter.prototype.init = function init (app /* Vue component instance */) {
...
var history = this.history;
// 根据history的类别执行相应的初始化操作和监听
if (history instanceof HTML5History) {
history.transitionTo(history.getCurrentLocation());
} else if (history instanceof HashHistory) {
var setupHashListener = function () {
history.setupListeners();
};
history.transitionTo(
history.getCurrentLocation(),
setupHashListener,
setupHashListener
);
}
history.listen(function (route) {
this$1.apps.forEach(function (app) {
app._route = route;
});
});
};
- 在初始化对应的history之前,会对mode做一些校验:若浏览器不支持HTML5History方式(通过supportsPushState变量判断),则mode设为hash;若不是在浏览器环境下运行,则mode设为abstract;
- VueRouter类中的onReady(),push()等方法只是一个代理,实际是调用的具体history对象的对应方法,在init()方法中初始化时,也是根据history对象具体的类别执行不同操作
pushState和replaceState两种方法的共同特点:当调用他们修改浏览器历史栈后,虽然当前url改变了,但浏览器不会立即发送请求该url,这就为单页应用前端路由,更新视图但不重新请求页面提供了基础。
而history模式则将url修改的就和正常请求后端的url一样(history不带#)
http://oursite.com/user/id
如果这种向后端发送请求的话,后端没有配置对应/user/id的get路由处理,会返回404错误。
你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面
给个警告,因为这么做以后,你的服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,你应该在 Vue 应用里面覆盖所有的路由情况,然后在给出一个 404 页面。
网友评论