React(一)


文章目录

  • 项目地址
  • 一、创建第一个react项目
  • 二、JSX语法
    • 2.1 生成列表
    • 2.2 大括号识别JS的表达式
    • 2.3 列表循环array
    • 2.4 条件判断以及假值显示
    • 2.5 复杂条件渲染
    • 2.6 事件监听和绑定
    • 2.7 使用Fregments返回多个根标签
    • 2.8 多条件渲染
    • 2.9 导出子组件
  • 三、组件
    • 3.1 设置组件
    • 3.2 props给子组件传递参数
    • 3.3 给props设置默认值
    • 3.4 给子组件传递children(div的children)
    • 3.5 父给子传递事件监听函数
    • 3.6 子组件传值给父组件
  • 四、State
    • 4.1修改数组的值(添加与删除)
    • 4.2 给setState传参
    • 4.3修改类的值(增删改)
      • 4.3.1 增加
      • 4.3.2 修改
      • 4.3.3 删
  • 五、表单处理事件
    • 5.1 表单的输入和保存(双向绑定)
    • 5.2 处理input,select,radio,checkbox
      • 5.2.1 input
      • 5.2.2 单选
      • 5.2.3 下拉
      • 5.2.4 多选
      • 5.2.5 合并表达的多个状态
      • 5.2.6 使用循环处理多个checkboxes
      • 5.2.7 表单整体提交处理与重置
      • 5.2.8 表单验证
  • 六、使用unEffect消除副作用(需要复习)
    • 6.1 执行副作用
    • 6.2 指定useEffect的执行时机
    • 6.3 清理副作用
    • 6.4 在useEffect()中执行异步


项目地址

  • 教程作者:SGG
  • 教程地址:
https://www.bilibili.com/video/BV1wy4y1D7JT/?spm_id_from=333.999.0.0&vd_source=791e6deaa9c8a56b1f845a0bc1431b71
  • 代码仓库地址:
  • 所用到的框架和插件:
Es6+ract
prettier
- vscode设置:bracket paris

一、创建第一个react项目

  1. 执行创建命令,创建名为react-basic的项目文件
npx create-react-app react-basic
  1. 进入到项目的根目录,开启react服务
npm start
  1. 核心流程:App被引入到了index.js里,然后被渲染到了public/index.html
    在这里插入图片描述

二、JSX语法

  1. JSX是react编写UI模板的方式,表示在JS里编写HTML模板解构;
  2. 他不是标准的js语言,浏览器本身不能识别,需要通过解析后才能在浏览器里运行;
  3. JSX中{}里嵌入的是表达式,有值的语句才是表达式
  4. 如果表达式有空,布尔值,undefined他是不会显示的
  5. 直接设置标签时,style必须使用对象设置
    在这里插入图片描述

2.1 生成列表

  • jsx自动将数组的元素在页面中显示
  • 使用array.map方法,循环列表,添加li
  • 生成列表的时候一定要个key
const arr  = ['猪八戒', '孙悟空', '唐僧', '沙和尚'];const App = () => {return (<div className="App"><ul>{arr.map(item =><li>{item}</li>)}</ul></div>);
}
  1. 使用for循环或者foreach
const arr  = ['猪八戒', '孙悟空', '唐僧', '沙和尚'];
const liList = [];arr.forEach(item => {item.push(<li key={item}>{item}</li>);
});

2.2 大括号识别JS的表达式

①只能识别表达式;②style必须以对象形式传入{{}}

function App() {return (<div className="App">this is a react app{/* 使用引号传递字符串 */}{'This fxx'}{/* 识别JS变量 */}{num}{/* 函数,直接显示方法的返回值 */}{getName()}{/* 方法调用 */}{new Date().toLocaleTimeString()}{/* 使用js对象,驼峰 */}<div style = {{color: 'red', fontSize: '50px'}}> this is a red div </div></div>)
}

2.3 列表循环array

①循环列表必须给Key值;②使用map循环

const list =[{id:'1001',name:'tom'},{id:'1002',name:'jerry'},{id:'1003',name:'kitty'}
]function App() {return (<div className="App">{list.map((item)=><li key={item.id}>{item.name}</li>)}</div>)
}export default App;

2.4 条件判断以及假值显示

只能用三元运算符或者&& || ! 条件表达式;不能使用if判断

  • 条件表达式:当为真,返回后面的表达式,假则返回前面的
