选项卡进阶


前言

上篇说到:如何实现选项卡。那么实现选项卡的目的是为了在展示更多内容·的同时,减少翻页成本。大部分文档都是以选项卡形式呈现,它就像一本书我们可以看到它的目录。常见的二级列表三级列表是它复杂的延伸。如何将其封装成一个功能,通过数据渲染就可以实现昵,那么今天就来实现。


一、思路分析

1,我需要的是一个类似字典结构的文档展示页面
2,它不需要数据回流只做展示
3,我只需要将数据模型放进去就可以自动生成页面
4,我需要实现一个两级的选项页,顶部是专栏,左侧是细分,中间是内容

二,实现过程

样式及结构

	.app{
				position: relative;
				/* width: 100vw; */
				/* background-color: burlywood; */
				
			}
			.top{
				position: absolute;
				width: 100vw;
				height: 100px;
				/* background-color: #4169E1; */
				/* overflow-x: scroll; */
				/* overflow-y: hidden; */
			}
			.left{
				position: absolute;
				width: 100px;
				left: 0;
				/* background-color: #4169E1; */
			}
			.left-tap{
				width: 100px;
				height: 50px;
				text-align: center;
				line-height: 50px;
				color: white;
				margin-top: 2px;
				background-color: pink;
			}
			.left-tap:hover{
				background-color: #008000;
			}
			.right{
				position: absolute;
				right: 0;
				width: 80vw;
				height: 100px;
				box-sizing: border-box;
				padding: 20px;
			}
			.right-content{
				height: 50px;
				width: 100%;
				font-size: 30px;
				color: orchid;
				
			}
			.bottom{
				position: absolute;
				left: 50%;
				width: 90vw;
				transform: translate(-50%);
				top:120px;
				height: 100px;
				
				/* display: flex;
				justify-content: space-between; */
			}
			.top-tab{
				float: left;
				width: 150px;
				text-align: center;
				line-height: 100px;
				height: 100px;
				margin-right: 5px;
				border-top-right-radius: 20px;
				background-color: green;
				font-size: 20px;
				color: white;
			}
<div class="app" id="app">
			
		</div>

结构就只有一个根结点,通过createElement()创建
*调用代码

window.onload = function(){
			new Tab("app").init(list,2).click1().click2();
		}

数据模型

const list = [
			{    
				"HTML":[
				    {
					    "div":[
						    "div是一个盒模型,是构成网页内容的基本盒子",
							"是块元素,独占一行"  
					    ]
				    },
					{
						"p":[
							"p标签是行内块元素,默认情况下独占一行",
							"p标签不可嵌套p标签"
						]
					},
					{
						"input":[
							"input内容输入标签,可设置多种type",
							"功能强大"
						]
					}
			    ],
				"CSS":[
				    {
					    "简介":[
						    "css层叠样式表是书写网页样式的重要部分",
							"有多种选择器"  
					    ]
				    },
					{
						"选择器":[
							"类选择器",
							"标签选择器",
							"id选择器"
						]
					},
					{
						"属性":[
							"color设置文本内容颜色",
							"height元素高度",
							"transition过渡效果"
						]
					}
				],
				"JAVASCRIPt":[
				    {
					    "环境":[
						    "js目前仍是网页展示的主流脚本",
							"node平台和ES6的普及大大提高了js的功能性",
							"它能做的事情很多包括智能设备"
					    ]
				    },
					{
						"变量":[
							"var,let,const变量的三种声明方式",
							"变量的本质是作用域上的键",
							"其作用是将相同的数据引用到不同的地方,如果引用数据最好使用变量接收"
						]
					},
					{
						"数据类型":[
							"基本数据类型",
							"引用数据类型"
						]
					}
				],
			}	
		]
		

封装

