下面我将为大家详细讲解如何用原生JS做单页应用的完整攻略。
什么是单页应用?
单页应用(SPA)是指使用Ajax或Websocket等技术,使得网页只需加载一次,就能实现多个页面的效果。
用原生JS做单页应用的步骤
- 定义路由
要实现单页应用,首先需要定义路由,以此来控制页面的跳转和展示。可以使用window.history.pushState()方法或者location.hash来实现路由。
示例代码:
// 定义路由表
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/contact', component: Contact }
]
// 监听路由变化
window.addEventListener('popstate', routeChanged);
// 路由跳转
function navigateTo(path) {
history.pushState(null, null, path);
routeChanged();
}
// 路由变化处理函数
function routeChanged() {
const path = location.pathname;
const route = routes.find(route => route.path === path) || {component: NotFound};
document.querySelector('#content').innerHTML = new route.component().render();
}
- 定义组件
为了实现复用和组合,需要将页面拆分成多个组件。每个组件可以由一个HTML模板和一个JS逻辑文件组成。
示例代码:
// Home组件
class Home {
constructor() {
this.template = `
<h1>Welcome to Home Page</h1>
<p>Home Page Content Here</p>
`;
}
render() {
return this.template;
}
}
// About组件
class About {
constructor() {
this.template = `
<h1>About Us</h1>
<p>About Us Content Here</p>
`;
}
render() {
return this.template;
}
}
// Contact组件
class Contact {
constructor() {
this.template = `
<h1>Contact Us</h1>
<p>Contact Us Content Here</p>
`;
}
render() {
return this.template;
}
}
// NotFound组件
class NotFound {
constructor() {
this.template = `
<h1>Not Found</h1>
<p>404 Page Not Found</p>
`;
}
render() {
return this.template;
}
}
- 编写事件处理函数和业务逻辑
单页应用中,事件处理函数和业务逻辑通常写在组件中。可以使用事件委托和事件监听等方法来实现交互效果。
示例代码:
// 定义事件处理函数
function handleClick(event) {
event.preventDefault();
const path = event.target.href;
navigateTo(path);
}
// 组件中使用事件处理函数
class Navigation {
constructor() {
this.template = `
<nav>
<ul>
<li><a href="/" class="link">Home</a></li>
<li><a href="/about" class="link">About</a></li>
<li><a href="/contact" class="link">Contact</a></li>
</ul>
</nav>
`;
}
render() {
const element = document.createElement('div');
element.innerHTML = this.template.trim();
element.addEventListener('click', handleClick); // 事件委托
return element;
}
}
// 业务逻辑处理函数
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const data = Object.fromEntries(formData.entries());
// 处理提交数据...
}
// 组件中使用业务逻辑处理函数
class Form {
constructor() {
this.template = `
<form>
<label>
Name: <input type="text" name="name" required>
</label>
<label>
Email: <input type="email" name="email" required>
</label>
<button type="submit">Submit</button>
</form>
`;
}
render() {
const element = document.createElement('div');
element.innerHTML = this.template.trim();
element.querySelector('form').addEventListener('submit', handleSubmit);
return element;
}
}
示例说明
示例一:基础单页应用
下面是一个基础的单页应用示例,实现了路由跳转和组件渲染。
<html>
<head>
<title>Example SPA</title>
</head>
<body>
<nav>
<ul>
<li><a href="/" class="link">Home</a></li>
<li><a href="/about" class="link">About</a></li>
<li><a href="/contact" class="link">Contact</a></li>
</ul>
</nav>
<div id="content"></div>
<script>
// 定义路由表
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/contact', component: Contact }
];
// 监听路由变化
window.addEventListener('popstate', routeChanged);
// 路由跳转
function navigateTo(path) {
history.pushState(null, null, path);
routeChanged();
}
// 路由变化处理函数
function routeChanged() {
const path = location.pathname;
const route = routes.find(route => route.path === path) || {component: NotFound};
document.querySelector('#content').innerHTML = new route.component().render();
}
// Home组件
class Home {
constructor() {
this.template = `
<h1>Welcome to Home Page</h1>
<p>Home Page Content Here</p>
`;
}
render() {
return this.template;
}
}
// About组件
class About {
constructor() {
this.template = `
<h1>About Us</h1>
<p>About Us Content Here</p>
`;
}
render() {
return this.template;
}
}
// Contact组件
class Contact {
constructor() {
this.template = `
<h1>Contact Us</h1>
<p>Contact Us Content Here</p>
`;
}
render() {
return this.template;
}
}
// NotFound组件
class NotFound {
constructor() {
this.template = `
<h1>Not Found</h1>
<p>404 Page Not Found</p>
`;
}
render() {
return this.template;
}
}
// 定义事件处理函数
function handleClick(event) {
event.preventDefault();
const path = event.target.href;
navigateTo(path);
}
// Navigation组件
class Navigation {
constructor() {
this.template = `
<nav>
<ul>
<li><a href="/" class="link">Home</a></li>
<li><a href="/about" class="link">About</a></li>
<li><a href="/contact" class="link">Contact</a></li>
</ul>
</nav>
`;
}
render() {
const element = document.createElement('div');
element.innerHTML = this.template.trim();
element.addEventListener('click', handleClick); // 事件委托
return element;
}
}
document.querySelector('#content').appendChild(new Navigation().render());
routeChanged();
</script>
</body>
</html>
示例二:表单提交处理
下面是一个实现表单提交处理的单页应用示例,演示了如何在组件中处理交互事件和业务逻辑。
<html>
<head>
<title>Example SPA</title>
</head>
<body>
<nav>
<ul>
<li><a href="/" class="link">Home</a></li>
<li><a href="/about" class="link">About</a></li>
<li><a href="/contact" class="link">Contact</a></li>
</ul>
</nav>
<div id="content"></div>
<script>
// 定义路由表
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/contact', component: Contact }
];
// 监听路由变化
window.addEventListener('popstate', routeChanged);
// 路由跳转
function navigateTo(path) {
history.pushState(null, null, path);
routeChanged();
}
// 路由变化处理函数
function routeChanged() {
const path = location.pathname;
const route = routes.find(route => route.path === path) || {component: NotFound};
document.querySelector('#content').innerHTML = new route.component().render();
}
// Home组件
class Home {
constructor() {
this.template = `
<h1>Welcome to Home Page</h1>
<p>Home Page Content Here</p>
`;
}
render() {
return this.template;
}
}
// About组件
class About {
constructor() {
this.template = `
<h1>About Us</h1>
<p>About Us Content Here</p>
`;
}
render() {
return this.template;
}
}
// Contact组件
class Contact {
constructor() {
this.template = `
<h1>Contact Us</h1>
<p>Contact Us Content Here</p>
<h2>Feedback Form</h2>
<div id="form"></div>
`;
}
render() {
const element = document.createElement('div');
element.innerHTML = this.template.trim();
element.querySelector('#form').appendChild(new ContactForm().render());
return element;
}
}
// NotFound组件
class NotFound {
constructor() {
this.template = `
<h1>Not Found</h1>
<p>404 Page Not Found</p>
`;
}
render() {
return this.template;
}
}
// ContactForm组件
class ContactForm {
constructor() {
this.template = `
<form>
<label>
Name: <input type="text" name="name" required>
</label>
<label>
Email: <input type="email" name="email" required>
</label>
<label>
Message: <textarea name="message" rows="5" required></textarea>
</label>
<button type="submit">Submit</button>
</form>
`;
}
render() {
const element = document.createElement('div');
element.innerHTML = this.template.trim();
element.querySelector('form').addEventListener('submit', handleSubmit);
return element;
}
}
// 提交处理函数
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
const data = Object.fromEntries(formData.entries());
console.log(data);
// 处理提交数据...
event.target.reset();
alert('Submit success.');
}
// 定义事件处理函数
function handleClick(event) {
event.preventDefault();
const path = event.target.href;
navigateTo(path);
}
// Navigation组件
class Navigation {
constructor() {
this.template = `
<nav>
<ul>
<li><a href="/" class="link">Home</a></li>
<li><a href="/about" class="link">About</a></li>
<li><a href="/contact" class="link">Contact</a></li>
</ul>
</nav>
`;
}
render() {
const element = document.createElement('div');
element.innerHTML = this.template.trim();
element.addEventListener('click', handleClick); // 事件委托
return element;
}
}
document.querySelector('#content').appendChild(new Navigation().render());
routeChanged();
</script>
</body>
</html>
以上就是用原生JS做单页应用的详细攻略,希望对大家有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:用原生js做单页应用 - Python技术站