基于原生JavaScript实现SPA单页应用
作者:TANKING 发布时间:2024-04-30 09:59:43
什么叫做SPA单页应用
单页Web应用 (single page web application,SPA)
,就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。
单页应用的说法是在JavaScript和AJAX技术比较成熟以后才出现的,指的是通过浏览器访问一个网站时,只需要加载一个入口页面,此后显示的内容和数据都不会再刷新浏览器页面。有了单页应用之后,传统的网站就被称为多页应用了。
单页应用的优点
• 1. 前端负责界面显示,后端负责数据存储和计算,各司其职。
• 2. 用户体验好、快,内容的改变不需要重新加载,提升了用户体验;而且同一套后端程序代码,不用修改就可以用于Web界面、手机、平板等多种客户端;
• 3. 减轻服务器压力,服务器只用出数据就可以,不用管展示逻辑和页面合成,吞吐能力会提高几倍。
单页应用的实现原理
其实很容易理解,就是在一个HTML页面当中只有一个div节点,通过后端获取到数据,然后js操作DOM来创建、删除、更新节点以达到修改页面内容,所以页面是没有被刷新的,只是DOM节点发生了改变,所以HTML发生了改变。
目前有非常多开发单页应用的优秀框架,常见的有Vue、React、Svelte、Angular,但是这些框架都需要依赖非常笨重的Node模块、打包工具、开发环境、以及各种组件。有没有一种传统的开发方式去实现单页应用呢?本文正是解决方案!
上代码
index.html
<html>
<head>
<title>原生JS实现的单页应用</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0,viewport-fit=cover">
<script src="./static/js/index.js"></script>
<link rel="stylesheet" href="./static/css/index.css" rel="external nofollow" >
</head>
<body>
<div id="app"></div>
</body>
</html>
static/css/index.css
*{
padding: 0;
margin: 0;
}
body{
background: #eee;
}
#app .topBar{
width: 100%;
height: 50px;
background: #fff;
margin-bottom: 20px;
line-height: 50px;
}
#app .topBar a{
display: block;
float: left;
padding:0 10px;
text-decoration: none;
color: #333;
}
#app .contentView a{
display: block;
text-decoration: none;
line-height: 40px;
background: #fff;
width: 90%;
margin: 0 auto 10px;
padding: 5px 10px;
color: #333;
font-size: 15px;
border-radius: 10px;
}
static/js/index.js
// 路由配置
const routes = {
'/': home,
'/weibo': weibo,
'/douyin': douyin
};
// 路由函数
function router() {
// 获取当前 URL 中的路径部分
const path = window.location.hash.slice(1);
// 根据路径找到对应的处理函数
const handler = routes[path] || notFound;
// 渲染页面
handler();
}
// 注入topBar选项
function addTopBarItem(){
$topBarItem_HTML = `
<a href="#/" rel="external nofollow" >百度热搜</a>
<a href="#/weibo" rel="external nofollow" >微博热搜</a>
<a href="#/douyin" rel="external nofollow" >抖音热搜</a>
`;
document.querySelector('#app .topBar').innerHTML = $topBarItem_HTML;
}
// 首页
function home() {
// 热搜列表
var hotlist = [
{
'title':'中俄联合声明:用和谈解决乌克兰危机',
'url':'https://baijiahao.baidu.com/s?id=1760993625204951286'
},
{
'title':'网友晒壮观的俄罗斯护送队',
'url':'https://quanmin.baidu.com/v/4235918912360611140'
},
{
'title':'春季旅游消费强势复苏',
'url':'https://quanmin.baidu.com/v/4235918912360611140'
},
{
'title':'你的城市在下雨,他的城市在下泥',
'url':'https://haokan.baidu.com/v?pd=wisenatural&vid=3490913664840969394'
},
{
'title':'英国宣布向乌提供贫铀弹',
'url':'https://news.ycwb.com/2023-03/22/content_51834441.htm'
}
];
$home_HTML = `
<div class="topBar"></div>
<div class="contentView"></div>
`;
document.querySelector('#app').innerHTML = $home_HTML;
addTopBarItem();
for (var i = 0; i < hotlist.length; i++) {
var node_li = document.createElement("a");
node_li.setAttribute('href',hotlist[i].url);
var hotlist_node = document.createTextNode(hotlist[i].title);
node_li.appendChild(hotlist_node);
document.querySelector('#app .contentView').appendChild(node_li);
}
}
// 微博热搜
function weibo() {
// 热搜列表
var hotlist = [
{
'title':'中俄元首签署联合声明',
'url':'https://s.weibo.com/weibo?q=%23%E4%B8%AD%E4%BF%84%E5%85%83%E9%A6%96%E7%AD%BE%E7%BD%B2%E8%81%94%E5%90%88%E5%A3%B0%E6%98%8E%23&t=31&band_rank=1&Refer=top'
},
{
'title':'迪丽热巴微博之夜正式官宣',
'url':'https://s.weibo.com/weibo?q=%23%E8%BF%AA%E4%B8%BD%E7%83%AD%E5%B7%B4%E5%BE%AE%E5%8D%9A%E4%B9%8B%E5%A4%9C%E6%AD%A3%E5%BC%8F%E5%AE%98%E5%AE%A3%23&t=31&band_rank=2&Refer=top'
},
{
'title':'中俄关系对世界格局人类前途命运至关重要',
'url':'https://s.weibo.com/weibo?q=%23%E4%B8%AD%E4%BF%84%E5%85%B3%E7%B3%BB%E5%AF%B9%E4%B8%96%E7%95%8C%E6%A0%BC%E5%B1%80%E4%BA%BA%E7%B1%BB%E5%89%8D%E9%80%94%E5%91%BD%E8%BF%90%E8%87%B3%E5%85%B3%E9%87%8D%E8%A6%81%23&t=31&band_rank=3&Refer=top'
},
{
'title':'朴妍珍和宋承宪演过人间中毒',
'url':'https://s.weibo.com/weibo?q=%23%E6%9C%B4%E5%A6%8D%E7%8F%8D%E5%92%8C%E5%AE%8B%E6%89%BF%E5%AE%AA%E6%BC%94%E8%BF%87%E4%BA%BA%E9%97%B4%E4%B8%AD%E6%AF%92%23&t=31&band_rank=4&Refer=top'
},
{
'title':'云之羽官宣演员阵容',
'url':'https://s.weibo.com/weibo?q=%23%E4%BA%91%E4%B9%8B%E7%BE%BD%E5%AE%98%E5%AE%A3%E6%BC%94%E5%91%98%E9%98%B5%E5%AE%B9%23&t=31&band_rank=5&Refer=top'
}
];
$weibo_HTML = `
<div class="topBar"></div>
<div class="contentView"></div>
`;
document.querySelector('#app').innerHTML = $weibo_HTML;
addTopBarItem();
for (var i = 0; i < hotlist.length; i++) {
var node_li = document.createElement("a");
node_li.setAttribute('href',hotlist[i].url);
var hotlist_node = document.createTextNode(hotlist[i].title);
node_li.appendChild(hotlist_node);
document.querySelector('#app .contentView').appendChild(node_li);
}
}
// 抖音热搜
function douyin() {
// 热搜列表
var hotlist = [
{
'title':'高双星偷走的是高加林的人生',
'url':'https://www.douyin.com/hot/1104967'
},
{
'title':'中国空间站的窗外有多美',
'url':'https://www.douyin.com/hot/1104853'
},
{
'title':'人民文娱评黑暗荣耀毒虫仿妆',
'url':'https://www.douyin.com/hot/1103955'
},
];
$douyin_HTML = `
<div class="topBar"></div>
<div class="contentView"></div>
`;
document.querySelector('#app').innerHTML = $douyin_HTML;
addTopBarItem();
for (var i = 0; i < hotlist.length; i++) {
var node_li = document.createElement("a");
node_li.setAttribute('href',hotlist[i].url);
var hotlist_node = document.createTextNode(hotlist[i].title);
node_li.appendChild(hotlist_node);
document.querySelector('#app .contentView').appendChild(node_li);
}
}
// 404 页面处理函数
function notFound() {
const main = document.querySelector('#app');
main.innerHTML = '<h1>404 页面不存在</h1>';
}
// 监听 URL 变化事件
window.addEventListener('hashchange', router);
// 页面加载完成后初始化路由
window.addEventListener('load', router);
代码说明
1.本次示例也是采用了目前的Web构建工具打包出来的目录模式(即Webpack、Vite等打包工具)
2.index.js里面的数据写在了一个对象当中,实际应用需要使用AJAX/Fetch等方式获取数据返回JSON对象进行显示。
动图演示
在这个动图示例中,可以看到,切换tab的时候,下面的列表发生了变化,URL也发生了变化,但是并没有刷新页面。
DEMO
http://demo.likeyunba.com/ys-js-spa/#/
来源:https://segmentfault.com/a/1190000043570065


