js实现vue-router
实现基本路由功能
在JavaScript中实现类似vue-router的功能,可以通过监听URL变化并动态渲染对应组件完成。以下是核心实现方式:
class VueRouter {
constructor(options) {
this.routes = options.routes || [];
this.current = window.location.pathname;
window.addEventListener('popstate', this.handlePopState.bind(this));
}
handlePopState() {
this.current = window.location.pathname;
this.render();
}
push(path) {
window.history.pushState({}, '', path);
this.current = path;
this.render();
}
render() {
const route = this.routes.find(r => r.path === this.current);
if (route) {
document.getElementById('app').innerHTML = route.component;
}
}
}
路由映射配置
需要定义路由与组件的映射关系,这是路由系统的核心配置:
const routes = [
{ path: '/', component: '<div>Home Page</div>' },
{ path: '/about', component: '<div>About Page</div>' },
{ path: '/contact', component: '<div>Contact Page</div>' }
];
const router = new VueRouter({
routes
});
HTML5 History API集成
现代前端路由通常使用HTML5 History API来实现无刷新跳转:
// 导航方法
function navigate(e) {
e.preventDefault();
const path = e.target.getAttribute('href');
router.push(path);
}
// 为链接添加事件监听
document.querySelectorAll('a[href]').forEach(link => {
link.addEventListener('click', navigate);
});
动态路由匹配
实现类似vue-router的动态路由参数功能:
class VueRouter {
// ...其他代码
matchRoute(path) {
return this.routes.find(route => {
const routeSegments = route.path.split('/');
const pathSegments = path.split('/');
if (routeSegments.length !== pathSegments.length) {
return false;
}
return routeSegments.every((seg, i) => {
return seg.startsWith(':') || seg === pathSegments[i];
});
});
}
render() {
const route = this.matchRoute(this.current);
if (route) {
const params = this.extractParams(route.path, this.current);
document.getElementById('app').innerHTML = route.component(params);
}
}
extractParams(routePath, currentPath) {
const params = {};
const routeParts = routePath.split('/');
const pathParts = currentPath.split('/');
routeParts.forEach((part, i) => {
if (part.startsWith(':')) {
params[part.slice(1)] = pathParts[i];
}
});
return params;
}
}
路由守卫实现
添加类似vue-router的导航守卫功能:
class VueRouter {
constructor(options) {
this.beforeEachHooks = [];
// ...其他初始化代码
}
beforeEach(fn) {
this.beforeEachHooks.push(fn);
}
push(path) {
const from = this.current;
const to = path;
this.runHooks(from, to, () => {
window.history.pushState({}, '', path);
this.current = path;
this.render();
});
}
runHooks(from, to, next) {
let index = 0;
const nextHook = () => {
if (index >= this.beforeEachHooks.length) {
return next();
}
const hook = this.beforeEachHooks[index++];
hook(from, to, nextHook);
};
nextHook();
}
}
嵌套路由支持
实现嵌套路由功能需要递归匹配路由:
class VueRouter {
// ...其他代码
matchRoute(path, routes = this.routes) {
for (const route of routes) {
if (route.path === path) {
return route;
}
if (route.children) {
const childPath = path.replace(route.path, '');
const matched = this.matchRoute(childPath, route.children);
if (matched) {
return {
...route,
child: matched
};
}
}
}
return null;
}
render() {
const route = this.matchRoute(this.current);
if (route) {
let content = route.component;
if (route.child) {
const outlet = document.createElement('div');
outlet.id = 'router-outlet';
content += outlet.outerHTML;
}
document.getElementById('app').innerHTML = content;
if (route.child) {
document.getElementById('router-outlet').innerHTML = route.child.component;
}
}
}
}
这些实现方式展示了如何用纯JavaScript构建一个基本的路由系统,包含了vue-router的核心功能。实际应用中可能需要考虑更多边界情况和性能优化。







