js分页逻辑(【JavaScript】JS实用案例分享:动态生成分页组件 | 通过按键实现移动控制)
CSDN话题挑战赛第2期
参赛话题:学习笔记🖥️ NodeJS专栏:Node.js从入门到精通
🖥️ 博主的前端之路(源创征文一等奖作品):前端之行 ,任重道远(来自大三学长的万字自述)
🖥️ TypeScript知识总结:TypeScript从入门到精通(十万字超详细知识点总结)
🧑💼 个人简介:大三学生 ,一个不甘平庸的平凡人🍬
👉 你的一键三连是我更新的最大动力❤️!
🏆分享博主自用牛客网🏆:一个非常全面的面试刷题求职网站 ,点击跳转🍬前言
最近博主一直在牛客网刷题巩固基础知识 ,牛客网不仅具有公司真题 、专项练习 、面试题库 、在线编程等功能 ,还具有非常强大的AI模拟面试功能 ,简直是求职者的福音!
牛客网里的题库非常全面的 ,无论你是前端还是后端 ,是想要备考还是准备面试又或者是想要提高自己 ,你都能在牛客网上找到适合自己的题 ,赶快点击链接去注册登录吧:点我进入牛客网
牛客网 牛客网本篇文章所有示例来自于牛客网题库/在线编程/JS篇 ,这些都是前端开发中常用的功能 ,借此记录一下刷题过程,巩固基础!
1 、动态生成分页组件
效果演示
有以下HTML和CSS:
HTML结构
<div> <!-- 存放JS动态生成组件容器:节点A --> <div id="jsContainer"> <div>生成分页组件:</div> </div> <hr> <!-- 以下是演示demo --> <div class="demo"> <div>(Demo1) total: 10 ,current: 4</div> <ul class="pagination"> <li>首页</li> <li>2</li> <li>3</li> <li class="current">4</li> <li>5</li> <li>6</li> <li>末页</li> </ul> </div> <div class="demo"> <div>(Demo2) total: 0 ,current: 0</div> <ul class="pagination hide"></ul> </div> <div class="demo"> <div>(Demo3) total: 3,current: 2</div> <ul class="pagination"> <li>1</li> <li class="current">2</li> <li>3</li> </ul> </div> <div class="demo"> <div>(Demo4) total: 10 ,current: 2</div> <ul class="pagination"> <li>1</li> <li class="current">2</li> <li>3</li> <li>4</li> <li>5</li> <li>末页</li> </ul> </div> <div class="demo"> <div>(Demo5) total: 10 ,current: 9</div> <ul class="pagination"> <li>首页</li> <li>6</li> <li>7</li> <li>8</li> <li class="current">9</li> <li>10</li> </ul> </div> </div>CSS样式
.demo { margin-bottom: 20px; border: 1px solid #ebedf0; border-radius: 2px; padding: 10px; } .demo div { margin-bottom: 10px; font-size: 14px; } .pagination { box-sizing: border-box; margin: 0; padding: 0; font-size: 14px; line-height: 1.5; list-style: none; display: inline-block; } .pagination.hide { display: none; } .pagination li { position: relative; display: inline-block; float: left; height: 32px; margin: 0; padding: 0 15px; line-height: 30px; background: #fff; border: 1px solid #d9d9d9; border-top-width: 1.02px; border-left: 0; cursor: pointer; transition: color 0.3s, border-color 0.3s; } .pagination li:first-child { border-left: 1px solid #d9d9d9; border-radius: 4px 0 0 4px; } .pagination li:last-child { border-radius: 0 4px 4px 0; } .pagination li:first-child { box-shadow: none !important; } .pagination li.current { border-color: #1890ff; color: #1890ff; border-left: 1px solid #1890ff; } .pagination li.current:not(:first-child) { margin-left: -1px; }案例需求
界面中存在id=jsContainer的节点A ,系统会随机实例化各种Pagination实例 ,按照如下要求补充完成Pagination函数 。
最多连续显示5页 ,居中高亮显示current页(如demo1所示):
total <= 1 时 ,隐藏该组件(如demo2所示):
如果total<=5 ,则显示全部页数 ,隐藏“首页 ”和“末页 ”元素(如demo3所示):
当current居中不足5页 ,向后(前)补足5页 ,隐藏“首页 ”(“末页 ”)元素(如demo4和demo5所示):
total 、current均为正整数 ,1 <= current <= total
上面效果演示是 new Pagination(document.getElementById(jsContainer), 16, 9) 执行后的结果
JavaScript实现
function Pagination(container, total, current) { this.total = total; this.current = current; this.html = html; this.el = document.createElement(ul); //TODO: 创建分页组件根节点 this.el.className = pagination if (!this.el) return; this.el.innerHTML = this.html(); container.appendChild(this.el); // 分页组件根节点内容为空时 ,添加hide类名隐藏 if (!this.el.innerHTML) { this.el.className = pagination hide; //TODO: 判断是否需要隐藏当前元素 } function html() { if (this.total <= 1) return ; let str = //TODO: 生成组件的内部html字符串 if (this.total <= 5) { for (let i = 1; i <= this.total; i++) { str += i == this.current ? `<li class="current">${this.current}</li>` : `<li>${i}</li>` } } else { if (this.current <= 3) { for (let i = 1; i <= 5; i++) { str += i == this.current ? `<li class="current">${this.current}</li>` : `<li>${i}</li>` } str += <li>末页</li> } if (this.current > 3 && this.current < this.total - 2) { str += <li>首页</li> for (let i = this.current - 2; i <= this.current + 2; i++) { str += i == this.current ? `<li class="current">${this.current}</li>` : `<li>${i}</li>` } str += <li>末页</li> } if (this.current >= this.total - 2) { str += <li>首页</li> for (let i = this.total - 4; i <= this.total; i++) { str += i == this.current ? `<li class="current">${this.current}</li>` : `<li>${i}</li>` } } } return str; } } // 测试 new Pagination(document.getElementById(jsContainer), 16, 20)这个案例中Pagination是一个构造函数,需要通过new操作符调用 ,需要注意的是Pagination内的方法(如html方法)需要先挂载到Pagination上(this.html = html)才能被Pagination中的其它成员访问(通过this访问this.html())
知识点:
new 运算符与构造函数的使用 。2 、通过按键实现移动控制
效果演示
有以下HTML和CSS:
HTML结构
<div id="jsContainer"> <table class="game"> <tbody> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td class="current"></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> <tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> </tbody> </table> </div>CSS样式
table.game { font-size: 14px; border-collapse: collapse; width: 100%; table-layout: fixed; } table.game td { border: 1px solid #e1e1e1; padding: 0; height: 30px; text-align: center; } table.game td.current{ background: #1890ff; }案例需求
界面中存在id=jsContainer的节点A ,系统会随机生成class为game的 m行 n列表格(m >= 1, n >= 1),并随机选中一个td节点 ,请按照如下需求实现bind函数
bind 函数为document绑定keydown事件 ,当系统触发上(键值38) 、下(键值40) 、左(键值37) 、右(键值39)按键时 ,请找到当前选中的td节点 ,并根据当前指令切换高亮节点 ,具体效果参考上面的效果演示 。
在第一列往左移动则到达最后一列;在最后一列往右移动则到达第一列;在第一行往上移动则到达最后一行;在最后一行往下移动则到达第一行;
当前界面为系统在节点A中生成 9 * 9 表格并随机选中一个td节点后的效果 。
JavaScript实现
function bind() { document.onkeydown = event => { if (!event) return; var code = event.keyCode || ; if (!{ 37: 1, 38: 1, 39: 1, 40: 1 }[code]) return; event.preventDefault && event.preventDefault(); //TODO: 请实现按键控制 // 当前元素 const nowCode = document.getElementsByClassName(current)[0] // 当前元素的父节点的所有子字节的集合 const brotherItems = nowCode.parentElement.getElementsByTagName(td) // 获取当前元素在父元素中的下标 // 通过数组的indexOf方法查找nowCode在brotherItems中的下标 // 因为brotherItems是伪数组 ,不算真正意义上的数组 ,不能直接使用indexOf方法 , // 所以这里通过在随便一个数组上使用indexOf([].indexOf) ,然后通过call改变indexOf方法的this指向 ,使其指向到brotherItems // 这样做之后就相当于是在brotherItems身上执行indexOf方法 ,call方法的第一个参数之后的参数会作为indexOf方法的参数 const index = [].indexOf.call(brotherItems, nowCode) // 去除类名 nowCode.className = switch (code) { // 向左移动 case 37: // previousElementSibling获取上一个兄弟节点 if (nowCode.previousElementSibling) { // 如果上个兄弟节点存在 ,则为上个兄弟节点添加class nowCode.previousElementSibling.className = current } else { // 如果上个兄弟节点不存在,则为父节点的最后一个孩子节点添加class // parentElement获取父节点 // lastElementChild获取最后一个孩子节点 nowCode.parentElement.lastElementChild.className = current } return; // 向右移动 case 39: // nextElementSibling获取下一个兄弟节点 if (nowCode.nextElementSibling) { // 如果下个兄弟节点存在 ,则为下个兄弟节点添加class nowCode.nextElementSibling.className = current } else { // 如果下个兄弟节点不存在 ,则为父节点的第一个孩子节点添加class // parentElement获取父节点 // firstElementChild获取第一个孩子节点 nowCode.parentElement.firstElementChild.className = current } return; // 向上移动 case 38: if (nowCode.parentElement.previousElementSibling) { // 如果父元素的上个兄弟节点存在,则为父元素上个兄弟节点的所有孩子节点中下标为index的元素添加class nowCode.parentElement.previousElementSibling.getElementsByTagName(td)[index].className = current } else { // 如果父元素的上个兄弟节点不存在 ,则为父元素的父元素(爷元素)的最后一个节点的所有孩子节点中下标为index的元素添加class nowCode.parentElement.parentElement.lastElementChild.getElementsByTagName(td)[index].className = current } return; // 向下移动 case 40: if (nowCode.parentElement.nextElementSibling) { // 如果父元素的下个兄弟节点存在 ,则为父元素下个兄弟节点的所有孩子节点中下标为index的元素添加class nowCode.parentElement.nextElementSibling.getElementsByTagName(td)[index].className = current } else { // 如果父元素的下个兄弟节点不存在 ,则为父元素的父元素(爷元素)的第一个节点的所有孩子节点中下标为index的元素添加class nowCode.parentElement.parentElement.firstElementChild.getElementsByTagName(td)[index].className = current } return; } }; } // 调用测试 bind()这个案例主要考察了对JavaScript DOMApi的运用 ,需要注意的是通过DOMApi获取的元素集合是HTMLCollection类型的伪数组对象 ,它并不能算是真正意义上的数组 ,数组上的一些方法对它也不适用 ,这与arguments相似 。
知识点:
previousElementSibling 返回当前元素在其父元素的子元素节点中的前一个元素节点 ,如果该元素已经是第一个元素节点 ,则返回 null, 该属性是只读的 。 nextElementSibling 返回当前元素在其父元素的子元素节点中的后一个元素节点 ,如果该元素已经是最后一个元素节点 ,则返回 null, 该属性是只读的 。 parentElement 返回当前节点的父元素节点 ,如果该元素没有父节点,或者父节点不是一个 DOM 元素 ,则返回 null 。 lastElementChild 返回对象的最后一个子元素 ,如果没有子元素,则返回 null 。 firstElementChild 只读属性 ,返回对象的第一个子元素, 如果没有子元素 ,则为 null 。 call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数 。结语
这篇文章的所有内容都出自于牛客网的JS篇题库:
牛客网的JS题库非常贴合实际的 ,在写的过程中自己查漏补缺 ,收获了很多 ,强烈将牛客网推荐给大家!
如果本篇文章对你有所帮助 ,还请客官一件四连!❤️
基础不牢 ,地动山摇! 快来和博主一起来牛客网刷题巩固基础知识吧!
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!