猜你喜欢
- 利用python进行求解,求解的要求是不能使用python内部封装好的函数例如:maxway1:def findmax(data,n): i
- Python数据库接口支持非常多的数据库,你可以选择适合你项目的数据库:GadFlymSQL MySQL PostgreSQL Micros
- 本文实例为大家分享了python实现抽奖小程序的具体代码,供大家参考,具体内容如下设计一个抽奖服务 背景:有x个奖品,要求在y天内
- 发版前接到一个临时新需求 ,需要在web端地址选择时用地图,并获取经纬度。 临阵发版之际加需求,真的是很头疼,于是赶紧找度娘,找api。 我
- 1.partial首先是partial函数,它可以重新绑定函数的可选参数,生成一个callable的partial对象:>>&g
- 看一个例子d={'test':1}d_test=dd_test['test']=2print d如果你在命令
- <!doctype html> <html> <head> <meta charset="
- BatchNorm2d中的track_running_stats参数如果BatchNorm2d的参数val,track_running_st
- 总结了5个关于css布局的常见问题,并附有解决方法,供参考。float的3像素问题及解决办法当使用float浮动容器后,在IE6下会产生3p
- 环境ubuntu 12.04 LTSpython 2.7.3opencv 2.3.1-7安装依赖sudo apt-get install l
- 我的目标是写一个非常详细的关于diff的干货,所以本文有点长。也会用到大量的图片以及代码举例,目的让看这篇文章的朋友一定弄明白diff的边边
- 1、hook背景Hook被成为钩子机制,这不是pytorch的首创,在Windows的编程中已经被普遍采用,包括进程内钩子和全局钩子。按照自
- 项目中有这样的需求,通过IP地址判断客户端是网通的还是电信的。从同事那拿了个纯文本的IP纯真数据库,用Python写了一个小程序,感觉挺好的
- 本文实例讲述了mysql基于正则实现模糊替换字符串的方法。分享给大家供大家参考,具体如下:例如: abcd(efg)hijk 替换之后是ab
- 一、and:在Python 中,and 和 or 执行布尔逻辑演算,如你所期待的一样,但是它们并不返回布尔值;而是,返回它们实际进行比较的值
- 最近在做zabbix的数据库MySQL5.6升级5.7时,出现主从延迟问题,这个问题困扰了很久没有解决,昨天终于解决了,整理了一下整个排查过
- 俺觉得自 己试着写写sql,调试调试还是有帮助的,读人家sql例子好像读懂了,自己写就未 必思路正确,调试得通,写得简洁。 这篇文字在网上被
- 在进行python的开发过程中一直倡导使用虚拟环境来进行项目隔离,这样不会因为python的包不同而导致各种问题,但是以往为了图省事简单,安
- 公司运营着的网站,流量很大,网站是交互式的,经常在过了三四个月的时候索引生成的碎片就很多,由于很大一部分页面没有生成静态,这就导致网站在打开
- 排序算法排序也是在程序中经常用到的算法。无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但如果是