const islogin = truefunction App() {return (<div className="App">{islogin ? <h2>欢迎回来</h2> : <h2>请登录</h2>}{islogin&&<h2>用户名:{list[0].name}</h2>}</div>)
}
  • jsx会将0和NaN 显示在页面上;其他得假值则为空

2.5 复杂条件渲染

  • 根据传来的listType,匹配不同的jsx的模板
const listType = 5//根据listTpye,返回不同的jsx模板
function getListType() {if (listType === 0) {return <div>单图模式</div>}else if (listType === 1) {return <div>两图模式</div>}else if (listType === 2) {return <div>多图模式</div>}else {return <div>默认模式</div>}
}
const islogin = truefunction App() {return (<div className="App">{getListType()}</div>)
}

2.6 事件监听和绑定

  • 执行流程:① React渲染时,先调用了handleclick("FXX"),该函数返回了一个未调用的函数;② 返回的函数,才是真正的被绑定在button上的函数;③ 当button被点击的时候,该返回的函数被触发;
  • 简单理解:handleclick("FXX") 在 渲染时候被执行,但是里面返回的函数,才是真正onclick执行的函数;
const handleclick = (name) => {return () => {alert(name);};
};function App() {return (<div className="App"><h1>hello world</h1><button onClick={handleclick("FXX")}>click me</button></div>);
}export default App;

2.7 使用Fregments返回多个根标签

  • react默认只能返回一个根标签,但是使用Fregments可以返回多个
function User() {return (<Fragment><p>用户名:张三</p><p>职业:前端工程师</p></Fragment>);
}

2.8 多条件渲染

  • 假如,需要从网络服务器请求一组数据,请求过程显示请求中,请求成功返回数据后,显示数据,这是一个副作用的例子
