当前位置: 首页 > news >正文

Ubuntu下QT操作Mysql数据库

本篇总结一下一下Ubuntu下QT操作Mysql数据库。

目录

1. 启动Mysql数据库服务器

2.查看QT支持的数据库驱动

3.连接数据库

4. 增加表和记录

5. 删除记录

6. 修改记录

7. 查询记录

8.完整代码和运行效果

常见错误总结:

(1) 数据库服务没启动报错信息

(2) 有QMYSQL驱动,连接数据缺失败


1. 启动Mysql数据库服务器

// 启动

sudo /etc/init.d/mysql start

// 重启

sudo /etc/init.d/mysql restart

// 关闭

sudo /etc/init.d/mysql stop

2.查看QT支持的数据库驱动

Qt SQL模块是Qt提供的一个访问数据库的接口,支持多种平台下使用不同类型的数据库,在这个过程中,数据库驱动起到了很大的作用,它负责与不同的数据库进行通信,有了数据库驱动,我们才能使用不同类型的数据库。

#include <QtSql/QSqlDatabase>// 查看支持的数据库驱动
qDebug() << QSqlDatabase::drivers();

3.连接数据库

QSqlDatabase db;
if(QSqlDatabase::contains("qt_sql_default_connection")) {db = QSqlDatabase::database("qt_sql_default_connection");
}
else {// 创建一个数据库连接,指定数据库驱动db = QSqlDatabase::addDatabase("QMYSQL");
}// 数据库连接需要设置的信息
db.setHostName("127.0.0.1"); // 数据库服务器IP,我用的是本地电脑
db.setDatabaseName("TestDB");// 数据库名
db.setUserName("root");// 用户名
db.setPassword("mysql");// 密码
db.setPort(3306);// 端口号// 连接数据库
bool ok = db.open();if (ok) {qDebug() << "连接成功";
}
else {qDebug() << "连接失败";
}

4. 增加表和记录

// 实例化QSqlQuery,用于执行sql语句
QSqlQuery query(m_db);
// 创建一个表
query.exec("create table newUser (id int primary key, username varchar(20))");
QSqlQuery query(m_db);
query.exec("INSERT INTO newUser (id, username) VALUES (1, 'Hello')");int userid = 2;
QString &&name = "张三";
query.prepare("INSERT INTO newUser (id, username) VALUES (:id, :username)");
query.bindValue(":id", userid);
query.bindValue(":username", name);
query.exec();query.exec("INSERT INTO newUser (id, username) VALUES (3, 'Andy')");
query.exec("INSERT INTO newUser (id, username) VALUES (4, '李四')");

5. 删除记录

QSqlQuery query(m_db);
query.prepare("DELETE FROM newUser WHERE username=:username");
query.bindValue(":username", "张三");
query.exec();

6. 修改记录

QSqlQuery query(m_db);
query.prepare("update newUser set username=:username WHERE id=:id");
query.bindValue(":id", 1);
query.bindValue(":username", "World");
query.exec();

7. 查询记录

  // 查询所有QString sql = "SELECT id, username FROM newUser" ; // 组装sql语句QSqlQuery query(m_db);                               // [1] 传入数据库连接query.exec(sql);                                   // [2] 执行sql语句while (query.next()) {                             // [3] 遍历查询结果qDebug() << QString("Id: %1, Username: %2").arg(query.value("id").toInt()).arg(query.value("username").toString());}// 查询指定记录QString username = "李四";sql = "SELECT * FROM newUser WHERE username='" + username + "'";query.exec(sql);        // [2] 执行sql语句while (query.next()) {  // [3] 遍历查询结果qDebug() << QString("Id: %1, Username: %2").arg(query.value("id").toInt()).arg(query.value("username").toString());}// 绑定数据查询username = "张三";sql = "SELECT * FROM newUser WHERE username=:username";query.prepare(sql);                     // [2] 使用名称绑定的方式解析 SQL 语句query.bindValue(":username", username); // [3] 把占位符替换为传入的参数query.exec();                           // [4] 执行数据库操作while (query.next()) {                  // [5] 遍历查询结果qDebug() << QString("Id: %1, Username: %2").arg(query.value("id").toInt()).arg(query.value("username").toString());}

