【JavaScript】JS实用案例分享:选择器组件 | 简易计算器

news2025/1/23 17:44:48

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


文章目录

  • 前言
  • 1、选择器组件
    • 效果演示
    • 案例需求
    • JavaScript实现
  • 2、简易计算器
    • 效果演示
    • 案例需求
    • JavaScript实现
  • 结语

前言

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

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

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

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

1、选择器组件

效果演示

在这里插入图片描述

有以下HTMLCSS

HTML结构

<div id="jsCheckGroup">
    <div class="checkgroup radius">
        <div data-val="a" class="item selected">选项a</div>
        <div data-val="b" class="item">选项b</div>
        <div data-val="c" class="item">选项c</div>
        <div data-val="d" class="item">选项d</div>
    </div>
</div>

CSS样式

.checkgroup .item{
    height: 42px;
    line-height: 42px;
    padding: 0 10px;
    margin: 10px 0;
    border: 1px solid #c7c7c7;
    border-radius: 6px;
}
.checkgroup.radius .item{
    border-radius: 21px;
}
.checkgroup .item.selected{
    border: 1px solid #08b292;
    background: #08b292;
    color: #ffffff;
}

案例需求

CheckGroup是一个选择组件类,支持单选多选选项参数格式、调用方式如下

  • 选项参数格式:

    var options = [{text: '选项a', value: 'a'}, {text: '选项b', value: 'b'}, {text: '选项c', value: 'c'}, {text: '选项d', value: 'd'}];
    
  • 实例化单选组件

    var item = new CheckGroup(document.getElementById('jsCheckGroup'), options);
    item.val(['a']);
    
  • 实例化多选组件

    var item = new CheckGroup(document.getElementById('jsCheckGroup'), options, true);
    item.val(['a']);
    

具体功能和需求如下:

  1. 单选组件请在 div.checkgroup 元素加上class radius
  2. 选中时,请在对应选项dom元素加上class selected
  3. 点击单选选项,如果未选中当前选项则选中当前选项并取消其他选项,否则取消当前选项。
  4. 点击多选选项,如果未选中当前选项则选中当前选项,否则取消当前选项。
  5. 给定的options中, textvalue属性的值均为非空字符串。
  6. val方法的参数和返回值均为数组(单选时数组长度不超过)。

JavaScript实现

// renderTo代表父容器,options为配置对象,isMultiple是否多选
function CheckGroup(renderTo, options, isMultiple) {
    var that = this;
    that.renderTo = renderTo;
    that.options = options;
    that.isMultiple = !!isMultiple;
    // 初始化模板
    that.initHtml();
    // 初始化事件
    that.initEvent();
}

// 挂载方法
CheckGroup.prototype.initHtml = fInitHtml;
CheckGroup.prototype.initEvent = fInitEvent;
CheckGroup.prototype.toggleEl = fToggleEl;
CheckGroup.prototype.isSelected = fIsSelected;
CheckGroup.prototype.val = fVal;

// 初始化模板
function fInitHtml() {
    var that = this;
    // 请补全代码,拼接html字符串
    var sHtml = `
    <div class="checkgroup${!that.isMultiple ? ' radius' : ''}">
        ${that.options.map(item => `<div data-val="${item.value}" class="item">${item.text}</div>`).join('')}
    </div>
        `
    that.renderTo.innerHTML = sHtml;
    // 请补全代码,获取checkgroup的dom元素引用
    that.el = document.getElementsByClassName('checkgroup')[0];
}

// 初始化事件
function fInitEvent() {
    var that = this;
    // 添加点击事件
    that.el && that.el.addEventListener('click', function (event) {
        var item = event.target;
        item.classList.contains('item') && that.toggleEl(item);
    });
}

// 点击事件处理函数
function fToggleEl(item) {
    // 根据当前是单选还是多选,以及当前元素是否选中,高亮/取消���亮指定的选项dom元素
    var that = this;
    if (that.isSelected(item)) {
        // 请补全代码
        // 当前元素以及被选中,则取消选中
        item.classList.remove('selected')
    } else if (that.isMultiple) {
        // 请补全代码
        // 多选时直接添加selected
        item.classList.add('selected')
    } else {
        // 请补全代码
        // 单选时先遍历取消所有的选中再选中当前元素
        var sel = that.el.getElementsByClassName('selected')[0]
        sel && sel.classList.remove('selected')
        item.classList.add('selected')
    }
}

