【JavaScript】JS实用案例分享:动态生成分页组件 | 通过按键实现移动控制

news2025/1/21 15:27:23

CSDN话题挑战赛第2期
参赛话题:学习笔记

🖥️ NodeJS专栏:Node.js从入门到精通
🖥️ 博主的前端之路(源创征文一等奖作品):前端之行,任重道远(来自大三学长的万字自述)
🖥️ TypeScript知识总结:TypeScript从入门到精通(十万字超详细知识点总结)
🧑‍💼 个人简介:大三学生,一个不甘平庸的平凡人🍬
👉 你的一键三连是我更新的最大动力❤️!
🏆分享博主自用牛客网🏆:一个非常全面的面试刷题求职网站,点击跳转🍬


文章目录

  • 前言
  • 1、动态生成分页组件
    • 效果演示
    • 案例需求
    • JavaScript实现
  • 2、通过按键实现移动控制
    • 效果演示
    • 案例需求
    • JavaScript实现
  • 结语

前言

最近博主一直在牛客网刷题巩固基础知识,牛客网不仅具有公司真题专项练习面试题库在线编程等功能,还具有非常强大的AI模拟面试功能,简直是求职者的福音!

牛客网里的题库非常全面的,无论你是前端还是后端,是想要备考还是准备面试又或者是想要提高自己,你都能在牛客网上找到适合自己的题,赶快点击链接去注册登录吧:点我进入牛客网

牛客网牛客网
在这里插入图片描述在这里插入图片描述

本篇文章所有示例来自于牛客网题库/在线编程/JS篇,这些都是前端开发中常用的功能,借此记录一下刷题过程,巩固基础!

1、动态生成分页组件

效果演示

在这里插入图片描述

有以下HTMLCSS

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函数。

  1. 最多连续显示5页,居中高亮显示current页(如demo1所示):

    在这里插入图片描述

  2. total <= 1 时,隐藏该组件(如demo2所示):

    在这里插入图片描述

  3. 如果total<=5,则显示全部页数,隐藏“首页”和“末页”元素(如demo3所示):

    在这里插入图片描述

  4. current居中不足5页,向后(前)补足5页,隐藏“首页”(“末页”)元素(如demo4demo5所示):

    在这里插入图片描述

  5. totalcurrent均为正整数,1 <= current <= total

  6. 上面效果演示是 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、通过按键实现移动控制

效果演示

在这里插入图片描述

有以下HTMLCSS

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,系统会随机生成classgamemn列表格(m >= 1, n >= 1),并随机选中一个td节点,请按照如下需求实现bind函数

  1. bind 函数为document绑定keydown事件,当系统触发上(键值38)下(键值40)左(键值37)右(键值39)按键时,请找到当前选中的td节点,并根据当前指令切换高亮节点,具体效果参考上面的效果演示。

  2. 在第一列往左移动则到达最后一列在最后一列往右移动则到达第一列在第一行往上移动则到达最后一行在最后一行往下移动则到达第一行

  3. 当前界面为系统在节点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题库非常贴合实际的,在写的过程中自己查漏补缺,收获了很多,强烈将牛客网推荐给大家!

如果本篇文章对你有所帮助,还请客官一件四连!❤️

基础不牢,地动山摇! 快来和博主一起来牛客网刷题巩固基础知识吧!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React 路由v6 - 超全详解

React router v6 路由 已经习惯了 v5 版本的路由 &#xff0c;那么 v6 版本的路由 该怎么应用呢&#xff1f; 文章目录React router v6 路由Ⅰ、路由 v6 (两种形式)Ⅱ、 动态路由Ⅲ、路由重定向Ⅳ、路由跳转 (两种形式)Ⅴ、路由懒加载Ⅰ、路由 v6 (两种形式) 方案一 &#xff…

JS原生——编写简易计算器

一个非常适合新手练习的小案例&#xff01;&#xff01;&#xff01; 使用JS的ES5语法HTMLCSS及企业级代码规范&#xff0c;方便后续良好的代码习惯养成&#xff01;&#xff01;&#xff01; 先来看一下样式吧&#xff01;&#xff01;&#xff01;&#xff08;后附代码&…

组件通信的6种方式

什么是组件通信 vue组件中关系说明: 如上图所示, A与B、A与C、B与D、C与E组件之间是父子关系&#xff1b; B与C之间是兄弟关系&#xff1b;A与D、A与E之间是隔代关系&#xff1b; D与E是堂兄关系&#xff08;非直系亲属&#xff09; 针对以上关系我们归类为&#xff1a; 父…

前端跨域解决方案

文章目录1.同源政策2.跨域解决方案2.1 CORS普通跨域请求&#xff1a;只需服务端设置Access-Control-Allow-Origin即可携带cookie跨域请求&#xff1a;前后端都需设置2.2 JSONP原理缺点数据格式jsonp跨域实现2.3 postMessage跨域2.4 WebSocket属性&#xff1a;事件&#xff1a;使…

vue3+vite:本地代理,配置proxy

一、项目&#xff1a;uniappvue3vitets 二、配置文件在vite.config.ts proxy: {/snow: { // 匹配请求路径&#xff0c;localhost:3000/snowtarget: https://www.snow.com/, // 代理的目标地址changeOrigin: true, // 开发模式&#xff0c;默认的origin是真实的 origin:localh…

压缩gltf/glb模型踩坑与解决 three.js DRACOLoader

前言 使用前端three.js加载3d模型过程中&#xff0c;往往会出现模型大小过大导致前端加载时间过长&#xff0c;降低用户体验。 本文所记录的是笔者在使用gltf-pipeline压缩3d模型中踩坑DRACOLoader与解决的一个过程。 所采用的three库版本为 ^0.138.2 解决方案与介绍 通过g…