function App() {const [user, setUser] = useState();useEffect(() => {//使用setTimeout模拟请求延迟,3秒后返回用户数据setTimeout(() => {setUser({name: "张三",occupation: "前端工程师",});}, 3000);}, []);if (!user) {return <div className="loading">loading...</div>;}return (<main className="container"><p>用户名:{user.name}</p><p>职业:{user.occupation}</p></main>);
}

2.9 导出子组件

设置了从属关系,让解构更加明确

  1. 设置 组件导出
function Menu({ children }) {return <nav>{children}</nav>;
}function Item({ children }) {return <a href="#">{children}</a>;
}//表明item是Menu的一部分
Menu.Item = Item;export default Menu;
  1. 使用子组件
function App() {return (<Menu><Menu.Item>主页</Menu.Item><Menu.Item>关于</Menu.Item><Menu.Item>联系</Menu.Item></Menu>);
}

三、组件

  1. 独立的组件单独放在一个模块(文件夹)里
  2. 一个大组件和他的卫星组件,可以一起放在一个文件里的同级目录;

3.1 设置组件

在这里插入图片描述

  • PostListItem是组件名,里面文件夹是组件的样式和jsx
    index.js: 将需要做成组件的部分放入到function内部
import "./style.css";function PostListItem({blog}) {return (<div className="post" key={blog.id}><img src={blog.author.avatar} alt="" /><div className="postContainer"><p className="postContent">{blog.content}</p><div className="postMeta"><p className="postAuthor">{blog.author.name}</p><p className="postDate">{blog.publishDate}</p></div></div></div>);
}export default PostListItem;
  • 将该组件的css样式放入到style.css

3.2 props给子组件传递参数

  • 将需要传递的参数,值,array,类,当作参数传入组件;
      <div className="postList">{microBlogs.length > 0 ? (microBlogs.map((blog, index) => (<PostListItem blog={blog} key={blog.id} />))) : (<p>暂无微博</p>)}
  • 在组件中使用参数
import "./style.css";function PostListItem(props) {return (<div className="post"><img src={props.blog.author.avatar} alt="" /><div className="postContainer"><p className="postContent">{props.blog.content}</p><div className="postMeta"><p className="postAuthor">{props.blog.author.name}</p><p className="postDate">{props.blog.publishDate}</p></div></div></div>);
}export default PostListItem;
  • 组件在接受props的时,除了直接传递props外,还可以使用解构来接收,这样就不需要使用props.blog 来使用

3.3 给props设置默认值

①防止报错;②页面显示正常

  • 如果我们在传递列表或者类的过程中,没有内容,可能会导致页面报错;此时,我们需要传递默认值
function PostListItem({ blog = { author: "" } }) {return (<div className="post"><img src={blog.author.avatar} alt="" /><div className="postContainer"><p className="postContent">{blog.content}</p><div className="postMeta"><p className="postAuthor">{blog.author.name}</p><p className="postDate">{blog.publishDate}</p></div></div></div>);
}

注意:需要给blog里的.属性也设置默认值

3.4 给子组件传递children(div的children)

简单理解:由一对开合标签包裹的所有内容,就是children

  1. 通过给当前组件的props添加一个children方式,并且在组件内部,添加<div>{children}<div>的方式来接收这个结构;
  2. 传递结构的父组件,需要将单个标签<PostListItem/>,改为对标签<PostListItem>children<PostListItem/>,标签里的内容,就是children;
  • PostListItem组件:将<a></a>作为children传递给自己组件内部使用

在这里插入图片描述

  • 组件内部 使用传来的children
    在这里插入图片描述

3.5 父给子传递事件监听函数

  1. 该传递的好处是,父类的一些数据和处理,可以添加到onEdit这个函数内部,然后传给子组件使用;
  2. 该组件不光可以传递给Delete组件,还可以传递给,添加,编辑等,只要逻辑相同,都可以通过父组件传递给子组件
  1. 子组件接受一个父类传来的函数,注意一定是函数
    在这里插入图片描述
  2. 父组件,传递一个未执行的函数

在这里插入图片描述

  1. 子组件在接收到这个onEidt的函数时,可以添加一些自己的逻辑进入,重新编辑之后,再绑定到自己的onclick事件上;
    在这里插入图片描述

3.6 子组件传值给父组件

  1. 事件中只要将需要传递的参数放在子组件里的onClick方法里,并且父组件用action接受,就可以完成传递
  2. 理解:其实并不是子组件传值给了父组件,而是子组件调用了父类的方法,将自己的参数传递给了父组件的方法里,父组件这个方法里,可以将子组件传来的数据进行处理;

子组件

在这里插入图片描述

父组件

 <PostListItem blog={blog} key={blog.id}><EditAndDeleteonEdit={(action) => console.log(blog.id, action)}/></PostListItem>

四、State

  • 整个创建state的过程大概如下:
  1. 找到变化的元素,例如用户的输入框,点击加购后的列表显示等等
  2. 根据变化的元素设置state,例如用户输入框需要一个初始值为空的state,需要展示的是用户输入的内容,需要捕获和保存的变化是,用户输入完成之后的内容
  3. 创建处理变化的setState函数
  4. 将该处理变化的函数和变化的元素绑定在一起,用于捕获变化

4.1修改数组的值(添加与删除)

由于数组是引用类型,所以需要修改后传入新的数组,可以使用解构,也可以直接使用赋值新的数组给setState

解构给数组添加元素,先放原数组,在将新的元素添加

在这里插入图片描述

过滤数组中的值,返回一个新的数组,item是要删除的值

  function handleDelete(item) {setLIst(list.filter((v) => v !== item));}

4.2 给setState传参

我们如果想在onclick里事件给setState传递参数 ,就必须使用

<button onClick={() => handleClick(100)}>更改数组</button>

4.3修改类的值(增删改)

类也是引用类型,所以修改的方式也是使用解构

4.3.1 增加

  • 添加新的属性
setPerson({
...persion,
gender:})

4.3.2 修改

  • 修改旧的属性
setPerson({
...persion,
gender:})

4.3.3 删

  • 删除属性
const newPerson = {...Person};
delete newPerson.age;
setPerson(newPerson);
  • 使用解构,这里排除了age,只拿了newPerson
const {age,...newPerson} = person;
setPerson(newPerson);

注意:嵌套类和嵌套数组,一定要将内部嵌套的类型解构,否则直接修改,会判定没有变化

五、表单处理事件

onInput:实时的监听输入内容
onChange:失焦后才监听内容

5.1 表单的输入和保存(双向绑定)

  1. 用户输入的text框,需要一个state,来展示更改和保存更改单个推文的输入
  2. 当单个推文编辑完成后,需要将推文的发布事件,用户id,内容等,存储在另外一个state里,该state要在页面展示,和保存新的推文
  3. 当用户点击publish的时候,监听onClick,然后将单条推文添加
  1. 单条推文的用户输入逻辑
    在这里插入图片描述
  2. 点击publish后的推文列表逻辑

在这里插入图片描述
在这里插入图片描述

5.2 处理input,select,radio,checkbox

5.2.1 input

  • input标签
<label htmlFor="password">密码</label>
<input type="text" id="username" value={username} onChange={handleUsernameChange}  />
  • 设置state
const [username, setUsername] = useState("");function handleUsernameChange(e) {setUsername(e.target.value);}

5.2.2 单选

  • 单选:通过checked={gender === "male"} 来判断是否选择
        <fieldset id="gender"><input type="radio" id="male" name="gender" value="male" checked={gender === "male"} onChange={handleGenderChange} /><label htmlFor="male"></label>

5.2.3 下拉

  • 单选
 <label htmlFor="occupation">职业</label><select id="occupation"  value={occupation} onChange={handleOccupationChange} ><option value="">请选择</option><option value="frontend">前端</option><option value="backend">后端</option><option value="fullstack">全栈</option></select>

5.2.4 多选

多选的State和上面3个不一样,因为他涉及了array的添加和删除

在这里插入图片描述

5.2.5 合并表达的多个状态

  1. 定义统一的状态,放在一个实例中
  const [user, setUser] = useState({username: "",password: "",repeatPassword: "",gender: "",occupation: "",hobbies: [],});
  1. 合并事件处理函数
  function handleInputChange(e) {let { value, name, type } = e.target;if (type === "checkbox") {const { checked } = e.target;if (checked) {value = [...user.hobbies, value];} else {value = user.hobbies.filter((hobby) => hobby !== value);}}setUser({...user,[name]: value,});}
  1. 给标签添加name的属性,用来判断
        <label htmlFor="username">用户名</label><input name="username" type="text" id="username" value={user.username}  onChange={handleInputChange} />

5.2.6 使用循环处理多个checkboxes

  • 将多个复选框不同的地方放在一个数组中,循环数组
  const hobbies = [{ value: "programming", label: "编程" },{ value: "drawing", label: "绘画" },{ value: "music", label: "音乐" },];<fieldset id="hobbies">{hobbies.map((hobby) => (<Fragment><inputtype="checkbox"name="hobbies"value={hobby.value}id={hobby.value}onChange={handleInputChange}checked={user.hobbies.includes(hobby.value)}/><label htmlFor={hobby.value}>{hobby.label}</label></Fragment>))}</fieldset>

5.2.7 表单整体提交处理与重置

  1. 在form标签上添加事件处理
      <form onSubmit={handleFormSubmit}>
  1. 将提交的表单数据保存,阻止表单的跳转
  function handleFormSubmit(e) {e.preventDefault();console.log(user);}
  1. 给form添加一个onReset事件
      <form onSubmit={handleFormSubmit} onReset={handleFormReset}>

重置
4. 设置表单的初始状态

  const initialUser = {username: "",password: "",repeatPassword: "",gender: "",occupation: "",hobbies: [],};const [user, setUser] = useState(initialUser);
  1. 事件监听useState
  function handleFormReset() {setUser(initialUser);}

5.2.8 表单验证

  1. 创建一个状态来存储表达的错误
  const [formErrors, setFormErrors] = useState({});
  1. 定义校验规则
  const rules = {username: (value) => {if (value.length < 3 || value.length > 12) {return "用户名必须大于 3 且小于 12 个字符";}},password: (value) => {if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/.test(value)) {return "密码必须大于 8 个字符,且至少包含一个字母和数字";}},};
  1. 保存错误信息
    const error = rules[name] && rules[name](value);setFormErrors({...formErrors,[name]: error,});}
  1. 修改页面,添加错误显示
        {formErrors.username && (<span className="formError">{formErrors.username}</span>)}
  1. 在提交表单时,验证错误信息是否消除
  function handleFormSubmit(e) {e.preventDefault();for (let rule of Object.keys(rules)) {const error = rules[rule](user[rule]);if (error) {setFormErrors({...formErrors,[rule]: error,});return;}}console.log(user);}

