原生JavaScript实现的SPA单页应用(hash路由)

什么叫做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">
</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="#/">百度热搜</a>
    <a href="#/weibo">微博热搜</a>
    <a href="#/douyin">抖音热搜</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/1104982'
        },
        {
            'title':'高双星偷走的是高加林的人生',
            'url':'https://www.douyin.com/hot/1104967'
        },
        {
            'title':'中国空间站的窗外有多美',
            'url':'https://www.douyin.com/hot/1104853'
        },
        {
            'title':'人民文娱评黑暗荣耀毒虫仿妆',
            'url':'https://www.douyin.com/hot/1103955'
        },
        {
            'title':'朝鲜超140万青年报名参军',
            'url':'https://www.douyin.com/hot/1103928'
        }
    ];

    $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等打包工具)

在这里插入图片描述

  1. index.js里面的数据写在了一个对象当中,实际应用需要使用AJAX/Fetch等方式获取数据返回JSON对象进行显示。

动图演示

在这个动图示例中,可以看到,切换tab的时候,下面的列表发生了变化,URL也发生了变化,但是并没有刷新页面。

在这里插入图片描述

DEMO

http://demo.likeyunba.com/ys-js-spa/#/

作者

TANKING

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/105423.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每日一练——返回链表的中间结点

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

Nginx 的配置文件(负载均衡,反向代理)

Nginx可以配置代理多台服务器&#xff0c;当一台服务器宕机之后&#xff0c;仍能保持系统可用。 cmd查找端口是否使用&#xff1a;netstat -ano Nginx出现403 forbidden #解决办法&#xff1a;修改web目录的读写权限&#xff0c;或者是把nginx的启动用户改成目录的所属用户&…

0基础学习PyFlink——用户自定义函数之UDF

大纲 标量函数入参并非表中一行&#xff08;Row&#xff09;入参是表中一行&#xff08;Row&#xff09;alias PyFlink中关于用户定义方法有&#xff1a; UDF&#xff1a;用户自定义函数。UDTF&#xff1a;用户自定义表值函数。UDAF&#xff1a;用户自定义聚合函数。UDTAF&…

Go学习第十章——文件操作,Json和测试

Go文件操作&#xff0c;Json和测试 1 文件1.1 基本介绍1.2 读取的基本操作1.3 写入的基本操作1.4 使用案例(三个) 2 Go语言的Json使用2.1 序列化案例2.2 反序列化案例 3 单元测试3.1 先看个需求3.2 快速入门3.3 入门总结 1 文件 1.1 基本介绍 文件在程序中是以流的形式来操作…

使用Jenkins触发gitlab的webhook

满足条件&#xff1a; 首先手动构建可以完成构建 例如&#xff1a; 打开项目点击配置 在“Build Triggers”栏勾选&#xff0c;Build when a change is pushed to GitLab. GitLab webhook &#xff1b;如下 复制URL链接&#xff0c;我的链接是&#xff1a;http://192.168.44…

HarmonyOS鸿蒙原生应用开发设计- 流转图标

HarmonyOS设计文档中&#xff0c;为大家提供了独特的流转图标&#xff0c;开发者可以根据需要直接引用。 开发者直接使用官方提供的流转图标内容&#xff0c;既可以符合HarmonyOS原生应用的开发上架运营规范&#xff0c;又可以防止使用别人的图标侵权意外情况等&#xff0c;减…

【每日一题】切割后面积最大的蛋糕

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;排序 其他语言python3 写在最后 Tag 【排序】【数组】【2023-10-27】 题目来源 1465. 切割后面积最大的蛋糕 题目解读 切割后面积最大的蛋糕。 解题思路 方法一&#xff1a;排序 本题较为简单&#xff0c;找出最大…

Android加载SO包

一、前言 这几天用Android整合开源的RTMP推拉流都没成功&#xff0c;好几年没玩Android了碰到好多坑&#xff0c;在Android中为了效率难免需要调用C语言编写生成的SO文件&#xff0c;比如图片渲染加速&#xff0c;视频编解码等插件&#xff0c;今天我们就先聊一下在Android中如…

51单片机实验:数码管动态显示00-99