// 判断item是否选中
function fIsSelected(item) {
    // 请补全代码,判断item是否选中
    // Element.classList 是一个只读属性,返回一个元素 class 属性的动态 DOMTokenList 集合。
    // DOMTokenList接口的 contains() 方法返回 Boolean (en-US) 类型。若传入的参数 token 包含在列表中时则返回true,否则返回 false。
    return item.classList.contains('selected');
}

// 设置/返回选中元素
function fVal(values) {
    var that = this;
    // 没有接受参数时该函数的作用是返回选中的数组
    if (arguments.length === 0) {
        // 请补全代码,获取高亮的选项元素
        var items = that.el.getElementsByClassName('selected');
        // 请补全代码,获取高亮的选项元素的data-val
        return [].map.call(items, item => item.getAttribute('data-val'))

    }
    // 接收参数时,该函数表示设置选中
    !that.isMultiple && values.length > 1 && (values.length = 1);
    // 请补全代码,获取所有的选项元素
    var its = that.el;
    // 请补全代码,在指定元素上加上高亮的class
    values.forEach(val => {
        let el = its.querySelector(`.item[data-val="${val}"]`);
        // 交给点击事件处理函数
        that.toggleEl(el);
    });
}


// 测试
var options = [{ text: '选项a', value: 'a' }, { text: '选项b', value: 'b' }, { text: '选项c', value: 'c' }, { text: '选项d', value: 'd' }];
// var item = new CheckGroup(document.getElementById('jsCheckGroup'), options);
// 多选
var item = new CheckGroup(document.getElementById('jsCheckGroup'), options, true);
item.val(['a', 'c']);
console.log(item.val());

这个案例中多次用到call来改变方法的this指向,因为获取的DOM集合是一种伪数组并不是真正的数组,不具有数组的方法,所以我们想要在它上面使用数组的方法时就需要先在一个确定的数组上调用方法再通过call将方法的this指向到它。

知识点:

  • 修改this指向callbindapply方法的使用,在前几期JS题解中我们对其讲解过,具体可见:https://ailjx.blog.csdn.net/article/details/126730075
  • Element.classList 是一个只读属性,返回一个元素 class 属性的动态 DOMTokenList 集合。
  • DOMTokenList.contains() 方法返回 Boolean 类型。若传入的参数包含在列表中时则返回true,否则返回 false

2、简易计算器

效果演示

在这里插入图片描述

有以下HTMLCSS

HTML结构

<div class="calculator">
    <header class="cal-header">简易计算器</header>
    <main class="cal-main">
        <div class="origin-value">0</div>
        <div class="cal-keyboard">
            <ul class="cal-items">
                <li data-action="num">7</li>
                <li data-action="num">8</li>
                <li data-action="num">9</li>
                <li data-action="operator">÷</li>
                <li data-action="num">4</li>
                <li data-action="num">5</li>
                <li data-action="num">6</li>
                <li data-action="operator">x</li>
                <li data-action="num">1</li>
                <li data-action="num">2</li>
                <li data-action="num">3</li>
                <li data-action="operator">-</li>
                <li data-action="num">0</li>
                <li data-action="operator">清空</li>
                <li data-action="operator">=</li>
                <li data-action="operator">+</li>
            </ul>
        </div>
    </main>
</div>

CSS样式