六、使用unEffect消除副作用(需要复习)

组件发生数据获取、订阅、手动修改 DOM、日志记录等操作。

useEffect(() => {// 副作用逻辑return () => {// 清理逻辑(可选)};
}, [依赖数组]);

6.1 执行副作用

设置定时器,网络请求,各种异步操作都在useEffect里执行

  useEffect(() => {const id = setInterval(() => {setDateTime(new Date());}, 1000);console.log(id);}, []);

6.2 指定useEffect的执行时机

  • []内添加处触发的事件:当refresh的状态发生改变,触发useEffect
function App() {const [dateTime, setDateTime] = useState(new Date());const [refresh, setRefresh] = useState(0);useEffect(() => {setDateTime(new Date());}, [refresh]);return (<main className="container"><h1>{dateTime.toLocaleString("zh-CN")}</h1><button onClick={() => setRefresh(refresh + 1)}>刷新</button></main>);
}

6.3 清理副作用

function App() {const [dateTime, setDateTime] = useState(new Date());const [refresh, setRefresh] = useState(0);useEffect(() => {const id = setInterval(() => {setDateTime(new Date());}, 1000);console.log(id);//清理副作用return () => {clearInterval(id);console.log("清理了 id 为" + id + "的 interval");};}, []);useEffect(() => {setDateTime(new Date());}, [refresh]);return (<main className="container"><h1>{dateTime.toLocaleString("zh-CN")}</h1><button onClick={() => setRefresh(refresh + 1)}>校准</button></main>);
}

6.4 在useEffect()中执行异步

  • 需要将异步方法先定义成为一个函数,然后再useEffect里调用
function App() {const [dateTime, setDateTime] = useState(new Date());useEffect(() => {updateTime();}, []);async function updateTime() {await new Promise((resolve) => setTimeout(resolve, 3000));setDateTime(new Date());}return (<main className="container"><h1>{dateTime.toLocaleString("zh-CN")}</h1></main>);
}

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

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

相关文章

记录一下在原有的接口中增加文件上传☞@RequestPart

首先&#xff0c;咱声明一下&#xff1a; RequestBody和 MultipartFile 不可以 同时使用&#xff01;&#xff01;&#xff01; 因为这两者预期的请求内容类型不同。RequestBody 预期请求的 Content-Type 是 application/json 或 application/xml&#xff0c;而 MultipartFile …

HTTPSOK ---助力阿里云免费 SSL 证书自动续期

目前许多用户面临着 SSL 证书过期续期的难题&#xff0c;尤其是对于阿里云的 免费 SSL 证书&#xff0c;每三个月需要手动申请和更新。为了帮助用户更轻松地管理 SSL 证书&#xff0c;现推出了强大的 HTTPSOK 服务&#xff0c;为用户提供了更便捷的自动续期和管理解决方案。 什…

5G的SUCI、SUPI、5G-GUTI使用场景及关系

使用场景(来源于对23.501、23.502、33.501、23.003的理解) 1、UE初始注册时&#xff0c;根据HN Public Key把SUPI加密成SUCI&#xff0c;并发送初始注册请求 2、AMF转发SUCI给AUSF和UDM进行认证&#xff0c;并获取解密后的SUPI 3、AMF根据SUPI生成一个5G-GUTI&#xff0c;并保…

【微服务】Spring AI 使用详解

目录 一、前言 二、Spring AI 概述 2.1 什么是Spring AI 2.2 Spring AI 特点 2.3 Spring AI 带来的便利 2.4 Spring AI 应用领域 2.4.1 聊天模型 2.4.2 文本到图像模型 2.4.3 音频转文本 2.4.4 嵌入大模型使用 2.4.5 矢量数据库支持 2.4.6 数据工程ETL框架 三、Sp…

【jvm】方法区的理解

目录 1. 说明2. 方法区的演进3. 内部结构4. 作用5.内存管理 1. 说明 1.方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等数据。它是各个线程共享的内存区域。2.尽管《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分&#xff0c;但它却…

大数据-226 离线数仓 - Flume 优化配置 自定义拦截器 拦截原理 拦截器实现 Java

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

编译OpenCV的速度,家里和公司的电脑相差很大

这一段时间&#xff0c;研究OpenCV带ffmpeg的编译问题。然后发现&#xff0c;同样是虚拟机&#xff0c;编译速度&#xff0c;家里的电脑明显比公司慢多了。 都是在SSD上。虚拟机内存&#xff0c;家里是16G&#xff0c;公司是8G。CPU&#xff0c;家里是E5 2667&#xff0c;公司…

Qt 的 QThread:多线程编程的基础

Qt 的 QThread&#xff1a;多线程编程的基础 在现代应用程序中&#xff0c;尤其是需要处理大量数据、进行长时间计算或者进行 I/O 操作时&#xff0c;多线程编程变得至关重要。Qt 提供了一个功能强大且易于使用的线程类 QThread&#xff0c;可以帮助开发者在 Qt 应用程序中实现…

Java 线程池介绍与实践

文章目录 引言概念优势Java 中的线程池实现线程池的核心参数1. corePoolSize&#xff1a;核心线程数2. maximumPoolSize&#xff1a;最大线程数3. keepAliveTime&#xff1a;线程空闲时间4. unit&#xff1a;时间单位5. workQueue&#xff1a;任务队列6. threadFactory&#xf…

富格林:安全指正规防欺诈套路

富格林指出&#xff0c;在现货黄金投资操作中&#xff0c;有众多的投资技巧和投资方式&#xff0c;但其实并不是所有的都适用。投资者应该注意选择安全、可信的投资方式去规防欺诈套路。值得提醒的是&#xff0c;现货黄金虽然拥有很多获利的机会&#xff0c;但也有不少欺诈套路…

PyAEDT:Ansys Electronics Desktop API 简介

在本文中&#xff0c;我将向您介绍 PyAEDT&#xff0c;这是一个 Python 库&#xff0c;旨在增强您对 Ansys Electronics Desktop 或 AEDT 的体验。PyAEDT 通过直接与 AEDT API 交互来简化脚本编写&#xff0c;从而允许在 Ansys 的电磁、热和机械求解器套件之间无缝集成。通过利…

SpringBoot(二十六)SpringBoot自定义注解

注解在springboot日常开发中使用的频率是很高的,官方为我们提供了很多注解,比如:@Autowired、@GetMapping等…… 但是我们有些特定的需求官方提供的注解是没有的。我们可以自定义注解。 下面我们来了解一下自定义注解的过程。 一:元注解 Java为我们提供了几个元注解来自定…

DHTMLX-gantt组件显示不同的颜色

在 dhtmlxGantt 组件中&#xff0c;你可以通过自定义任务的颜色来显示不同的任务类型或状态。这通常通过配置任务的 color 属性来实现。你可以在初始化 Gantt 图表时或在动态添加任务时设置这个属性。 以下是一些常见的方法来为任务设置不同的颜色&#xff1a; 1. 初始化时设…

什么是迭代器?Python迭代器及其用法

迭代器是一种对象&#xff0c;它表示一个数据流&#xff0c;可以一次访问一个成员&#xff08;元素&#xff09;。 迭代器从集合的第一个元素开始访问&#xff0c;直到所有的元素被访问完结束。迭代器只能往前不会后退。 在Python中&#xff0c;迭代器是一个实现了迭代协议的…

什么是C++中的友元函数和友元类?

友元函数&#xff08;Friend Function&#xff09;和 友元类&#xff08;Friend Class&#xff09;是用于控制类的访问权限的机制。这允许特定的函数或类访问另一个类的私有成员和保护成员&#xff0c;打破了 C 的封装性规则。 友元函数 定义 友元提供了不同类的成员函数之间…

深入理解 CSS 属性 pointer-events: none

pointer-events 是 CSS 中一个用于控制元素响应鼠标事件&#xff08;或触摸事件&#xff09;的属性。 通过这个属性&#xff0c;我们可以控制元素是否能够接受鼠标事件&#xff0c;例如点击、悬停、拖动等。 其中&#xff0c;pointer-events: none 是 pointer-events 属性的一…

定时器(QTimer)与随机数生成器(QRandomGenerator)的应用实践——Qt(C++)

一、QTimer与QRandomGenerator &#xff08;一&#xff09;QTimer&#xff08;定时器&#xff09;[2] QTimer类为定时功能提供了一个高级编程接口。在使用QTimer时&#xff0c;实例化一个QTimer对象并将其timeout()发射信号与合适的信号槽相连接。通过调用QTimer的start()函数…

用redis的zset实现日榜,周榜,月榜

思路&#xff1a; 1.初始化一个月的数据&#xff1a; /*** 初始化一个月数据*/Testpublic void initMonthData(){//计算当前时间小时的keylong hourSystem.currentTimeMillis()/(1000*60*60);for(int i1;i<24*30;i){String key"W_hour"(hour-i);Random random new…

《MySQL 实战教程:从零开始到高手进阶》

当然可以。下面是一篇关于MySQL的学习指南&#xff0c;它适合初学者到中级用户&#xff0c;涵盖了MySQL的基础知识、安装步骤、基本命令以及一些高级功能。 MySQL 学习指南 1. 了解 MySQL MySQL 是一个关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;由瑞典…

通过shell脚本分析部署nginx网络服务

通过shell脚本分析部署nginx网络服务 1.接收用户部署的服务名称 [rootlocalhost xzy]# vim 1.sh [rootlocalhost xzy]# chmod x 1.sh [rootlocalhost xzy]# ./1.sh2.判断服务是否安装 已安装&#xff1b;自定义网站配置路径为/www&#xff1b;并创建共享目录和网页文件&…