1、实验要求 利用STC89C52RC单片机开发板实现&#xff1a;使用2位数码管循环显示00-99&#xff0c;每次间隔1s&#xff0c;并且当计数到20时&#xff0c;则蜂鸣器鸣响1次。 2、实验分析 程序实现分析&#xff1a; 1、定义数码管位选引脚&#xff08;P2.4、P2.5、P2.6、…

ES6初步了解迭代器

迭代器是什么&#xff1f; 迭代器(iterator)是一种接口&#xff0c;为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 iterator 接口&#xff0c;就可以完成遍历操作 ES6创造了一种新的遍历方法for…of循环&#xff0c;iterator 接口主要供 for…of 使用 原生中具…

Android12之#pragma clang diagnostic ignored总结(一百六十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

pip 更换源

方案1 在C盘用户名录下新建pip文件夹&#xff0c;里面包含pip.ini文件 方案2 在C盘用户名目录的AppData的Roaming下新建pip文件夹&#xff0c;里面包含pip.ini文件。 内容为 [global] index-url https://pypi.tuna.tsinghua.edu.cn/simple

Git(四)底层命令:git对象、树对象、提交对象

目录 一、知识回顾1.1 Linux 基础命令1.2 .git 文件夹解析 二、git 对象&#xff08;数据对象&#xff09;2.1 hash-object 存储对象2.2 cat-file 查看对象 三、树对象3.1 ls-files 查看暂存区3.2 update-index 创建暂存区3.3 write-tree 生成树对象3.4 更新暂存区&#xff0c;…

ffmpeg的下载和编译(vs2022)

感谢大佬的二创,直接提供了sln编译 ffmpeg二创地址 创建如下目录 build存放代码(build最好改成source,因为作者这么建议,编译完才发现) msvc存放第三方依赖的头文件,这里固定叫msvc,因为大佬的sln里查找的路径是这个,不嫌麻烦也可以自己改 下载代码和编译器 下载源码…

[论文阅读]Point Density-Aware Voxels for LiDAR 3D Object Detection(PDV)

PDV Point Density-Aware Voxels for LiDAR 3D Object Detection 论文网址&#xff1a;PDV 论文代码&#xff1a;PDV 简读论文 摘要 LiDAR 已成为自动驾驶中主要的 3D 目标检测传感器之一。然而&#xff0c;激光雷达的发散点模式随着距离的增加而导致采样点云不均匀&#x…

层次式架构的设计理论与实践

层次式架构的设计理论与实践 层次式架构概述 层次式架构的定义和特性 定义 特性 层次式架构的一般组成(表现层、中间层、数据访问层和数据层) 表现层框架设计 设计模式 MVC MVP MVVM XML技术 UIP设计思想 表现层动态生成设计思想(基于XML界面管理技术) 中间层架构设计 业务…

Vue+ElementUI项目打包部署到Ubuntu服务器中

1、修改config/index.js中的assetsPublicPath: /,修改为assetsPublicPath: ./ assetsPublicPath: ./2、在build/utils.js中增加publicPath: ../../ publicPath: ../../3、打开终端&#xff0c;在根目录下执行npm run build进行打包&#xff0c;打包成功后会生成dist npm run…

cmake练习一

需求&#xff1a; 1、利用CGAL库Boost库&#xff0c;写一个关于CGAL的程序 2、使用cmake构建 1、创建目录结构 src中有一个main.cpp&#xff0c;放的是我们的主程序代码 2、安装CGAL和Boost库 略 3、编写cmakelist.txt cmake_minimum_required(VERSION 3.1.0) project(cg…

规则推理桌游

目录 Eleusis Express 1&#xff0c;规则 2&#xff0c;出牌规则示例 3&#xff0c;中文规则 Eleusis Express 原文&#xff1a;Eleusis Express 1&#xff0c;规则 简单来说就是需要一个主持人想一个出牌规则&#xff0c;其他人通过出牌试探过程推理出这个出牌规则。 …

甘特图组件DHTMLX Gantt用例 - 如何自定义任务、月标记和网格新外观

dhtmlxGantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求&#xff0c;是最完善的甘特图图表库。 本文将为大家揭示DHTMLX Gantt自定义的典型用例&#xff0c;包括自定义任务、网格的新外观等&#xff0c;来展示其功能的强大性&…