body, ul, li,select {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
ul,li {list-style: none;}
.calculator {
    max-width: 300px;
    margin: 20px auto;
    border: 1px solid #eee;
    border-radius: 3px;
}
.cal-header {
    font-size: 16px;
    color: #333;
    font-weight: bold;
    height: 48px;
    line-height: 48px;
    border-bottom: 1px solid #eee;
    text-align: center;
}
.cal-main {
    font-size: 14px;
}
.cal-main .origin-value {
    padding: 15px;
    height: 40px;
    line-height: 40px;
    font-size: 20px;
    text-align: right;
    overflow: hidden;
    text-overflow:ellipsis;
    white-space: nowrap;
}
.cal-main .origin-type,
.cal-main .target-type {
    padding-left: 5px;
    width: 70px;
    font-size: 14px;
    height: 30px;
    border: 1px solid #eee;
    background-color: #fff;
    vertical-align: middle;
    margin-right: 10px;
    border-radius: 3px;
}
.cal-keyboard {
    overflow: hidden;
}
.cal-items {
    overflow: hidden;
}
.cal-items li {
    user-select: none;
    float: left;
    display: inline-block;
    width: 75px;
    height: 75px;
    text-align: center;
    line-height: 75px;
    border-top: 1px solid #eee;
    border-left: 1px solid #eee;
    box-sizing: border-box;
}
li:nth-of-type(4n+1) {
    border-left: none;
}
li[data-action=operator] {
    background: #f5923e;
    color: #fff;
}
.buttons {
    float: left;
    width: 75px;
}
.buttons .btn {
    width: 75px;
    background-color: #fff;
    border-top: 1px solid #eee;
    border-left: 1px solid #eee;
    height: 150px;
    line-height: 150px;
    text-align: center;
}
.btn-esc {
    color: #ff5a34;
}
.btn-backspace {
    position: relative;
}

案例需求

本题展示了一个简化版的计算器,需求如下:

  1. 除法操作时,如果被除数为0,则结果为0。
  2. 结果如果为小数,最多保留小数点后两位,如 2 / 3 = 0.67(显示0.67), 1 / 2 = 0.5(显示0.5)。
  3. 阅读并根据提示补充完成函数initEventresultcalculate

JavaScript实现

var Calculator = {
    init: function () {
        var that = this;
        if (!that.isInited) {
            that.isInited = true;
            // 保存操作信息
            // total: Number, 总的结果
            // next: String, 下一个和 total 进行运算的数据
            // action: String, 操作符号
            that.data = { total: 0, next: '', action: '' };
            that.bindEvent();
        }
    },
    bindEvent: function () {
        var that = this;
        // 请补充代码:获取 .cal-keyboard 元素
        var keyboardEl = document.getElementsByClassName('cal-keyboard')[0];
        keyboardEl && keyboardEl.addEventListener('click', function (event) {
            // 请补充代码:获取当前点击的dom元素
            var target = event.target;
            // 请补充代码:获取target的 data-action 值
            var action = target.getAttribute('data-action');
            // 请补充代码:获取target的内容
            var value = target.innerText;
            if (action === 'num' || action === 'operator') {
                that.result(value, action === 'num');
            }
        });
    },
    result: function (action, isNum) {
        var that = this;
        var data = that.data;
        if (isNum) {
            data.next = data.next === '0' ? action : (data.next + action);
            !data.action && (data.total = 0);
        } else if (action === '清空') {
            // 请补充代码:设置清空时的对应状态
            data.total = 0;
            data.next = '';
            data.action = '';
        } else if (action === '=') {
            if (data.next || data.action) {
                data.total = that.calculate(data.total, data.next, data.action);
                data.next = '';
                data.action = '';
            }
        } else if (!data.next) {
            data.action = action;
        } else if (data.action) {
            data.total = that.calculate(data.total, data.next, data.action);
            data.next = '';
            data.action = action;
        } else {
            data.total = +data.next || 0;
            data.next = '';
            data.action = action;
        }

        // ���补充代码:获取 .origin-value 元素
        var valEl = document.getElementsByClassName('origin-value')[0];
        valEl && (valEl.innerHTML = data.next || data.total || '0');
    },
    calculate: function (n1, n2, operator) {
        n1 = +n1 || 0;
        n2 = +n2 || 0;
        if (operator === '÷') {
            // 请补充代码:获取除法的结果
            if (n2 === 0) {
                return 0
            }
            let tol = n1 / n2
            // Number.isInteger() 方法用来判断给定的参数是否为整数。
            // Math.round() 函数返回一个数字四舍五入后最接近的整数。
            return Number.isInteger(tol) ? tol : Math.round(tol * 100) / 100;
        } else if (operator === 'x') {
            // 请补充代码:获取乘法的结果
            let tol = n1 * n2
            return Number.isInteger(tol) ? tol : Math.round(tol * 100) / 100;
        } else if (operator === '+') {
            // 请补充代码:获取加法的结果
            let tol = n1 + n2
            return Number.isInteger(tol) ? tol : Math.round(tol * 100) / 100;
        } else if (operator === '-') {
            // 请补充代码:获取减法的结果
            let tol = n1 - n2
            return Number.isInteger(tol) ? tol : Math.round(tol * 100) / 100;
            return 0;
        }
    }
};
Calculator.init();

这个案例的实现并不难,牛客上面已经把大致的骨架写好了,我们只需按照要求在需要补充的地方进行补充就行,这就使难度大大降低了,我们需要做的不只是补充代码,还要去学习这个案例实现的思想,逻辑以及代码结构,个人认为牛客给出的这个解法的代码结构还是比较好的,具有学习意义,我们不能盲目的去写代码,要学会去提高自己的思维。

知识点:

  • Number.isInteger() 方法用来判断给定的参数是否为整数。
  • Math.round() 函数返回一个数字四舍五入后最接近的整数。

结语

这篇文章的所有内容都出自于牛客网的JS篇题库:
在这里插入图片描述

牛客网的JS题库非常贴合实际的,在写的过程中自己查漏补缺,收获了很多,强烈将牛客网推荐给大家!

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

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

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

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

相关文章

Axure RP9使用指南

1、快捷键 选中图层移动到上一层 ctrl [ 选中图层移动到下一层 ctrl ] 选中图层移动到顶层 ctrl shift [ 选中图层移动到底层 ctrl shift ] 合并为一组 ctrl G 取消合并 ctrl shift G 锁定位置和尺寸 ctrl K 解锁 ctrl shift K 拖动页面可以按住空格再通过鼠标拖动…

CSS实现文字颜色渐变

三行代码即可实现&#xff1a; background: linear-gradient(to bottom, #ffff, #f8fdff, #acf5ff, #67eeff, #24d8ff);-webkit-background-clip: text;color: transparent; 一 先设置背景颜色渐变 background 渐变属性可选值&#xff1a; 1 linear-gradient 为线性渐变…

JavaScript的节点操作 —— 增加节点

目录 JavaScript中的节点操作分为&#xff1a;增、删、改、查&#xff08;获取&#xff09;&#xff0c;四大类型。 我们直接利用案例来学习&#xff1a; HTML布局代码&#xff1a; JavaScript代码实现&#xff1a; 第一步&#xff1a;获取所有要用到的元素对象&#xff…

Vue3中toRef以及toRefs的基本使用

toRef以及toRefs 作用:创建一个ref对象&#xff0c;其value值指向另一个对象中的某个属性。 语法&#xff1a;const name toRef(obj,name) 应用&#xff1a;要将响应式对象中的某个属性单独提供给外部使用时 拓展:toRefs与toRef功能一致&#xff0c;但可以批量创建多个ref对…

vue报错 Error in render: “TypeError: Cannot read properties of undefined (reading ‘nickname‘)“

起因&#xff1a;我用axios请求数据&#xff08;可以看见数据了&#xff0c;已经请求成功的&#xff09;&#xff0c;最后加载在模板上&#xff08;页面模板上有内容&#xff09;&#xff0c;但是控制台出现了一个奇怪的错误 在created()钩子函数请求接口并报错数据&#xff0…

css 如何实现文本竖排、横排展示

writing-mode 该属性定义了文本在水平或垂直方向上如何排布 writing-mode:horizontal-tb | vertical-rl | vertical-lr | sideways-rl | sideways-lr接下来和我一起看看各个属性值的用法吧&#xff01;Go! <style>.root {border: 1px solid green;width: 400px;height: 4…

Vue内置组件的component标签

component标签&#xff1a;它的用途是可以动态绑定我们的组件,根据数据不同更换不同的组件. 有一个is属性&#xff0c;is的作用就是显示指定的组件 官方说明&#xff1a;渲染一个“元组件”为动态组件。依 is 的值&#xff0c;来决定哪个组件被渲染 使用方式也很简单&#xf…

nvue基础快速入门

一、uniapp连接手机 1、用USB让手机和电脑连接 2、点击3---8次手机版本信息打开开发者模式 3、在更多设置里面找到开发者选项 4、打开USB调试和允许手机可以USB安装&#xff0c;以及不要让手机只允许充电&#xff0c;要打开文件传输模式&#xff08;在手机消息栏里面会有提示…

前后端交互流程

1.前后端交互: 前后端交互&#xff0c;也可以理解为数据交互。前端需要获取&#xff08;GET&#xff09;的数据获取上传&#xff08;POST&#xff09;的数据&#xff0c;要通过 请求 来完成的&#xff0c;前端发送请求&#xff0c;后端接收到请求后&#xff0c;便进行对数据库…

若依移动端Ruoyi-App——引入uview2.0开发项目

1. 背景&#xff1a; 若依移动端Ruoyi-App只有个人中心&#xff0c;登录&#xff0c;其他模块都是建设中&#xff0c;因uniapp本身样式不够美观&#xff0c;所以本文基于ruoyi移动端引入uview2.0&#xff0c;实现基本功能。 RuoYi-App: &#x1f389; RuoYi APP 移动端框架&am…

element plus 的表单form使用详解

首先在你需要使用form组件的Vue文件里引入 import type { FormInstance } from element-plus 拿这一张图解释一下属性&#xff0c;第一项ref"ruleFormRef",&#xff0c;ruleFormRef就是我们定义并使用各个属性的必要条件&#xff0c;const ruleFormRef ref<Form…

vue 项目启动失败 ‘webpack-dev-server‘ 不是内部或外部命令,也不是可运行的程序

报错描述 我使用命令 npm run dev 启动项目 报了下面的错。 webpack-dev-server 不是内部或外部命令&#xff0c;也不是可运行的程序 > webpack-dev-server --inline --progress --config build/webpack.dev.conf.js webpack-dev-server 不是内部或外部命令&#xff0c;也不…

Vue3 框架使用报错以及解决办法

1、TypeError: Failed to fetch dynamically imported module: 引入组件时&#xff0c;没有添加.vue后缀 或者引入的组建没有被使用 2、SyntaxError: The requested module /node_modules/_schart.js3.0.4schart.js/lib/sChart.min.js?v0343bb8c does not provide an export…

前后端分离项目,如何解决跨域问题?

跨域问题是前后端分离项目中非常常见的一个问题&#xff0c;举例来说&#xff0c;编程猫&#xff08;codingmore&#xff09;学习网站的前端服务跑在 8080 端口下&#xff0c;后端服务跑在 9002 端口下&#xff0c;那么前端在请求后端接口的时候就会出现跨域问题。 403 Forbidd…

在uniapp中获取可视区域的高度(uni.getSystemInfo)

前言在实际开发中我们会遇到不确定高度的情况&#xff0c;那么在uniapp中我们如何获取区域的高度呐&#xff1f;一起来看看吧使用到的&#xff1a;uni-app提供了异步(uni.getSystemInfo)和同步(uni.getSystemInfoSync)的2个API获取系统信息uni.getSystemInfo(OBJECT)异步获取系…

Google Chrome装到D盘的方法

1. 下载chrome安装包 Google Chrome 网络浏览器 2. 创建自定义安装目录 D:\Program Files\Google\Chrome 3. 创建个人数据目录 D:\Program Files\Google\PersonData 4. 创建chrome浏览器的默认安装目录&#xff08;目录中的文件删除掉&#xff09; C:\Program Files\Google …

手把手教你如何Vue项目打包dist文件并Tomcat发布【超级详细】

???作者&#xff1a;bug菌 博客&#xff1a;CSDN、掘金等 ??公众号&#xff1a;猿圈奇妙屋 ??特别声明&#xff1a;原创不易&#xff0c;转载请附上原文出处链接和本文声明&#xff0c;谢谢配合。 ??版权声明&#xff1a;文章里可能部分文字或者图片来源于互联网或者百…

React中CodeMirror插件的使用及封装

目录 一、CodeMirror是什么 二、React中CodeMirror的基本使用介绍 &#xff08;一&#xff09;引入CodeMirror 1. 安装CodeMirror插件 2.引入 CodeMirror 插件 &#xff08;二&#xff09;引入文件配置 &#xff08;三&#xff09;关键属性解读 1.value 2.mode 3.the…

Vue3 从零开始 搭建 简单 干净 的 后台管理系统

前言&#xff1a; 记得自己大二时&#xff08;2017年&#xff09;&#xff0c;想搭建一个后台管理系统&#xff0c;当时头脑想的是用原生JS写的。我肯定干不出来&#xff0c;后来乖乖用了当时比较流行的layui&#xff0c;就算现在也真的难以做下去。 这几天&#xff0c;有了需…

微信小程序如何将表单的数据发送到数据库,云开发,并实现将数据渲染到页面中

一、表单数据发送到数据库 1. 利用bindsubmit来写一个函数 <form bindsubmit"bindSubmit"><view class"form_border"><label>收件人名称:</label><input name"userName" auto-focus placeholder" 请填写收件…