不用vue实现spa
使用原生 JavaScript 实现 SPA
通过监听 URL 变化动态加载内容,结合 history.pushState 或 hashchange 事件实现路由切换。
// 路由配置
const routes = {
'/': 'Home Page Content',
'/about': 'About Page Content',
'/contact': 'Contact Page Content'
};
// 渲染函数
function render(path) {
document.getElementById('app').innerHTML = routes[path] || '404 Not Found';
}
// 监听路由变化
window.addEventListener('popstate', () => {
render(window.location.pathname);
});
// 初始化路由
document.addEventListener('DOMContentLoaded', () => {
document.body.addEventListener('click', (e) => {
if (e.target.matches('[data-link]')) {
e.preventDefault();
history.pushState(null, null, e.target.href);
render(window.location.pathname);
}
});
render(window.location.pathname);
});
使用 Hash 路由方案
通过 window.location.hash 的变化实现路由切换,兼容性更好。
// 路由配置
const routes = {
'#/': 'Home Page Content',
'#/about': 'About Page Content',
'#/contact': 'Contact Page Content'
};
// 渲染函数
function render(hash) {
document.getElementById('app').innerHTML = routes[hash] || '404 Not Found';
}
// 监听 hash 变化
window.addEventListener('hashchange', () => {
render(window.location.hash);
});
// 初始化
document.addEventListener('DOMContentLoaded', () => {
if (!window.location.hash) {
window.location.hash = '#/';
}
render(window.location.hash);
});
使用 Page.js 轻量级路由库
引入 Page.js 库简化路由实现,提供更丰富的路由功能。
<script src="https://unpkg.com/page/page.js"></script>
<script>
page('/', () => {
document.getElementById('app').innerHTML = 'Home Page';
});
page('/about', () => {
document.getElementById('app').innerHTML = 'About Page';
});
page('*', () => {
document.getElementById('app').innerHTML = '404 Not Found';
});
page();
</script>
结合 AJAX 加载动态内容
通过 XMLHttpRequest 或 Fetch API 从服务器加载内容片段。
function loadContent(url) {
fetch(url)
.then(response => response.text())
.then(html => {
document.getElementById('app').innerHTML = html;
});
}
window.addEventListener('popstate', () => {
loadContent(window.location.pathname + '.html');
});
实现组件化架构
通过自定义元素或模板引擎实现组件化开发。
// 定义组件
class MyComponent extends HTMLElement {
connectedCallback() {
this.innerHTML = `<div>Component Content</div>`;
}
}
// 注册组件
customElements.define('my-component', MyComponent);
// 使用组件
document.getElementById('app').innerHTML = '<my-component></my-component>';
状态管理方案
通过全局对象或事件总线实现简单的状态管理。
const store = {
state: { count: 0 },
setState(newState) {
this.state = { ...this.state, ...newState };
this.notify();
},
subscribers: [],
subscribe(callback) {
this.subscribers.push(callback);
},
notify() {
this.subscribers.forEach(callback => callback(this.state));
}
};
// 组件订阅状态变化
store.subscribe(state => {
document.getElementById('counter').textContent = state.count;
});
性能优化技巧
使用惰性加载和缓存策略提升应用性能。
const componentCache = {};
async function loadComponent(name) {
if (!componentCache[name]) {
const response = await fetch(`/components/${name}.html`);
componentCache[name] = await response.text();
}
return componentCache[name];
}
实现路由守卫
通过中间件函数实现路由权限控制。
function authGuard(ctx, next) {
if (!isLoggedIn() && ctx.path !== '/login') {
page.redirect('/login');
} else {
next();
}
}
page('/dashboard', authGuard, () => {
// 受保护的路由
});
服务端渲染支持
通过 Express 等服务器框架实现同构渲染。
const express = require('express');
const app = express();
app.get('*', (req, res) => {
const html = `
<html>
<body>
<div id="app">${getContentForPath(req.path)}</div>
<script src="/client.js"></script>
</body>
</html>
`;
res.send(html);
});






