首页
统计
关于
Search
1
Sealos3.0离线部署K8s集群
1,314 阅读
2
类的加载
873 阅读
3
Spring Cloud OAuth2.0
861 阅读
4
SpringBoot自动装配原理
752 阅读
5
集合不安全问题
647 阅读
笔记
Java
多线程
注解和反射
JVM
JUC
设计模式
Mybatis
Spring
SpringMVC
SpringBoot
MyBatis-Plus
Elastic Search
微服务
Dubbo
Zookeeper
SpringCloud
Nacos
Sentinel
数据库
MySQL
Oracle
PostgreSQL
Redis
MongoDB
工作流
Activiti7
Camunda
消息队列
RabbitMQ
前端
HTML5
CSS
CSS3
JavaScript
jQuery
Vue2
Vue3
Canvas
React
Linux
容器
Docker
Containerd
Podman
Kubernetes
Python
FastApi
OpenCV
数据分析
牛牛生活
登录
Search
标签搜索
Java
CSS
mysql
RabbitMQ
JavaScript
Redis
OpenCV
JVM
Mybatis-Plus
Camunda
多线程
CSS3
Python
Canvas
Spring Cloud
注解和反射
Activiti
工作流
SpringBoot
ndarray
蘇阿細
累计撰写
459
篇文章
累计收到
4
条评论
首页
栏目
笔记
Java
多线程
注解和反射
JVM
JUC
设计模式
Mybatis
Spring
SpringMVC
SpringBoot
MyBatis-Plus
Elastic Search
微服务
Dubbo
Zookeeper
SpringCloud
Nacos
Sentinel
数据库
MySQL
Oracle
PostgreSQL
Redis
MongoDB
工作流
Activiti7
Camunda
消息队列
RabbitMQ
前端
HTML5
CSS
CSS3
JavaScript
jQuery
Vue2
Vue3
Canvas
React
Linux
容器
Docker
Containerd
Podman
Kubernetes
Python
FastApi
OpenCV
数据分析
牛牛生活
页面
统计
关于
搜索到
459
篇与
的结果
2026-02-03
React - classnames 优化类名控制、受控表单绑定、获取 DOM
classnames 优化类名控制该库可以通过条件动态控制 class 类名的显示,github:https://github.com/JedWatson/classnames1. 安装npm install classnames2. 使用import classNames from 'classnames' <li className="nav-sort"> {tabs.map((item) => ( <span key={item.type} className={classNames('nav-item', { active: type === item.type })} onClick={() => tabChangeHandler(item.type)} > {item.text} </span> ))} </li>受控表单绑定概念:使用 useState 控制表单的状态import { useState } from 'react' function App() { // 1. 通过 value 属性绑定 react 状态 const [inputVal, setInputVal] = useState('') // 2. 绑定 onChange 事件,通过事件参数(即输入框最新的值)反向修改 react 状态 return ( <div className="App"> <input type="text" value={inputVal} onChange={(e) => setInputVal(e.target.value)} ></input> </div> ) } export default App 获取 DOM通过 useRef 钩子函数实现:使用 useRef 创建 ref 对象在 DOM 可用时,通过创建的 xxxRef.current 拿到 DOM 对象import { useRef } from 'react' function App() { const inputRef = useRef(null) // 组件渲染完毕后获取 DOM const getDom = () => { console.dir(inputRef.current) } return ( <div className="App"> <input type="text" ref={inputRef}></input> <button onClick={getDom}>获取 DOM</button> </div> ) } export default App
2026年02月03日
2 阅读
0 评论
0 点赞
2026-02-01
React - 组件的样式处理
1. 内联样式(不推荐)<div style={{ color='red' }}>测试</div>2. class 类名控制.App { color: red }import './index.css' function App() { return ( <div className="App">测试</div> ) } export default App 3. 示例.test { color: plum; }import './index.css' const style = { color: 'lightBlue', fontSize: 20 } function App() { return ( <div className="App"> <div style={style}>行内样式</div> <div className="test">行内样式</div> </div> ) } export default App
2026年02月01日
2 阅读
0 评论
0 点赞
2026-01-31
React - useState
1. 基础使用useState 是 React 中的一个 Hook 函数,它允许我们向组件添加一个状态变量,从而控制/影响组件的渲染结果,注:状态变量一旦发生变化,组件的视图 UI 也会同步变化(数据驱动视图)// useState import { useState } from 'react' function App() { // 1. 调用 useState 添加状态变量 // count 状态变量 // setCount 修改状态变量的方法 const [count, setCount] = useState(0) // 2. 点击事件回调 const clickHandler = () => { setCount(count + 1) } return ( <div className="App"> <button onClick={clickHandler}>{count}</button> </div> ) } export default App 2. 修改状态的规则(1)状态不可变在 React 中,状态被认为是只读的,应秉持“替换它而不是修改它”的原则,直接修改状态不会触发视图的更新import { useState } from 'react' function App() { let [count, setCount] = useState(0) const clickHandler = () => { // setCount(count + 1) // 直接修改,值变化了,但不会触发视图的更新 count++ console.log('count:', count) } return ( <div className="App"> <button onClick={clickHandler}>{count}</button> </div> ) } export default App (2)修改对象状态对于对象类型的状态变量,应该始终传给 set 方法一个全新的对象来进行修改import { useState } from 'react' function App() { // 修改对象 const [form, setForm] = useState({ name: '孙笑川', age: 33 }) const changeForm = () => { setForm({ ...form, name: '药水哥', age: '30' }) } return ( <div className="App"> <p>姓名:{form.name}</p> <p>年龄:{form.age}</p> <button onClick={changeForm}>修改对象</button> </div> ) } export default App
2026年01月31日
2 阅读
0 评论
0 点赞
2026-01-31
React - 组件
概念:一个组件即用户界面的一部分,它有自己的逻辑和样式,如:Header、SiderBar、MainPage在 React 中,一个组件就是首字母大写(大驼峰)的函数,内部存放对应组件的逻辑和视图 UI,使用时把组件当成标签书写即可// 定义组件 const Button = () => { return <button>Click</button> } function App() { return ( <div className="App"> {/* 使用/渲染组件 */} <Button /> </div> ) } export default App
2026年01月31日
3 阅读
0 评论
0 点赞
2026-01-31
React - 事件绑定
1. 基础事件绑定语法:on + 事件名称 = { 事件处理方法/函数 }function App() { const clickHandler = () => { alert('事件绑定') } return ( <div className="App"> <button onClick={clickHandler}>Click</button> </div> ) } export default App 2. 使用事件对象参数function App() { const clickHandler = (e) => { alert('事件绑定') console.log('事件参数', e) } return ( <div className="App"> <button onClick={clickHandler}>Click</button> </div> ) } export default App 3. 传递自定义参数语法:绑定事件时改造为箭头函数(通过函数引用的方式实现),通过形参传递function App() { const clickHandler = (name) => { console.log('自定义参数', name) } return ( <div className="App"> <button onClick={() => clickHandler('孙笑川')}>Click</button> </div> ) } export default App 4. 同时传递事件对象和自定义参数语法:在绑定事件的位置传递事件实参 e,clickHandler 中声明形参,且需要注意参数的顺序function App() { const clickHandler = (name, e) => { console.log('自定义参数', name, '事件参数', e) } return ( <div className="App"> <button onClick={(e) => clickHandler('孙笑川', e)}>Click</button> </div> ) } export default App
2026年01月31日
3 阅读
0 评论
0 点赞
2026-01-27
React - 简介、JSX基础
一、搭建开发环境官网快速开始文档 - 创建一个 React 项目:https://18.react.dev/learn/creating-a-react-appnpx create-react-app react-demo npm start二、JSX 基础1. 概念JSX(JS的语法扩展)是JavaScript 和 XML(HTML)的缩写,表示在 js 代码中编写 HTML 模板结构,它是 React 中编写 UI 模板的方式2. 使用 js 表达式在 JSX 中可以通过大括号语法 {} 识别 js 中的表达式,如:变量、函数调用、方法调用等使用引号传递字符串使用 js 变量函数调用和方法调用使用 js 对象const index = 1 function getName() { return '孙笑川' } function App() { return ( <div className="App"> 这是 React Demo {/* 使用引号传递字符串 */} {'这是 React Demo'} {/* 使用 js 变量 */} {index} {/* 函数调用 */} {getName()} {/* 方法调用 */} {new Date().getDate()} {/* 使用js对象 */} <div style={{ color: 'red' }}>这是 React Demo</div> </div> ); } export default App; 3. 列表渲染const list = [ {id: '1', name: '孙笑川'}, {id: '2', name: '药水哥'}, {id: '3', name: '刘波'} ] function App() { return ( <div className="App"> {/* 渲染列表 */} <ul> {list.map(item => <li key={item.id}>{item.name}</li>)} </ul> </div> ); } export default App; 4. 条件渲染通过逻辑运算符、三元表达式实现基础的条件渲染const flag = true function App() { return ( <div className="App"> {/* 逻辑运算 */} {flag && <span>这是 span 标签</span>} {/* 三元运算 */} {!flag ? <span>这是 span 标签</span> : <p>这是 p 标签</p>} </div> ); } export default App; 5. 复杂条件渲染通过自定义函数 + if 判断语句实现const type = 1 // 0 1 2 function getType() { if (type === 0) { return <div>孙笑川</div> } if (type === 1) { return <div>药水哥</div> } if (type === 2) { return <div>刘波</div> } } function App() { return ( <div className="App"> {/* 复杂条件渲染 */} {getType()} </div> ); } export default App;
2026年01月27日
4 阅读
0 评论
0 点赞
2026-01-19
四、Podman - 网络
1. 简介Podman 管理的容器在进行网络连接时,非特权用户无法在主机上创建网络接口,默认是 slirp4netns,相比于特权用户而言缺少一部分功能,如:无法为容器分配 IP 地址;特权用户运行的容器默认网络模式是 netavark。防火墙当容器执行端口映射时,防火墙也会同步打开对应的端口,但当重新加载防火墙规则时,会删除 netavark iptables,导致容器丢失网络连接,Podman v3 提供了 podman network reload 命令来恢复对应设置,且无需重启容器。2. 桥接桥接指创建一个内部网络,容器和主机都连接到该网络,以此实现容器与外部主机通信Podman 默认使用桥接模式,同时也提供了一个默认的桥接网络,从 4.0 版本开始,非特权用户运行的容器也可以使用 netavark(但不提供默认配置)从旧版本 CNI 切换到 netavark 时,需执行 podman system reset --force 命令,该命令会删除所有的镜像、容器和自定义网络rootless 容器的网络操作是在一个额外的命名空间内执行的,可以通过 podman unshare --rootless-netns 命令加入3. 默认Netavark 是纯内存网络,由于需要向后兼容 Docker,因此不支持 DNS 解析,可通过以下命令修改对应的配置文件# 特权 podman network inspect podman | jq .[] > /etc/containers/networks/podman.json # 非特权 podman network inspect podman | jq .[] > ~/.local/share/containers/storage/networks/podman.json以特权和非特权为例,将服务暴露至主机外# 特权 sudo podman run -d --name webserver -p 8080:80 quay.io/libpod/banner 00f3440c7576aae2d5b193c40513c29c7964e96bf797cf0cc352c2b68ccbe66a # 非特权 podman run -d --name webserver --network podman1 -p 8081:80 quay.io/libpod/banner 269fd0d6b2c8ed60f2ca41d7beceec2471d72fb9a33aa8ca45b81dc9a0abbb12外部客户端可通过8080 或 8081 端口访问到对应的服务4. MacvlanPodman 必须以 root 身份才能操作 macvlan# 创建 macvlan,eth0 为主机的网络接口(与 Docker 的创建方式一致) sudo podman network create -d macvlan -o parent=eth0 macvlan_test macvlan_test # --subnet指定子网,不使用 DHCP(可选) sudo podman network create -d macvlan \ --subnet 192.168.123.0/24 \ --gateway 192.168.123.1 \ -o parent=eth0 \ macvlan_test # 使用 DHCP # 查看当前使用的网络后端 sudo podman info --format {{.Host.NetworkBackend}} # NetAvark 启用 DHCP(以systemd为例) sudo systemctl enable --now netavark-dhcp-proxy.socket # CNI 启用 DHCP(以systemd为例) sudo systemctl enable --now cni-dhcp.socket# 容器使用 macvlan sudo podman run -d --name webserver --network macvlan_test quay.io/libpod/banner 03d82083c434d7e937fc0b87c25401f46ab5050007df403bf988e25e52c5cc40 # 使用外部客户端访问 (outside_host): $ curl http://<容器分配到的ip> ___ __ / _ \___ ___/ /_ _ ___ ____ / ___/ _ \/ _ / ' \/ _ `/ _ \ /_/ \___/\_,_/_/_/_/\_,_/_//_/5. Slirp4netnsSlirp4netns 是 rootless 容器和 Pod 的默认网络配置,它的出现是因为非特权用户无法在主机上创建网络接口。Slirp4netns 会在容器的网络命名空间中创建一个 TAP 设备,并连接到用户模式 TCP/IP 协议栈非特权用户必须使用 1024 到 65535 端口,因为更低的端口需要 root 权限,可以使用以下方法调整默认的设置 sysctl net.ipv4.ip_unprivileged_port_startslirp4netns 网络模式下,容器与容器之间完全隔离,且没有虚拟网络,容器之间要进行通信时,需要使用与宿主机的端口映射,或者将它们放入同一个 Pod 中(即共享同一个网络命名空间)以两个 rootless 容器通信为例# 假设主机 ip 为 192.168.123.123 # 运行 rootless 容器 podman run -d --name webserver -p 8080:80 quay.io/libpod/banner 17ea33ccd7f55ff45766b3ec596b990a5f2ba66eb9159cb89748a85dc3cebfe0 # 运行另一个 rootless 容器,并执行 curl podman run -it quay.io/libpod/banner curl http://192.168.123.123:8080 # 外部客户端访问 (outside_host): $ curl http://192.168.123.123:8080 ___ __ / _ \___ ___/ /_ _ ___ ____ / ___/ _ \/ _ / ' \/ _ `/ _ \ /_/ \___/\_,_/_/_/_/\_,_/_//_/6. 容器与 Pod 之间的通信Podman Pod 中的所有容器共享同一个网络命名空间(即它们将具有相同的 IP 地址、MAC 地址和端口映射),Pod 中的容器之间可以使用 localhost 方便地进行通信如上图所示,该 Pod 中的 DB Container 和 Web Container 所属同一个网络命名空间下,他们之间可以通过 localhost:[port] 进行通信,也可以通过分配给 Pod 的 ip 进行寻址,在 DNS 服务可用时,也可以使用 dns name 进行通信(类似于 K8s 中的 Core DNS)。
2026年01月19日
8 阅读
0 评论
0 点赞
2026-01-15
三、Podman - 对镜像进行签名和分发
以 GNU Privacy Guard(GPG)密钥为例如果使用 Podman 在将镜像推送到镜像仓库前对其进行了签名,则拉取时的客户端必须配置为从远程服务器获取签名,未签名的镜像都将被拒绝1. 生成 GPG密钥gpg --full-gen-key # 验证密钥 gpg --list-keys xxx@gmail.com2. 拉取镜像# 拉取镜像 podman pull docker://docker.io/alpine:latest # 查看 podman images alpine REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/alpine latest e7b39c54cdec 4 weeks ago 8.74 MB # 自定义 tag(localhost:5000 为本地镜像仓库) sudo podman tag alpine localhost:5000/alpine3. 修改配置/etc/containers/registries.d/default.yaml default-docker: sigstore: http://localhost:8000 # 引用网络服务器进行签名读取 sigstore-staging: file:///var/lib/containers/sigstore # 引用文件路径进行签名写入4. 签名并推送镜像sudo -E GNUPGHOME=$HOME/.gnupg \ podman push \ --tls-verify=false \ --sign-by sgrunert@suse.com \ localhost:5000/alpine … Storing signatures推送镜像后,可以看到产生的新的可用签名ls /var/lib/containers/sigstore 'alpine@sha256=e9b65ef660a3ff91d28cc50eba84f21798a6c5c39b4dd165047db49e84ae1fb9'5. 自定义本地8000端口服务bash -c 'cd /var/lib/containers/sigstore && python3 -m http.server' Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...6. 强制签名要求配置nano /etc/containers/policy.json { "default": [{ "type": "insecureAcceptAnything" }], "transports": { "docker": { "localhost:5000": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "/tmp/key.gpg" } ] } } }# 将 GPG 密钥放置到 keyPath 目录下 gpg --output /tmp/key.gpg --armor --export xxx@gmail.com7. 拉取测试# 先删除本地已经拉取的 alpine 镜像 podman rmi docker.io/alpine localhost:5000/alpine # 重新拉取 podman pull --tls-verify=false localhost:5000/alpine此时在8000端口的服务日志中可以看到访问签名的日志8. 错误配置示例keyPath 路径配置错误,在拉取镜像时会报错sudo podman pull --tls-verify=false localhost:5000/alpine Trying to pull localhost:5000/alpine... Error: pulling image "localhost:5000/alpine": unable to pull localhost:5000/alpine: unable to pull image: Source image rejected: Invalid GPG signature: ......
2026年01月15日
9 阅读
0 评论
0 点赞
1
2
...
58