【React】classnames 优化类名控制

1. 介绍

classnames是一个简单的JS库,可以非常方便的通过条件动态的控制class类名的显示
ClassNames是一个用于有条件处理classname字符串连接的库
简单来说就是动态地去操作类名,把符合条件的类名粘在一起
在这里插入图片描述

现在的问题:字符串的拼接方式不够直观,也容易出错
在这里插入图片描述

2. 安装

npm install classnames

3. 引入

在nodejs里引入

var classNames = require('classnames');

在js里引入

import classnames from 'classnames'

基本使用

普通字符串粘合

将参数拼接为字符串,中间用空格分开

classNames('foo', 'bar'); // => 'foo bar'

带条件的类参数

这里第二个参数是对象类型,键值为true,则粘合进classname里

classNames('foo', { bar: true }); // => 'foo bar'

若为false,则不粘进去

classNames('foo', { bar: false }); // => 'foo'

参数类型是数组

var arr = ['b', { c: true, d: false }];
classNames('a', arr); // => 'a b c'

特别注意

null和undefiend会被忽略

classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'

在react中优雅地使用classnames

下面这段代码,通过if-else判断state的状态,动态选择btnClass的具体值

class Button extends React.Component {
  // ...
  render () {
    var btnClass = 'btn';
    if (this.state.isPressed) btnClass += ' btn-pressed';
    else if (this.state.isHovered) btnClass += ' btn-over';
    return <button className={btnClass}>{this.props.label}</button>;
  }
}

现在用classnames来做,btnClass就可以边成一个对象,通过键值的条件确定最终生成的classname

import classnames from 'classnames'

class Button extends React.Component {
  // ...
  render () {
    var btnClass = classnames({
      btn: true,
      'btn-pressed': this.state.isPressed,
      'btn-over': !this.state.isPressed && this.state.isHovered
    });
    return <button className={btnClass}>{this.props.label}</button>;
  }
}

我的使用

import classnames from 'classnames'

 <li className="nav-sort">
            {/* 高亮类名: active */}
            {tabsList.map((item,index)=>
            <span className={classnames('nav-item',{active:item.type===type})}
            key={index} onClick={()=>{changTab(item.type)}} >{item.text}</span>)}
            {/* {tabsList.map((item,index)=>
            <span className={`nav-item ${item.type===type && 'active'}`} 
            key={index} onClick={()=>{changTab(item.type)}} >{item.text}</span>)} */}
          </li>

原理

classNames源码:

function classNames() {
  var classes = [];//用于存储生成的类名

  for (var i = 0; i < arguments.length; i++) {//遍历classnames的所有参数
    var arg = arguments[i];
    if (!arg) continue;

    var argType = typeof arg; //拿到每一个参数的类型

    if (argType === "string" || argType === "number") { //如果是字符串或数字就直接加到classes数组里
      classes.push(arg);
    } else if (Array.isArray(arg)) { //如果参数是数组,则将数组的值当作参数调用自己
      if (arg.length) {
        var inner = classNames.apply(null, arg);
        if (inner) {
          classes.push(inner);
        }
      }
    } else if (argType === "object") { //如果是对象且有自定义的toString方法,则调用toString方法添加到classes对象里,if里面的表达式下面会详细介绍
      if (
        arg.toString !== Object.prototype.toString &&
        !arg.toString.toString().includes("[native code]") 
      ) {
        classes.push(arg.toString());
        continue;
      }

      for (var key in arg) {
        if (hasOwn.call(arg, key) && arg[key]) { //如果键值为真就加进classes数组里
          classes.push(key);
        }
      }
    }
  }

  return classes.join(" ");// 最后在中间加上空格转成字符串
}

arg.toString !== Object.prototype.toString啥意思?

我们知道所有js对象都继承Object对象,即都继承toString方法,这个表达式的意思就是这个对象的toString方法不是继承自Object.prototype

arg.toString.toString().includes(“[native code]”) 啥意思?