31.JavaScript数组进阶,一网打尽数组操作函数slice、filter、map、reduce、some、every、find、splice

文章目录数组进阶元素删除&#xff08;对象方式&#xff09;splice()删除一个元素删除多个元素截断数组元素替换元素插入返回值负索引slice()concat()forEach()indexOf、lastIndexOf、includesfind、findIndexfiltermapsortreversestr.split()和arr.join()reduce、reduceRightA…

vue在html标签 {{}} 中调用函数的方法

目录 一、问题 1&#xff09;实现上述需求&#xff1a;有两种方式 2&#xff09;两种实现方式对比&#xff1a; 二、解决方法&#xff08;在html渲染时调用函数&#xff09; 三、总结 注&#xff1a;不想仔细看的&#xff0c;可以直接看有颜色的及代码哟 一、问题 1.在ht…

关于 HbuilderX 运行项目到手机,搜索不到手机解决

注意 本文内&#xff0c;我的 HbuilderX 安装目录都是在 D:\app 目录下&#xff0c;所有关于本文的操作文件都是在 HbuilderX 安装包内。 第一步&#xff1a;打开环境变量&#xff0c;找到系统变量&#xff0c;然后点击编辑。 第二部&#xff1a;配置 HbuilderX 的 adbs 目录…

JS中的位运算

目录 JS中的位运算 JS中的与运算 JS中的或运算 JS中的否&#xff08;非&#xff09;运算 计算机中负数的存储方式 JS中的异或运算 JS中位运算的应用场景 位的叠加&#xff08;开关&#xff09; JS中的位移运算 左位移 右位移 全右位移 首先了解一下什么是位运算 位…

Vite 配置篇:日常开发掌握这些配置就够了!

不知道有没有这样的兄弟&#xff0c;学习 Vite 的时候&#xff0c;官网上各种配置看的是眼花缭乱。不知道哪些需要掌握&#xff0c;哪些只用简单了解一下。为了提高大家的效率&#xff0c;我把项目中常用的配置梳理了一下分享给大家&#xff0c;希望对你上手 Vite 有所帮助。话…

若依框架前端切换TagView时刷新问题

若依框架点击顶部tag切换时&#xff0c;永远都是刷新的。刷新问题两种情况&#xff1a;普通view切换时刷新及iFrame切换刷新 一、普通view切换时刷新 原因是view的name与在菜单填写的大小写不一致&#xff0c;按若依框架规则&#xff0c;路由地址必须写为 camel 驼峰命名形式&…

前端:Tomcat服务器部署Web项目

文章目录1.1 C/S架构1.2 B/S架构2.1 服务器2.2 常见服务器3.1 Tomcat安装3.2 Tomcat使用3.3 Tomcat配置3.4 Tomcat项目部署4.1 Servlet技术4.2 Servlet配置4.3 配置测试4.4 Servlet部署5.1 IDEA部署1.1 C/S架构 Client / Server客户端/服务器 客户端作为独立程序 图形效果较好…

【面试题】面试官: Vue如何实现权限管理?

我正在参加「掘金启航计划」 一、权限管理 权限管理就是让不同的用户只能访问自己权限内的资源&#xff0c;有以下几种 路由权限&#xff0c;用户登录后只能看到自己权限内的导航菜单&#xff0c;且只能访问自己权限内的路由地址视图权限&#xff0c;用户只能看到自己权限内…

为你心仪的她做一个 “旋转木马“告白相册【零基础纯 CSS3 实现】

&#x1f4b3; 效果展示&#xff1a; 旋转相册效果里面就不放女朋友的美照了防止虐狗 &#x1f970;&#x1f970;&#x1f970;&#xff0c;就用个前端技能树的图片代替哈&#xff0c;有需要大家自行替换。 &#x1f4b3; 源码获取&#xff1a; 源码我已经上传到了资源里&…

Django web开发(二) - Mysql数据库

文章目录Mysql数据库Mysql的安装(CentOS7)下载修改配置文件Mysql强制重置密码远程可登录数据库管理数据表的管理常用数据类型数据管理添加数据查询数据删除数据修改数据员工管理Python管理数据库添加数据查询数据删除数据修改数据案例: Flask Mysql案例: 查询所有用户Mysql数据…

Three.js 渲染glb,gltf模型(保姆级教程)

1.准备工作 将下列文件在three.js的包中找到&#xff0c;注意的是我这里使用的是模块化版本的&#xff0c;这里不知道模块化的&#xff0c;可以先去看一下es6的模块化。 控制器&#xff1a; OrbitControls.js 加载器&#xff1a;GLTFLoader.js 材质&#xff1a; RoomEnviron…

echarts折线图流动特效的实现(非平滑曲线)

1.实现效果 2.实现原理 echarts官网&#xff1a;series-lines 注意&#xff1a;流动特效只支持非平滑曲线&#xff08;smooth&#xff1a;false&#xff09; series-lines路径图&#xff1a; 用于带有起点和终点信息的线数据的绘制&#xff0c;主要用于地图上的航线&#xff…

若依框架:前端登录组件与图像验证码

在上一篇《若依框架&#xff1a;前端项目结构与初始页面渲染流程》中&#xff0c;我们探讨了与“vue.config.js文件配置、.env模式和环境变量配置、vue-router全局导航守卫配置、vue-router路由配置简介”相关的内容&#xff0c;书接上回&#xff0c;我们继续探讨若依前端项目的…

前端实现在线预览Word文件

简介 在项目中遇到了个需求&#xff0c;大致需求这样的&#xff1a;用户在上传文件前需要先预览一下内容&#xff0c;确认内容是否正确&#xff0c;正确的情况下才可以上传&#xff1b; 那么这里面会涉及到一个在上传前的文档的预览操作&#xff0c;下面就记录一下踩坑记录 d…