【JS】Day24

学习内容

  • 认识单页面应用程序
  • 组件化开发

认识单页面应用程序

//关于单页应用
//单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。简单来说就是用户只需要加载一次页面就可以不再请求,当点击其他子页面时只会有相应的URL改变而不会重新加载。
  //大部分用于 移动端 / PC端的后台管理系统。

//网站的默认端口号是80
//端口号的范围0~65535
//protocol: 协议
//auth: 作者
//username: 用户名
//password: 密码
//host: 主机
//hostname: 主机名
//port: 端口号
//path: 路径
//pathname: 路径名
//search: 搜索、检索
//query: 查询、请求
//hash: 哈希
//#thash: 锚点链接

//单页应用的实现
//1.依赖hash的改变(锚点)
//2.依赖历史记录(history)
  //前端路由: 在页面中同一个位置,根据不同的hash值显示不同的页面结构。

//实现改变URL页面不刷新
//按照常规的逻辑我们切换URL好像就会跳转网页,但是转念一想锚链接的URL不是也改变了吗? 这里,存在两种满足需求的方式。
  //1.利用URL中的hash方式
    //了解http协议就会知道,url的组成部分有很多,譬如协议、主机名、资源路径、查询字段等等,其中包含一个称之为片段的部分,以“#”为标识。打开控制台,输入 location.hash,你可以得到当前url的hash部分(如果当前url不存在hash则返回空字符串)。接下来,输入 location.hash = '123',会发现浏览器地址栏的url变了,末尾增加了’#123’字段,并且,页面没有被重新刷新。很显然,这很符合我们的要求。
  //2.利用H5的history API
    //html5引入了一个history对象,包含了一套访问浏览器历史的api,可以通过window.history访问到它。 HTML5 History API包括2个方法:history.pushState()和history.replaceState(),和1个事件:window.onpopstate。这两个方法都是对浏览器的历史栈进行操作,将传递的url和相关数据压栈,并将浏览器地址栏的url替换成传入的url且不刷新页面,而且他们的参数也相同,第一个参数用于存储该url对应的状态对象,该对象可在onpopstate事件中获取,也可在history对象中获取。第二个参数是标题,目前浏览器并未实现。第三个参数则是设定的url。一般设置为相对路径,如果设置为绝对路径时需要保证同源。。不同的是pushState 将指定的url直接压入历史记录栈顶,而 replaceState 是将当前历史记录栈顶替换成传入的数据。不过低版本对history AIP的兼容性不是很好。

//监听URL的变化,执行页面替换逻辑
//对于hash方式,我们通常采用监听 hashchange 事件,在事件回调中处理相应的页面视图展示等逻辑。

//两种实现的比较
//总的来说,基于Hash的路由,兼容性更好;基于History API的路由,更加直观和正式。但是,有一点很大的区别是,基于Hash的路由不需要对服务器做改动,基于History API的路由需要对服务器做一些改造。

	<style>
		*{
			margin: 0;
			padding: 0;
		}
		html,body,#box{
			width: 100%;
			height:100%;
		}
		#box{
			display: flex;
			flex-direction:column;
		}
		#box>.top{
			height: 130px;
			background: skyblue;
		}
		#box>.bottom{
			flex:1;
			display: flex;
		}
		#box>.bottom>.slide{
			width: 230px;
			background-color: orange;
			box-sizing: border-box;
			padding: 15px;
		}
		#box>.bottom>.slide>a{
			font-size: 22px;
			display: block;
			margin: 10px 0;
			text-decoration: none;
			color: #333;
		}
		#box>.bottom>.content{
			flex: 1;
			box-sizing: border-box;
			padding: 15px;
			background: purple;
			font-size: 100px;
			color: white
		}
	</style>
<body>
	<div id="box">
		<div class="top">顶部通栏</div>
		<div class="bottom">
			<div class="slide">
				<a href="#/first">first</a>
				<a href="#/second">second</a>
				<a href="#/third">third</a>
				<a href="#/fourth">fourth</a>
			</div>
			<div class="content router-view"></div>
		</div>
	</div>
	<script>
		// 路由:
		//根据不同的请求,我们封装不同的页面数据
		//    template : 模板
		//当发出 #/first 请求时,我们响应的页面数据
		const template1 = `
			<div>
				first - 哈哈
			</div>
		`;
		//当发出 #second 请求时,我们响应的页面数据
		const template2 = `
			<div>
				second - 呵呵
			</div>
		`;
		//当发出 #third 请求时,我们响应的页面数据
		const template3 = `
			<div>
				third - 嘿嘿
			</div>
		`;
		//当发出 #fourth请求时,我们响应的页面数据
		const template4 = `
			<div>
				fourth - 嘻嘻
			</div>
		`;
		//一、 获取页面元素
		//content : 内容
		let content = document.querySelector('.content');
		//内容区初始化第一个页面的内容
		content.innerHTML = template1;
		//二、添加事件
		//监听浏览器地址栏中的hash值的变化
		//url: http://www.baidu.com:80/s?id=1#/first
		window.onhashchange = function(){
			//获取hash值
			//给hash 设置一个默认值 / : 根目录
			// let hash = window.location.hash || '/';
			let { hash } = window.location;
			console.log(hash);
			switch(hash){
				case '#/first' : 
					content.innerHTML = template1; break;
				case '#/second' : 
					content.innerHTML = template2;break;
				case '#/third' : 
					content.innerHTML = template3;break;
				case '#/fourth' : 
					content.innerHTML = template4;break;
			}
		}
	</script>