我们首先要知道toString方法的一些知识:当我们对一个自定义函数调用toString()方法时,可以得到该函数的源代码;如果对内置函数使用toString()方法时,会得到一个’[native code]'字符串。因此,可以使用toString()方法来区分自定义函数和内置函数,注意是对函数调用toString()方法,所以我们通过对toString函数调用toString方法,就能得知这个toString是内置的,还是自定义的

这里两个表达式连起来的意思就是:现在这个类有toString方法,而且还是自定义的
  References

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VMware导入小白分享的MacOS版本之后,无法开机的解决方案

前言 这段时间陆续有小伙伴找到小白&#xff0c;说&#xff1a;导入小白分享的MacOS版本之后&#xff0c;出现无法开机的问题。 遇到这个问题&#xff0c;并不是说明分享版本有问题&#xff0c;因为大部分小伙伴导入之后都没有出现类似的问题&#xff0c;都是导入之后开机&…

记录项目使用ts时引入js文件后导致项目运行空白问题

主要原因&#xff1a; 使用ts后开启了eslint检测&#xff0c;而js压缩文件引入的位置在eslint检测的文件内。导致eslint检测认为该文件为很大的文件&#xff0c;或eslint认为此文件内存在无法处理的语法结构等问题。 解决方法&#xff1a; 1、把文件移到eslint检测外的文件引入…

居家实用类词汇,柯桥俄语培训

Посудомоечная машина 洗碗机 Холодильник 冰箱 Микроволновая печь 微波炉 Мультиварка 多功能电饭煲 Электронные весы для продуктов 食品电子秤 Электрическая мяс…

前端开发之中svg图标的使用和实例

svg图标的使用和实例 前言效果图1、安装插件2、vue3中使用2.1、 在components文件夹中,创建公共类SvgIcon/index.vue2.2、创建icons文件,存放svg图标和将所有的svg图标进行引用并注册成全局组件2.3、在man.js 中注册2.4、在vue.config.js中配置svg2.5、在vue中的调用svg图标3…

【JS实战03】学生信息的添加与删除

说明&#xff1a;本文章提供相应源码&#xff0c;需要到主页资源栏下载&#xff0c;并搭配源码看本文档&#xff1b;重点阐述每个JS模块实现过程中的重难点问题。 一&#xff1a;录入模块 1 渲染数据思路 减少DOM相关操作&#xff0c;避免因过多的DOM操作造成程序运行速度的…

计网总结☞物理层

五层协议体系结构->各层的功能有&#xff1a; 物理层 物理层的任务就是尽可能地屏蔽传输媒体的差异&#xff0c;透明地传送比特流&#xff08;注意&#xff1a;传递信息的物理媒体&#xff0c;如双绞线、同轴电缆、光缆等&#xff0c;是在物理层的下面&#xff0c;当做第 0…

【Vue】声明式导航-自定义类名(了解)

问题 router-link的两个高亮类名 太长了&#xff0c;我们希望能定制怎么办 解决方案 我们可以在创建路由对象时&#xff0c;额外配置两个配置项即可。 linkActiveClass和linkExactActiveClass const router new VueRouter({routes: [...],linkActiveClass: "类名1&quo…

WinForms 应用(.NET 8.0)使用ReportViewerCore.WinForms显示打印RDLC报表

在要WinForms 应用&#xff08;.NET 8.0&#xff09;中&#xff0c;显示RDLC报表&#xff0c;就要使用ReportViewerCore.WinForms。原来的ReportViewer只能在.NET Framework框架下运行。 1.ReportViewerCore.WinForms 程序包说明 SQL Server Reporting Services ReportViewer…

万字长文|OpenAI模型规范(全文)

本文是继《OpenAI模型规范概览》之后对OpenAI Model Spec的详细描述&#xff0c;希望能对各位从事大模型及RLHF研究的朋友有帮助。万字长文&#xff0c;建议收藏后阅读。 一、概述 在AI的世界里&#xff0c;确保技术的行为符合我们的期望至关重要。OpenAI最近发布了一份名为Mo…

Linux(Rocky)下 如何输入中文(切换中文输入法)教程