function Tab(id){
	this.app = document.getElementById(id);
	this.topDiv = document.createElement("div");
	this.bottomDiv = document.createElement("div");
	this.leftDiv = document.createElement("div");
	this.rightDiv = document.createElement("div");
    this.app.appendChild(this.topDiv);
	this.app.appendChild(this.bottomDiv);
	this.bottomDiv.appendChild(this.leftDiv);
	this.bottomDiv.appendChild(this.rightDiv);
}
Tab.prototype.init = function(list=[],index=0,place=0){
	if(this.leftDiv.className) return;//避免重复渲染
	this.topDiv.classList.add('top');
	this.bottomDiv.classList.add('bottom');
	this.leftDiv.classList.add('left');
	this.rightDiv.classList.add('right');
	
	for(var i = 0;i<list.length;i++){
		//取得一级结构主键生成专栏
		let oneTap = Object.keys(list[i]);
		let leftCont = [];
		for(var k = 0;k<oneTap.length;k++){
			let elementTop = document.createElement('duv');
			elementTop.innerHTML = oneTap[k];
			elementTop.classList.add('top-tab');
			if(k === index){
				elementTop.style.backgroundColor = "yellow";
			}
			this.topDiv.appendChild(elementTop);
		}
		//遍历每个主键的内容,生成侧边栏
		for(let key in list[i]){
			// console.log(key);
			for(var j = 0;j < list[i][key].length; j++){
				let leftTap = document.createElement("div");
				leftTap.classList.add('left-tap');
				leftTap.innerText = Object.keys(list[i][key][j]);
				leftTap.keys = Object.keys(list[i][key][j])[0];
				if(oneTap[index] === key){
					leftTap.style.display = 'block';
					leftCont.push(Object.keys(list[i][key][j])[0]);
					if(j === place){
						leftTap.style.backgroundColor = 'yellow';
					}
				}else{
					leftTap.style.display = 'none';
					
				}
				this.leftDiv.appendChild(leftTap);
				//遍历生成内容
				for(var p = 0;p < list[i][key][j][Object.keys(list[i][key][j])].length;p++){
					
					let contentDiv = document.createElement("div");
					contentDiv.classList.add('right-content');
					contentDiv.innerText = list[i][key][j][Object.keys(list[i][key][j])][p];
					contentDiv.cont = list[i][key][j][Object.keys(list[i][key][j])][p];
					contentDiv.level = Object.keys(list[i][key][j])[0];
					if(oneTap[index] === key&&Object.keys(list[i][key][j])[0] === leftCont[0]){
						if(j === place){
							contentDiv.style.display = 'block';
						}
					}else{
						contentDiv.style.display = 'none';
					}
					this.rightDiv.appendChild(contentDiv);
				}
			}
		}
	}
	return this;
}
Tab.prototype.click1 = function(){
	let oneTap = Object.keys(list[0]);
	let topTap = this.topDiv.children;
	let leftTap = this.leftDiv.children;
	let contentDiv = this.rightDiv.children;
	for(let i = 0;i < topTap.length;i++){
		topTap[i].key = i;
		topTap[i].onclick = function(){
			let key = this.key;
			let keyArr = [];
			let optTapArr = [];
			let contArr = [];
			//点击态
			for(var k = 0 ;k < topTap.length;k++){
				if(key === k){
					topTap[k].style.backgroundColor = "yellow";
				}else{
					topTap[k].style.backgroundColor = "green";
				}
			}
			//数据 对应的键
			for(var k = 0;k < list[0][oneTap[key]].length;k++){
				keyArr.push(Object.keys(list[0][oneTap[key]][k])[0])
			}
			//筛选应该显示的键
			for(var k = 0 ;k < leftTap.length;k++){
				for(var j = 0 ;j < keyArr.length;j++){
					if(keyArr[j] === leftTap[k].keys){
						optTapArr.push(leftTap[k]);
					}else{
						leftTap[k].style.display = 'none';
						leftTap[k].style.backgroundColor = 'pink';
					}
				}
			}
			for(var k = 0;k < optTapArr.length;k++){
				optTapArr[k].style.display = "block";
			}
			//默认选择第一个
			optTapArr[0].style.backgroundColor = 'yellow';
			//对应的内容也要展示第一个的
			for(var k = 0;k < contentDiv.length;k++){
				if(optTapArr[0].keys === contentDiv[k].level){
					contentDiv[k].style.display = "block";
				}else{
					contentDiv[k].style.display = "none";
				}
			}
		}
	}
	return this;
}
Tab.prototype.click2 = function(){
	let leftTap = this.leftDiv.children;
	let contentDiv = this.rightDiv.children;
	for(let i = 0;i < leftTap.length; i++){
		leftTap[i].key = i;
		leftTap[i].onclick = function(){
			let keys = this.keys;
			let key = this.key;
			for(var k = 0;k < leftTap.length; k++){
				leftTap[k].style.backgroundColor = 'pink';
			}
			this.style.backgroundColor = "yellow";
			for(var k = 0;k < contentDiv.length; k++){
				if(keys === contentDiv[k].level){
					contentDiv[k].style.display = "block";
				}else{
					contentDiv[k].style.display = "none";
				}
			}
		}
	}
    return this;	
}

效果
在这里插入图片描述

总结

整个实现过程较为粗糙,细节需要打磨,在生成dom结构的时候,我就应该生成和数据文档一样的dom结构。这样可以提高效率和便于后续操作。数据模型写的有些问题,我应该直接使用对象为最外层。在这个过程中我一点虚拟dom的思路了。还可以做一个标识,当切回来的时候保持原有状态。后续会写。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值