用JS原生实现锚点定位功能/动态目录高亮

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Document</title>
		<style>
			html,
			body {
				margin: 0;
				padding: 0;
				height: 100%;
			}

			.container {
				width: 100%;
				display: flex;
				padding: 20px 50px;
				box-sizing: border-box;
			}

			.directory {
				width: 200px;
			}

			.content {
				flex: 1;
				display: flex;
				flex-direction: column;
			}

			.content h2 {
				margin: 0;
			}

			.districtName {
				width: 100%;
			}

			.container .directory ul,
			.container .directory li {
				list-style: none;
			}

			#category {
				position: sticky;
				top: 16px;
				right: 0;
			}

			#category a {
				padding: 0 16px;
				color: #2d2e2f;
				outline: none;
				text-decoration: none;
				line-height: 30px;
			}

			#category a:hover {
				background: #efefef;
			}

			#category a.active {
				background: #efefef;
				color: #1890ff;
			}
		</style>
	</head>
	<body>
		<div class="container">
			<div class="content">
				<div data-tab="districtName1" class="districtName">
					<h2 class="data-tab">页面一</h2>
					<section class="markdown">
						<p>按钮用于开始一个即时操作。</p>
						</h2>
						<p>标记了一个(或封装一组)操作命令,响应用户点击行为,触发相应的业务逻辑。</p>
						<ul>
							<li>
								<p>主按钮:用于主行动点,一个操作区域只能有一个主按钮。</p>
							</li>
							<li>
								<p>默认按钮:用于没有主次之分的一组行动点。</p>
							</li>
							<li>
								<p>虚线按钮:常用于添加操作。</p>
							</li>
							<li>
								<p>文本按钮:用于最次级的行动点。</p>
							</li>
							<li>
								<p>链接按钮:一般用于链接,即导航至某位置。</p>
							</li>
						</ul>
						<p>以及四种状态属性与上面配合使用。</p>
						<ul>
							<li>
								<p>危险:删除/移动/修改权限等危险操作,一般需要二次确认。</p>
							</li>
							<li>
								<p>幽灵:用于背景色比较复杂的地方,常用在首页/产品页等展示场景。</p>
							</li>
							<li>
								<p>禁用:行动点不可用的时候,一般需要文案解释。</p>
							</li>
							<li>
								<p>加载中:用于异步操作等待反馈的时候,也可以避免多次提交。</p>
							</li>
						</ul>
					</section>
				</div>
				<div data-tab="districtName2" class="districtName">
					<h2 class="data-tab">页面二</h2>
					<section class="markdown api-container">
						<ul>
							<li>
								<p>页面二</p>
								<p>页面二</p>
								<p>页面二</p>
								<p>页面二</p>
								<p>页面二</p>
								<p>页面二</p>
								<p>页面二</p>
								<p>页面二</p>
								<p>页面二</p>
								<p>页面二</p>
							</li>
						</ul>
					</section>
				</div>
				<div data-tab="districtName3" class=" districtName">
					<h2 class="data-tab">页面三</h2>
					<div>
						<p>页面三</p>
						<p>页面三</p>
						<p>页面三</p>
						<p>页面三</p>
						<p>页面三</p>
						<p>页面三</p>
						<p>页面三</p>
						<p>页面三</p>
						<p>页面三</p>
						<p>页面三</p>
						<p>页面三</p>
						<p>页面三</p>
					</div>
				</div>
				<div data-tab="districtName4" class="districtName">
					<h2 class="data-tab">页面四</h2>
					<div>
						<p>页面四</p>
						<p>页面四</p>
						<p>页面四</p>
						<p>页面四</p>
						<p>页面四</p>
						<p>页面四</p>
						<p>页面四</p>
						<p>页面四</p>
						<p>页面四</p>
						<p>页面四</p>
					</div>
				</div>
				<div data-tab="districtName5" class="districtName">
					<h2 class="data-tab">页面五</h2>
					<div>
						<p>页面五</p>
						<p>页面五</p>
						<p>页面五</p>
						<p>页面五</p>
						<p>页面五</p>
						<p>页面五</p>
						<p>页面五</p>
						<p>页面五</p>
						<p>页面五</p>
						<p>页面五</p>
					</div>
				</div>
			</div>
			<div class="directory">
				<div id="category">
					<ul>
					</ul>
				</div>
			</div>
		</div>
		<div style="height: 500px; background: #eee;">

		</div>
	</body>
	<script>
		class dataScroll {
			// 声明获取名字的节点
			districtName = document.querySelectorAll('.container .districtName')
			constructor() {
				this.init()
			}
			init() {
				this.initDom() //初始化dom
				this.initScroll() //初始化监听滚动
			}
			initDom() {
				var districtName = this.districtName
				var directoryDom = document.querySelector('.directory #category ul')
				let Listdom = "";
				districtName.forEach(item => {
					let linkClass = item.querySelector(".data-tab")
					Listdom += `<li><a data-tab=${item.getAttribute('data-tab')}>${linkClass.innerHTML}</a></li>`
				})
				directoryDom.innerHTML = Listdom
				var Alist = directoryDom.querySelectorAll("li a")
				Alist.forEach(el => {
					el.addEventListener('click', function(e) {
						let aClick = e.target.getAttribute("data-tab")
						districtName.forEach(targetNode => {
							if (targetNode.getAttribute('data-tab') === e.target.getAttribute(
									"data-tab")) {
								//页面直接滚动不过度 A标签高亮
								// document.documentElement.scrollTop = targetNode.offsetTop
								// 页面动画滚动过度 A标签高亮
								targetNode.scrollIntoView({
									behavior: "smooth",
									block: "start",
									inline: "start",
								});
							}
						})
					})
				})
			}
			initScroll() {
				window.addEventListener("scroll", (e) => {
					var scroll = document.documentElement.scrollTop || document.body.scrollTop;
					var sections = this.districtName
					for (var i = sections.length - 1; i >= 0; i--) {
						if (parseInt(scroll) >= Math.ceil(sections[i].offsetTop) - 20) {
							this.activeLoadScroll(sections[i].getAttribute('data-tab'))
							return
						}
					}
				})
			}
			activeLoadScroll(sections) {
				var categoryDomA = document.querySelectorAll('.directory #category ul li a')
				categoryDomA.forEach(item => {
					if (item.getAttribute('data-tab') == sections) {
						item.className = "active"
					} else {
						item.className = ""
					}
				})
			}
		}
		new dataScroll() //初始化节点和监听滚动
	</script>

</html>

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值