RockyLinux如何输入中文&#xff08;切换中文输入法&#xff09; 注意 在字符画界面的Linux系统中 默认不具备中文输入法的功能 需要SSH或其他远程工具来实现 问题 可能大家有的时候安装了一个虚拟机之后 想切换中文输入法 但是一直找不到方法 下面将利用Rocky9.2作为演示…

数学+思维,CF1056B - Divide Candies

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1056B - Codeforces 二、解题报告 1、思路分析 考虑i^2 j^2 | m 而m的余数有限&#xff0c;且m很小 我们枚举两重循环&#xff0c;都枚举m的余数&#xff0c;分别记为x&#xff0c;y 如果x ^ …

python Tk 获取输入框内容,分割内容

创建输入框、一个按钮和一个标签的GUI。 用户可以在输入框中输入文本&#xff0c;点击按钮后&#xff0c;程序将在控制台打印输入的文本&#xff08;已经分割为列表&#xff09;&#xff0c;并在GUI中的标签上显示一些静态文本。 import tkinter as tk# 创建主窗口 root tk.…

【模拟-BM99 顺时针旋转矩阵】

题目 BM99 顺时针旋转矩阵 描述 有一个NxN整数矩阵&#xff0c;请编写一个算法&#xff0c;将矩阵顺时针旋转90度。 给定一个NxN的矩阵&#xff0c;和矩阵的阶数N,请返回旋转后的NxN矩阵。 分析 模拟&#xff0c;写几个样例&#xff0c;分析一下新矩阵元素下标与原矩阵元素…

12c rac dg开启日志应用报错 ora-00313 ora-00312 ora-17503 ora-15012处理

错误 当备库开启日志应用后看到告警日志报大量ora-00313\ora-00312\ora-17503等错误 处理方法 SQL> alter database clear unarchived logfile group 1; alter database clear unarchived logfile group 1 * ERROR at line 1: ORA-01156: recovery or flashback in pro…

后台管理系统排序混乱,分页出现重复条例

检查了接口和请求参数都没有问题。 查询数据库发现是排序字段create_time 都相同导致的。没有区分度。 解决方案 按照唯一id排序 避免create_time 大批量相同 order by create_time &#xff0c;xxx 两个排序字段

MathType 7.8最新版核心功能特性 及免费汉化版安装包下载地址

大家好&#xff01;今天我要给大家种草一个非常实用的数学公式编辑器——MathType 7.8&#xff01;作为一名软件评测专家&#xff0c;我对这款软件进行了详细的测试和试用&#xff0c;下面来给大家分享一下我的使用体验。 我们来说说MathType 7.8的核心特性吧&#xff01;它是一…

Servlet基础(续集)

Servlet原理 Servlet是由Web服务器调用&#xff0c;Web服务器在收到浏览器请求之后&#xff0c;会&#xff1a; Mapping问题 一个Servlet可以指定一个映射路径 <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pa…

基于Texture2D 实现Unity 截屏功能

实现 截屏 Texture2D texture new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false); texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0); texture.Apply(); 存储 byte[] array ImageConversion.EncodeToPNG(texture); if (!…

腾讯元宝APP上线,AIGC产品的未来何去何从?

目录 腾讯元宝APP上线&#xff0c;AIGC产品的未来何去何从&#xff1f; 一、大模型AIGC产品概览 二、使用体验分享 1. 百度大脑 2. 阿里巴巴的AliMe 3. 字节跳动的TikTok AI 4. 腾讯元宝APP 小结 三、独特优势和倾向选择 1. 字节豆包 2. 百度文心一言 3. 阿里通义千…

SuntoryProgrammingContest2024(AtCoder Beginner Contest 357)(A~F)(最爱线段树的一集)

A - Sanitize Hands 题意&#xff1a; 模拟 // Problem: A - Sanitize Hands // Contest: AtCoder - SuntoryProgrammingContest2024&#xff08;AtCoder Beginner Contest 357&#xff09; // URL: https://atcoder.jp/contests/abc357/tasks/abc357_a // Memory Limit: 1024…