</body>

组件化开发

//--html--

<head>
	<meta charset="utf-8">
	<title></title>
	<style>
		*{
			margin: 0;
			padding: 0;
		}
		html,body,#box{
			width: 100%;
			height:100%;
		}
		#box{
			display: flex;
			flex-direction:column;
		}
		#box>.top{
			height: 130px;
			background: skyblue;
		}
		#box>.bottom{
			flex:1;
			display: flex;
		}
		#box>.bottom>.slide{
			width: 230px;
			background-color: orange;
			box-sizing: border-box;
			padding: 15px;
		}
		#box>.bottom>.slide>a{
			font-size: 22px;
			display: block;
			margin: 10px 0;
			text-decoration: none;
			color: #333;
		}
		#box>.bottom>.content{
			flex: 1;
			box-sizing: border-box;
			padding: 15px;
			background: purple;
			font-size: 100px;
			color: white
		}
	</style>
</head>
<body>
	<div id="box">
		<div class="top">顶部通栏</div>
		<div class="bottom">
			<div class="slide">
				<a href="#/first">first</a>
				<a href="#/second">second</a>
				<a href="#/third">third</a>
				<a href="#/fourth">fourth</a>
			</div>
			<div class="content router-view"></div>
		</div>
	</div>
	<script src="js/index.js" type="module"></script>
</body>

//--js--

//1. 导入路由表
import router from '../router/router.js';
fn(); //在没有触发hash改变事件前,也就是刚打开页面时,所要显示的内容
//2. 监听事件
window.onhashchange = fn;
function fn(){
    //1. 获取url中的hash值
    // let {hash} = window.location;//'#/first'
    let hash = window.location.hash.slice(1) || '/';
    console.log(hash); 
    //2. 在路由表中找到我们需要的数据
    // 数组的方法: find((value,index,array){return 条件}) : 找到满足条件的第一个元素返回来,如果没有满足条件的,则返回undefined 
    //                item : 代表数组中的第一个元素(对象)
    //information : 信息
    let info = router.find(item => hash === item.name);
    console.log(info);

    //3. 检测信息是否存在
    //如果component 没有找到任何内容 undefined
    if(!info){
        console.log('缺少页面数据!');
        return; //退出函数
    }
    //4. 渲染页面
    info.component(); //渲染页面
}

//--router--

//1. 导入渲染页面的组件
import firstCom from '../components/first.js';
import secondCom from '../components/second.js';
import thirdCom from '../components/third.js';
import fourthCom from '../components/fourth.js';
//2. 定义一个路由表
//router: 路由
// hash: #/first
const router = [
    {
        name: '/first',  //用户的请求
        component: firstCom //响应用户的页面数据
    },
    {
        name: '/second', //用户的请求
        component: secondCom  //响应用户的页面数据
    },
    {
        name: '/third', // 用户的请求
        component: thirdCom //响应用户的页面数据
    },
    {
        name: '/fourth',//用户的请求
        component: fourthCom //响应用户的页面数据
    },
    {
        name: '/',
        component: firstCom
    }
];
//3. 导出路由表
export default router;

//--components--

//1. 准备页面数据
const template = `
    <div id="first">
        first-呵呵
    </div>
`;
//2. 获取页面数据存放的地方
let content = document.querySelector('.content');
//3. 封装一个渲染页面数据的函数
//render : 渲染
function render(){
    content.innerHTML = template;
}
//ES6的模块化设计
export default render;

//1. 准备渲染的数据
const template = `
    <div id="second">
        second -- 哈哈
    </div>
`;
//2. 获取内容区的元素
let content = document.querySelector('.content');
//3. 封装渲染函数
function render(){
    content.innerHTML = template;
}
//4. 导入渲染模块
export default render;

//1. 准备渲染数据
const template = `
    <div id="third">
        third -- 嘿嘿
    </div>
`;
//2. 获取内容区元素
let content = document.querySelector('.content');
//3. 封装渲染函数
function render(){
    content.innerHTML = template;
}
//4. 导出模块
export default render;

//1. 准备渲染数据
const template = `
    <div id="fourth">
        fourth--- 嘻嘻
    </div>
`;
//2. 获取内容区元素
let content = document.querySelector('.content');
//3. 封装渲染函数
function render(){
    content.innerHTML = template;
}
//4. 导出模块
export default render;
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值