8.完整代码和运行效果

qt_mysql.pro

#-------------------------------------------------
#
# Project created by QtCreator 2023-09-05T23:12:20
#
#-------------------------------------------------QT       += core gui
QT += sqlgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = qt_mysql
TEMPLATE = app# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0SOURCES += \main.cpp \mainwindow.cppHEADERS += \mainwindow.hFORMS += \mainwindow.ui

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QtSql/QSqlDatabase>
#include <QDebug>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void on_pushButton_3_clicked();void on_pushButton_4_clicked();void on_pushButton_5_clicked();void on_pushButton_6_clicked();void on_pushButton_7_clicked();void on_pushButton_clear_table_clicked();private:void createConnectionByName(const QString &connectionName); //使用自定义 connectionName 创建连接QSqlDatabase getConnectionByName(const QString &connectionName);  // 使用自定义 connectionName 获取连接private:Ui::MainWindow *ui;QSqlDatabase m_db;
};#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSqlQuery>/*
Qt SQL模块是Qt提供的一个访问数据库的接口,支持多种平台下使用不同类型的数据库,在这个过程中,
数据库驱动起到了很大的作用,它负责与不同的数据库进行通信,有了数据库驱动,我们才能使用不同类型的数据库。*/MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);// 创建名为 firstMysqlConnect 的数据库连接createConnectionByName("firstMysqlConnect");
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{// 查看支持的数据库驱动qDebug() << QSqlDatabase::drivers();
}//使用自定义 connectionName 创建连接
void MainWindow::createConnectionByName(const QString &connectionName){m_db = QSqlDatabase::addDatabase("QMYSQL", connectionName);// 数据库连接需要设置的信息m_db.setHostName("127.0.0.1"); // 数据库服务器IP,我用的是本地电脑m_db.setDatabaseName("TestDB");// 数据库名m_db.setUserName("root");// 用户名m_db.setPassword("mysql");// 密码m_db.setPort(3306);// 端口号// 连接数据库判断bool ok = m_db.open();if (ok){qDebug() << "连接成功";} else {qDebug() << "连接失败";}}// 使用自定义 connectionName 获取连接
QSqlDatabase MainWindow::getConnectionByName(const QString &connectionName) {// 获取数据库连接return QSqlDatabase::database(connectionName);
}void MainWindow::on_pushButton_2_clicked()
{QSqlDatabase db;if(QSqlDatabase::contains("qt_sql_default_connection")) {db = QSqlDatabase::database("qt_sql_default_connection");}else {// 创建一个数据库连接,指定数据库驱动db = QSqlDatabase::addDatabase("QMYSQL");}// 数据库连接需要设置的信息db.setHostName("127.0.0.1"); // 数据库服务器IP,我用的是本地电脑db.setDatabaseName("TestDB");// 数据库名db.setUserName("root");// 用户名db.setPassword("mysql");// 密码db.setPort(3306);// 端口号// 连接数据库bool ok = db.open();if (ok) {qDebug() << "连接成功";}else {qDebug() << "连接失败";}
}void MainWindow::on_pushButton_3_clicked()
{// 实例化QSqlQuery,用于执行sql语句QSqlQuery query(m_db);// 创建一个表query.exec("create table newUser (id int primary key, username varchar(20))");
}void MainWindow::on_pushButton_4_clicked()
{QSqlQuery query(m_db);query.exec("INSERT INTO newUser (id, username) VALUES (1, 'Hello')");int userid = 2;QString &&name = "张三";query.prepare("INSERT INTO newUser (id, username) VALUES (:id, :username)");query.bindValue(":id", userid);query.bindValue(":username", name);query.exec();query.exec("INSERT INTO newUser (id, username) VALUES (3, 'Andy')");query.exec("INSERT INTO newUser (id, username) VALUES (4, '李四')");
}void MainWindow::on_pushButton_5_clicked()
{QSqlQuery query(m_db);query.prepare("DELETE FROM newUser WHERE username=:username");query.bindValue(":username", "张三");query.exec();
}void MainWindow::on_pushButton_6_clicked()
{QSqlQuery query(m_db);query.prepare("update newUser set username=:username WHERE id=:id");query.bindValue(":id", 1);query.bindValue(":username", "World");query.exec();
}void MainWindow::on_pushButton_7_clicked()
{// 查询所有QString sql = "SELECT id, username FROM newUser" ; // 组装sql语句QSqlQuery query(m_db);                               // [1] 传入数据库连接query.exec(sql);                                   // [2] 执行sql语句while (query.next()) {                             // [3] 遍历查询结果qDebug() << QString("Id: %1, Username: %2").arg(query.value("id").toInt()).arg(query.value("username").toString());}// 查询指定记录QString username = "李四";sql = "SELECT * FROM newUser WHERE username='" + username + "'";query.exec(sql);        // [2] 执行sql语句while (query.next()) {  // [3] 遍历查询结果qDebug() << QString("Id: %1, Username: %2").arg(query.value("id").toInt()).arg(query.value("username").toString());}// 绑定数据查询username = "张三";sql = "SELECT * FROM newUser WHERE username=:username";query.prepare(sql);                     // [2] 使用名称绑定的方式解析 SQL 语句query.bindValue(":username", username); // [3] 把占位符替换为传入的参数query.exec();                           // [4] 执行数据库操作while (query.next()) {                  // [5] 遍历查询结果qDebug() << QString("Id: %1, Username: %2").arg(query.value("id").toInt()).arg(query.value("username").toString());}
}void MainWindow::on_pushButton_clear_table_clicked()
{QSqlQuery query(m_db);query.exec("DELETE FROM newUser");
}

main.cpp

#include "mainwindow.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}

mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"><class>MainWindow</class><widget class="QMainWindow" name="MainWindow"><property name="geometry"><rect><x>0</x><y>0</y><width>693</width><height>412</height></rect></property><property name="windowTitle"><string>MainWindow</string></property><widget class="QWidget" name="centralWidget"><layout class="QGridLayout" name="gridLayout"><item row="0" column="0"><widget class="QPushButton" name="pushButton"><property name="text"><string>查看数据库驱动</string></property></widget></item><item row="0" column="1"><widget class="QPushButton" name="pushButton_2"><property name="text"><string>连接mysql数据库</string></property></widget></item><item row="1" column="0"><widget class="QPushButton" name="pushButton_3"><property name="text"><string>创建表</string></property></widget></item><item row="1" column="1"><widget class="QPushButton" name="pushButton_4"><property name="text"><string>插入记录</string></property></widget></item><item row="2" column="0"><widget class="QPushButton" name="pushButton_5"><property name="text"><string>删除记录</string></property></widget></item><item row="2" column="1"><widget class="QPushButton" name="pushButton_6"><property name="text"><string>修改记录</string></property></widget></item><item row="3" column="0"><widget class="QPushButton" name="pushButton_7"><property name="text"><string>查询记录</string></property></widget></item><item row="3" column="1"><widget class="QPushButton" name="pushButton_clear_table"><property name="text"><string>删除表中所有数据</string></property></widget></item></layout></widget><widget class="QMenuBar" name="menuBar"><property name="geometry"><rect><x>0</x><y>0</y><width>693</width><height>39</height></rect></property></widget><widget class="QToolBar" name="mainToolBar"><attribute name="toolBarArea"><enum>TopToolBarArea</enum></attribute><attribute name="toolBarBreak"><bool>false</bool></attribute></widget><widget class="QStatusBar" name="statusBar"/></widget><layoutdefault spacing="6" margin="11"/><resources/><connections/>
</ui>

常见错误总结:

(1) 数据库服务没启动报错信息

(2) 有QMYSQL驱动,连接数据缺失败

原因:Qt对Mysql进行了封装,库名为libqsqlmysql.so,但是其还需要调用Mysql的客户端库才能真正连接数据库,如下可以看到libqsqlmysql.so需要依赖libmysqlclient.so.18。

相关文章:

Ubuntu下QT操作Mysql数据库

本篇总结一下一下Ubuntu下QT操作Mysql数据库。 目录 1. 启动Mysql数据库服务器 2.查看QT支持的数据库驱动 3.连接数据库 4. 增加表和记录 5. 删除记录 6. 修改记录 7. 查询记录 8.完整代码和运行效果 常见错误总结&#xff1a; (1) 数据库服务没启动报错信息 (2) 有…...

sqli --【1--10】

Less-1&#xff08;联合查询&#xff09; 1.查看是否有回显 2.查看是否有报错 3.使用联合查询&#xff08;字符注入&#xff09; 3.1判断其列数 3.2 判断显示位置 3.3敏感信息查询 Less-2&#xff08;联合查询&#xff09; 1.查看是否有回显 2.查看是否有报错 3.使用…...

《自然语言处理(NLP)的最新进展:Transformers与GPT-4的浅析》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

Wireshark 用命令行分析数据包

1&#xff0c;那些情况需要使用命令行 Wireshark一次性提供了太多的信息。使用命令行工具可以限制打印出的信息&#xff0c;最后只显示相关数据&#xff0c;比如用单独一行来显示IP地址。命令行工具适用于过滤数据包捕获文件&#xff0c;并提供结果给另一个支持UNIX管道的工具…...

LVS DR模式负载均衡群集部署

目录 1 LVS-DR 模式的特点 1.1 数据包流向分析 1.2 DR 模式的特点 2 DR模式 LVS负载均衡群集部署 2.1 配置负载调度器 2.1.1 配置虚拟 IP 地址 2.1.2 调整 proc 响应参数 2.1.3 配置负载分配策略 2.2 部署共享存储 2.3 配置节点服务器 2.3.1 配置虚拟 IP 地址 2.3.2…...

探讨前后端分离开发的优势、实践以及如何实现更好的用户体验?

随着互联网技术的迅猛发展&#xff0c;前后端分离开发已经成为现代软件开发的一种重要趋势。这种开发模式将前端和后端的开发工作分开&#xff0c;通过清晰的接口协议进行通信&#xff0c;旨在优化开发流程、提升团队协作效率&#xff0c;并最终改善用户体验。本文将深入探讨前…...

微博一面:JVM预热,你的方案是啥?

说在前面 在40岁老架构师 尼恩的读者社区(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如微博、阿里、汽车之家、极兔、有赞、希音、百度、网易、滴滴的面试资格&#xff0c;遇到一几个很重要的面试题&#xff1a; JVM预热&#xff0c;你的方案是啥&#xff1f;Springb…...

open与fopen的区别

1. 来源 从来源的角度看&#xff0c;两者能很好的区分开&#xff0c;这也是两者最显而易见的区别&#xff1a; open是UNIX系统调用函数&#xff08;包括LINUX等&#xff09;&#xff0c;返回的是文件描述符&#xff08;File Descriptor&#xff09;&#xff0c;它是文件在文件…...

Unity记录一些glsl和hlsl的着色器Shader逆向代码

以下内容一般基于 GLSL 300 之后 以下某些代码行&#xff0c;是“伪代码“&#xff0c;绝大部分是renderDoc 逆向产生标准代码 本人OpenlGL零基础&#xff0c;也不打算重头学 目录 Clip&#xff08;&#xff09; 剔除函数 discard; FS最终颜色输出 out 和最终颜色相加方程…...

基于Sentinel的微服务保护

前言 Sentinel是Alibaba开源的一款微服务流控组件&#xff0c;用于解决分布式应用场景下服务的稳定性问题。Sentinel具有丰富的应用场景&#xff0c;它基于流量提供一系列的服务保护措施&#xff0c;例如多线程秒杀情况下的系统承载&#xff0c;并发访问下的流量控制&#xff…...

Collectors类作用:

一、Collectors类&#xff1a; 1.1、Collectors介绍 Collectors类&#xff0c;是JDK1.8开始提供的一个的工具类&#xff0c;它专门用于对Stream操作流中的元素各种处理操作&#xff0c;Collectors类中提供了一些常用的方法&#xff0c;例如&#xff1a;toList()、toSet()、to…...

LASSO回归

LASSO回归 LASSO(Least Absolute Shrinkage and Selection Operator&#xff0c;最小绝对值收敛和选择算子算法)是一种回归分析技术&#xff0c;用于变量选择和正则化。它由Robert Tibshirani于1996年提出&#xff0c;作为传统最小二乘回归方法的替代品。 损失函数 1.线性回…...

机器学习中的 K-均值聚类算法及其优缺点。

K-均值聚类算法是一种常见的无监督学习算法&#xff0c;它可以将数据集分成 K 个簇&#xff0c;每个簇内部的数据点尽可能相似&#xff0c;而不同簇之间的数据点应尽可能不同。下面详细讲解 K-均值聚类算法的优缺点&#xff1a; 优点&#xff1a; 简单易用&#xff1a;K-均值…...

云计算与虚拟化

一、概念 什么是云计算&#xff1f; 云计算&#xff08;cloud computing&#xff09;是分布式计算的一种&#xff0c;指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序&#xff0c;然后&#xff0c;通过多部服务器组成的系统进行处理和分析这些小程序得到结果…...

Linux常见进程类别

目录 常见进程类别 守护进程&精灵进程 任务管理 进程组 作业 作业 | 进程组 会话 w命令 守护进程 守护进程的创建 setsid()函数 daemon()函数 模拟实现daemon函数 前台进程 | 后台进程 僵尸进程 | 孤儿进程 僵尸进程的一些细节 守护进程 | 后台进程 守护…...

智能小车之蓝牙控制并测速小车、wife控制小车、4g控制小车、语音控制小车

目录 1. 蓝牙控制小车 2. 蓝牙控制并测速小车 3. wifi控制测速小车 4. 4g控制小车 5. 语音控制小车 1. 蓝牙控制小车 使用蓝牙模块&#xff0c;串口透传蓝牙模块&#xff0c;又叫做蓝牙串口模块 串口透传技术&#xff1a; 透传即透明传送&#xff0c;是指在数据的传输过…...

指针进阶(一)

指针进阶 1. 字符指针面试题 2. 指针数组3. 数组指针3.1 数组指针的定义3.2 &数组名VS数组名 3.3 数组指针的使用4. 数组传参和指针传参4.1 一维数组传参4.2 二维数组传参4.3 一级指针传参4.4 二级指针传参 前言 指针的主题&#xff0c;我们在初级阶段的《指针》章节已经接…...

c# sql 判断表中是否包含指定字段

你可以使用以下方法来判断一个 SQL 数据库中的表是否包含指定的字段。 首先&#xff0c;你需要连接到数据库&#xff0c;然后执行一条 SQL 查询语句来检查表结构。你可以使用 SELECT 语句和 INFORMATION_SCHEMA.COLUMNS 系统视图来获取表中的所有列信息。 下面是一个示例代码…...

08-JVM垃圾收集器详解

上一篇&#xff1a;07-垃圾收集算法详解 如果说收集算法是内存回收的方法论&#xff0c;那么垃圾收集器就是内存回收的具体实现。 虽然我们对各个收集器进行比较&#xff0c;但并非为了挑选出一个最好的收集器。因为直到现在为止还没有最好的垃圾收集器出现&#xff0c;更加没…...

sql_mode详解

文章目录 一、sql_mode作用二、查询sql_mode三、mysql8默认的mode配置&#xff08;6个默认配置&#xff09;四、常见mode详细解释mysql8默认配置了的mode&#xff08;6个&#xff09;需要自己配置的mode&#xff08;4个&#xff09; 五、设置sql_mode&#xff08;一旦设置了&am…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

ubuntu22.04 安装docker 和docker-compose

首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

深入理解 React 样式方案

React 的样式方案较多,在应用开发初期,开发者需要根据项目业务具体情况选择对应样式方案。React 样式方案主要有: 1. 内联样式 2. module css 3. css in js 4. tailwind css 这些方案中,均有各自的优势和缺点。 1. 方案优劣势 1. 内联样式: 简单直观,适合动态样式和…...