react-问卷星项目(7)
实战
React表单组件
入门
重点在于change的时候改变state的值,类似vue的双向数据绑定v-model,即数据更新的时候页面同步更新,页面数据更新时数据源也能获得最新的值,只是Vue中设置在data中的属性默认绑定,React中需要state触发页面更新
使用原先较多测试组件的项目写基础
input组件
import React, { useState, ChangeEvent } from "react";
// 上下两种引入方式都可以
// import type { ChangeEvent } from "react";function App() {const [text, setText] = useState<string>("hello");function handleChange(event: ChangeEvent<HTMLInputElement>) {// event.target.value就是当前input的值setText(event.target.value);}return (<div><input defaultValue={text} onChange={handleChange} /><button onClick={() => console.log(text)}>打印</button></div>);
}export default App;
- 受控组件:值同步到state,使用value属性,可获可控
- 非受控组件:值不同步到state,使用defaultValue属性,能够设置默认值,但是无法获得更改后最新的数值
- React推荐使用受控组件,看似繁琐(没有规律),但更加可控(有规律,可读)
textarea组件
function App() {const [text, setText] = useState<string>("hello");function handleChange(event: ChangeEvent<HTMLTextAreaElement>) {// event.target.value就是当前input的值setText(event.target.value);}function genHtml() {return { __html: text.replaceAll("\n", "<br>") };}return (<div>{/* <input defaultValue={text} onChange={handleChange} /> */}<textarea value={text} onChange={handleChange}></textarea>{/* {text.replaceAll("\n", "<br>")} */}{/* 上面这个方法中为了防止XSS注入,React会将br换成明文展示在页面而不是换行,可以通过下列方式解决 */}<p dangerouslySetInnerHTML={genHtml()}></p></div>);
}export default App;
radio单选框
function App() {const [gender, setGender] = useState("male");function handleChange(event: ChangeEvent<HTMLInputElement>) {// event.target.value就是当前input的值setGender(event.target.value);}return (<div><label htmlFor="radio1">男</label><inputtype="radio"id="radio1"name="gender"value="male"checked={gender == "male"}onChange={handleChange}/><label htmlFor="radio2">女</label><inputtype="radio"id="radio2"name="gender"value="female"checked={gender === "female"}onChange={handleChange}/><button onClick={() => console.log(gender)}>打印</button></div>);
}export default App;
checkbox复选
function App() {const [selectedList, setSelectedList] = useState<string[]>([]);function handleCityChange(event: ChangeEvent<HTMLInputElement>) {// event.target.value就是当前input的值const city = event.target.value;if (selectedList.includes(city)) {setSelectedList(selectedList.filter((c) => {if (c == city) return false;return true;}),);} else {// 添加setSelectedList(selectedList.concat(city));}}return (<>{/* htmlFor 点击的时候也会触发切换 */}<label htmlFor="checkbox1">北京</label><inputtype="checkbox"id="checkbox1"value="beijing"checked={selectedList.includes("beijing")}onChange={handleCityChange}/><label htmlFor="checkbox2">上海</label><inputtype="checkbox"id="checkbox2"value="shanghai"checked={selectedList.includes("shanghai")}onChange={handleCityChange}/><label htmlFor="checkbox3">深圳</label><inputtype="checkbox"id="checkbox3"value="shenzhen"checked={selectedList.includes("shenzhen")}onChange={handleCityChange}/>{/* 方便表单获取和提交 */}<inputtype="hidden"name="cityInput"value={JSON.stringify(selectedList)}/></>);
}export default App;
select下拉框
function App() {const [lang, setLang] = useState("js");function handleChange(event: ChangeEvent<HTMLSelectElement>) {// event.target.value就是当前input的值setLang(event.target.value);}return (<>{/* 不设置state的话选择了没反应 */}<select value={lang} onChange={handleChange}><option value="java">Java</option><option value="C++">C++</option><option value="python">Python</option></select></>);
}
form表单组件
function App() {function handleSubmit(event: ChangeEvent<HTMLFormElement>) {event.preventDefault(); // 阻止默认行为,即不会提交到action// 可以自行处理提交的逻辑}return (<>{/* 点击提交后会将相应的数据发送到action中填写的接口。提交的就是name和value */}{/* 没有name,没有value的话会导致提交无法识别 */}{/* 隐藏input(type:hidden)的价值就在于可以把想要提交的数据偷偷提交上去 */}{/* onSubmit提交前调用的钩子函数,可以阻止默认行为,不然点击就直接提交了 */}<form action="/api/post" onSubmit={handleSubmit}><input /><br /><textarea /><input type="hidden" /><button type="submit">提交</button></form></>);
}
Ant Design 实现
为什么地址要添加参数,避免刷新的时候搜索数据丢失,不保存的话一刷新页面内容就重置了,保存了之后就算是刷新,由于地址附有参数,刷新时地址不会改变,所以仍能展示出搜索后的数据
同时也是为了避免组件之间的耦合,最好不要一搜索就更新列表组件或者一分页就更新列表组件,而是通过一个更加公共的比如地址栏进行搜索或者分页信息的传递,也能避免刷新后数据无法保存,比如搜索栏一刷新原来的搜索词就没有了,但是可以通过从路径获取参数来达到“保存”的效果
新建constants文件夹,其中设置index.tsx文件保存常用变量,跟router中导出常用变量类似
// 存储所有的常量
export const LIST_SEARCH_PARAM_KEY = "keyword";
搜索栏组件
ListSearch.tsx
import React, { FC, useEffect, useState } from "react";
import { Input } from "antd";
import type { ChangeEvent } from "react";
import { useNavigate, useLocation, useSearchParams } from "react-router-dom";
import { LIST_SEARCH_PARAM_KEY } from "../constants";const { Search } = Input;const ListSearch: FC = () => {const [val, setVal] = useState("");const nav = useNavigate();const { pathname } = useLocation();function handleChange(event: ChangeEvent<HTMLInputElement>) {setVal(event.target.value);}function handleSearch(value: string) {// 跳转页面增加URL参数nav({pathname,search: `${LIST_SEARCH_PARAM_KEY}=${value}`,});}// 获取url参数,并设置到input valueconst [searchParams] = useSearchParams();useEffect(() => {// 每当searchParams有变化就执行函数// serchParams用来获得上面nav中设置的参数const newVal = searchParams.get(LIST_SEARCH_PARAM_KEY) || "";setVal(newVal);}, [searchParams]);return (<SearchallowClearplaceholder="请输入关键字"value={val}onChange={handleChange}onSearch={handleSearch}style={{ width: "260px" }}/>);
};
export default ListSearch;
开发注册页
Register.module.scss
.contain{height: 100vh;width: 100vw;display: flex;flex-direction: column;justify-content: center;align-items: center;background-image: linear-gradient(to top, #5ee7df 0%, #b490ca 100%);// background-image: linear-gradient(to top, #9890e3 0%, #b1f4cf 100%);
}
Register.tsx
import React, { FC } from "react";
import { Typography, Space, Form, Input, Button } from "antd";
import { UserAddOutlined } from "@ant-design/icons";
import styled from "./Register.module.scss";
import { Link } from "react-router-dom";
import { LOGIN_PATHNAME } from "../router";const { Title } = Typography;const Register: FC = () => {// any表示任意类型都可const onFinish = (values: any) => {console.log(values);};return (<div className={styled.contain}><div><Space><Title level={2}><UserAddOutlined /></Title><Title level={2}>注册新用户</Title></Space></div><div><FormlabelCol={{ span: 6 }}wrapperCol={{ span: 16 }}onFinish={onFinish}><Form.Item label="用户名" name="userName"><Input /></Form.Item><Form.Item label="密码" name="passWord"><Input.Password /></Form.Item><Form.Item label="确认密码" name="conFirm"><Input.Password /></Form.Item><Form.Item label="昵称" name="nickName"><Input /></Form.Item><Form.Item wrapperCol={{ offset: 8, span: 16 }}><Space>{/* htmlType就是之前html里的type,只是前面设置属性被占用了,用这个一样的效果都是为了触发方法 */}<Button type="primary" htmlType="submit">注册</Button></Space><Link to={LOGIN_PATHNAME}>已有账户,登录</Link></Form.Item></Form></div></div>);
};
export default Register;
开发登录页
Login.module.scss
.contain{height: 100vh;width: 100vw;display: flex;flex-direction: column;justify-content: center;align-items: center;background-image: linear-gradient(to top, #5ee7df 0%, #b490ca 100%);// background-image: linear-gradient(to top, #9890e3 0%, #b1f4cf 100%);
}
Login.tsx
// 登陆页面
import React, { FC, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import { Space, Typography, Form, Input, Button, Checkbox } from "antd";
import { UserAddOutlined } from "@ant-design/icons";
import { REGISTER_PATHNAME } from "../router";
import styled from "./Login.module.scss";const { Title } = Typography;const USERNAME_KEY = "USERNAME";
const PASSWORD_KEY = "PASSWORD";function rememberUser(username: string, password: string) {localStorage.setItem(USERNAME_KEY, username);localStorage.setItem(PASSWORD_KEY, password);
}function deleteUser() {localStorage.removeItem(USERNAME_KEY);localStorage.removeItem(PASSWORD_KEY);
}function getUser() {return {username: localStorage.getItem(USERNAME_KEY),password: localStorage.getItem(PASSWORD_KEY),};
}const Login: FC = () => {const nav = useNavigate();// 第三方hook,即第三方提供的组件const [form] = Form.useForm();const onFinish = (values: any) => {const { username, password, remember } = values;if (remember) {rememberUser(username, password);} else {deleteUser();}};// 依赖不填写,默认在组件渲染完成后执行useEffect(() => {const { username, password } = getUser();// 这里如果不小心写成了setFieldValue会报错,差了个s,这个只能输入一个参数,有s的才能输入多个form.setFieldsValue({ username, password });}, []);return (<div className={styled.contain}><div><Space><Title level={2}><UserAddOutlined /></Title><Title level={2}>用户登录</Title></Space></div><div><FormlabelCol={{ span: 6 }}wrapperCol={{ span: 16 }}onFinish={onFinish}// 默认remember设置为trueinitialValues={{ remember: true }}// 将返回值关联起来,即使其变成受控组件form={form}><Form.Item label="用户名" name="username"><Input /></Form.Item><Form.Item label="密码" name="password"><Input.Password /></Form.Item><Form.Itemname="remember"valuePropName="checked"wrapperCol={{ offset: 6, span: 16 }}>{/* 表单需要有name和value才能提交,valuePropname就是将Checkbox的checked属性,即选中的属性(true || false)当作值 */}<Checkbox>记住我</Checkbox></Form.Item><Form.Item wrapperCol={{ offset: 6, span: 16 }}><Space><Button type="primary" htmlType="submit">登录</Button><Link to={REGISTER_PATHNAME}>注册新用户</Link></Space></Form.Item></Form></div></div>);
};
export default Login;
表单校验
先在注册里进行校验,使用的都是antd里form的功能,然后复制到登录就行
Register.tsx
// 注册界面
import React, { FC } from "react";
import { Typography, Space, Form, Input, Button, message } from "antd";
import { UserAddOutlined } from "@ant-design/icons";
import styled from "./Register.module.scss";
import { Link } from "react-router-dom";
import { LOGIN_PATHNAME } from "../router";const { Title } = Typography;const Register: FC = () => {// any表示任意类型都可const onFinish = (values: any) => {console.log(values);};return (<div className={styled.contain}><div><Space><Title level={2}><UserAddOutlined /></Title><Title level={2}>注册新用户</Title></Space></div><div><FormlabelCol={{ span: 6 }}wrapperCol={{ span: 16 }}onFinish={onFinish}><Form.Itemlabel="用户名"name="username"rules={[{ required: true, message: "请输入用户名" },// string表示按长度计算区间范围,不然变成数字就成最小5最大20了{type: "string",min: 5,max: 20,message: "字符长度在5-20之间",},{pattern: /^\w+$/,message: "只能是字母数字下划线",},]}><Input /></Form.Item><Form.Itemlabel="密码"name="password"// required表示必填项,会出现红点rules={[{ required: true, message: "请输入密码" }]}><Input.Password /></Form.Item><Form.Itemlabel="确认密码"name="confirm"// 依赖password属性,password变化会重新触发验证dependencies={["password"]}rules={[{ required: true, message: "请确认输入的密码" },// 这个校验传递进去的是一个函数({ getFieldValue }) => ({validator(_, value) {if (getFieldValue("password") === value) {return Promise.resolve();} else {return Promise.reject(new Error("两次密码不一致"));}},}),]}><Input.Password /></Form.Item><Form.Item label="昵称" name="nickname"><Input /></Form.Item><Form.Item wrapperCol={{ offset: 8, span: 16 }}><Space>{/* htmlType就是之前html里的type,只是前面设置属性被占用了,用这个一样的效果都是为了触发方法 */}<Button type="primary" htmlType="submit">注册</Button><Link to={LOGIN_PATHNAME}>已有账户,登录</Link></Space></Form.Item></Form></div></div>);
};
export default Register;
Login.tsx
// 登陆页面
import React, { FC, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import { Space, Typography, Form, Input, Button, Checkbox } from "antd";
import { UserAddOutlined } from "@ant-design/icons";
import { REGISTER_PATHNAME } from "../router";
import styled from "./Login.module.scss";const { Title } = Typography;const USERNAME_KEY = "USERNAME";
const PASSWORD_KEY = "PASSWORD";function rememberUser(username: string, password: string) {localStorage.setItem(USERNAME_KEY, username);localStorage.setItem(PASSWORD_KEY, password);
}function deleteUser() {localStorage.removeItem(USERNAME_KEY);localStorage.removeItem(PASSWORD_KEY);
}function getUser() {return {username: localStorage.getItem(USERNAME_KEY),password: localStorage.getItem(PASSWORD_KEY),};
}const Login: FC = () => {const nav = useNavigate();// 第三方hook,即第三方提供的组件const [form] = Form.useForm();const onFinish = (values: any) => {const { username, password, remember } = values;if (remember) {rememberUser(username, password);} else {deleteUser();}};// 依赖不填写,默认在组件渲染完成后执行useEffect(() => {const { username, password } = getUser();// 这里如果不小心写成了setFieldValue会报错,差了个s,这个只能输入一个参数,有s的才能输入多个form.setFieldsValue({ username, password });}, []);return (<div className={styled.contain}><div><Space><Title level={2}><UserAddOutlined /></Title><Title level={2}>用户登录</Title></Space></div><div><FormlabelCol={{ span: 6 }}wrapperCol={{ span: 16 }}onFinish={onFinish}// 默认remember设置为trueinitialValues={{ remember: true }}// 将返回值关联起来,即使其变成受控组件form={form}><Form.Itemlabel="用户名"name="username"rules={[{ required: true, message: "请输入用户名" },// string表示按长度计算区间范围,不然变成数字就成最小5最大20了{type: "string",min: 5,max: 20,message: "字符长度在5-20之间",},{pattern: /^\w+$/,message: "只能是字母数字下划线",},]}><Input /></Form.Item><Form.Itemlabel="密码"name="password"rules={[{ required: true, message: "请输入密码" }]}><Input.Password /></Form.Item><Form.Itemname="remember"valuePropName="checked"wrapperCol={{ offset: 6, span: 16 }}>{/* 表单需要有name和value才能提交,valuePropname就是将Checkbox的checked属性,即选中的属性(true || false)当作值 */}<Checkbox>记住我</Checkbox></Form.Item><Form.Item wrapperCol={{ offset: 6, span: 16 }}><Space><Button type="primary" htmlType="submit">登录</Button><Link to={REGISTER_PATHNAME}>注册新用户</Link></Space></Form.Item></Form></div></div>);
};
export default Login;
相关文章:

react-问卷星项目(7)
实战 React表单组件 入门 重点在于change的时候改变state的值,类似vue的双向数据绑定v-model,即数据更新的时候页面同步更新,页面数据更新时数据源也能获得最新的值,只是Vue中设置在data中的属性默认绑定,React中需…...

【git】main|REBASE 2/6
很久没合并代码合并出现冲突,自动进入了 main|REBASE 2/6 的提示: 【git】main|REBASE 2/6 It looks like you’ve encountered several merge conflicts after a git pull operation while a rebase is in progress. Here’s how you can resolve these conflict…...

51单片机的水质检测系统【proteus仿真+程序+报告+原理图+演示视频】
1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块温度传感器ph传感器浑浊度传感器蓝牙继电器LED、按键和蜂鸣器等模块构成。适用于水质监测系统,含检测和调整水温、浑浊度、ph等相似项目。 可实现功能: 1、LCD1602实时显示水温、水体ph和浑浊度 2、温…...

【python面试宝典7】线程池,模块和包
目录标 题目37:解释一下线程池的工作原理。题目38:举例说明什么情况下会出现KeyError、TypeError、ValueError。题目39:说出下面代码的运行结果。题目40:如何读取大文件,例如内存只有4G,如何读取一个大小为…...

Android input系统原理二
1.inputmanager启动源码分析 在SystemServer.java中构造了 inputmanagerservice的对象,在其构造函数中,最重要的是这个nativeInit函数。 下面是核心代码 inputManager new InputManagerService(context);public InputManagerService(Context context)…...

Oracle登录报错-ORA-01017: invalid username/password;logon denied
接上文:Oracle创建用户报错-ORA-65096: invalid common user or role name 我以为 按照上文在PDB里创建了用户,我以为就可以用PLSQL远程连接了,远程服务器上也安装了对应版本的Oracle客户端,但是我想多了,客户只是新建…...

JavaScript 获取浏览器本地数据的4种方式
JavaScript 获取浏览器本地数据的方式 我们在做Web开发中,客户端存储机制对于在浏览器中持久化数据至关重要。这些机制允许开发者存储用户偏好设置、应用状态以及其他关键信息,从而增强用户体验。本文将介绍几种常用的JavaScript获取浏览器本地数据的方…...

77寸OLED透明触摸屏有哪些应用场景
说到77寸OLED透明触摸屏,那可真是市场营销中的一大亮点,应用场景多到数不清!我这就给你细数几个热门的: 商业展示:这可是77寸OLED透明触摸屏的拿手好戏!在高端零售店铺里,它可以作为陈列窗口&am…...

二分解题的奇技淫巧都有哪些,你还不会吗?
先说一下我为什么要写这篇文章。 “二分“ 查找 or ”二分“ 答案的思想大家想必都知道吧(如果不懂,可以看一下我之前写的一篇文章)。 二分求解 可是呢?思想都会,做题的时候,就懵圈了。 这个题竟然考的是…...

LeetCode-871 最低加油次数
重启力扣每日一题系列! 因为过去两个月里掉粉掉的好严重,我想大抵是因为更新的频率不如上半年了,如果我重启了每日一题系列那岂不是至少是每日一更☝🤓? 也不是每天都更,我有两不更,特难的就不…...

OpenCV-OCR
文章目录 一、OCR技术的基本原理二、OpenCV在OCR识别中的应用1.图像预处理2.文字区域检测3.OCR识别:4.后处理: 三、OCR识别示例代码四、注意事项 OpenCV-OCR主要涉及使用OpenCV库进行光学字符识别(OCR)的技术。OCR技术可以识别图像…...

Linux卸载mysql
一、查看当前安装mysql情况,查找以前是否装有mysql rpm -qa|grep -i mysql二、停止MySQL服务 三、删除mysql库和文件 查找MySQL库 # 查找命令 find / -name mysql# 显示结果 /var/lib/mysql/var/lib/mysql/mysql/usr/lib64/mysql删除对应的mysql目录 rm -rf /v…...

【大语言模型-论文精读】用于医疗领域摘要任务的大型语言模型评估综述
【大语言模型-论文精读】用于医疗领域摘要任务的大型语言模型评估综述 论文信息: 用于医疗领域摘要任务的大型语言模型评估:一篇叙述性综述, 文章是由 Emma Croxford , Yanjun Gao 博士 , Nicholas Pellegrino , Karen K. Wong 等人近期合作…...

图吧工具箱
图吧工具箱202309绿色版自动解压程序R2.exe,永久有效 链接:https://pan.baidu.com/s/1M6TI7Git8bXOzZX_qZ3LJw?pwdzked 提取码:zked...

vue2 + View design 使用inputNumber设置默认值为undefined但展示数据为1且表单校验不通过的原因
文章目录 一、背景二、操作步骤1.复现前的准备工作(1)vue版本和view design 版本(2)创建一个组件(组件中根据类型渲染不同的组件)(3)在list.vue页面中引入组件,传入配置&…...

【SpringSecurity】基本流程
【中文文档: Spring Security 中文文档 :: Spring Security Reference】 【英文文档:Spring Security】 以下内容只是记录springsecurity最简单的一种验证流程,所有配置基本都是默认的配置。 引入依赖 <dependency><groupId>org.springf…...
算法-汉诺塔问题(Hanoi tower)
介绍 汉诺塔是源于印度的一个古老传说的小游戏,简单来说就是有三根柱子,开始的时候,第一根柱子上圆盘由大到小,自下往上排列。这个小游戏要实现的目的呢,就是要把第一根柱子上的圆盘移到第三根的柱子上去;…...

HarmonyOS鸿蒙 Next 实现协调布局效果
HarmonyOS鸿蒙 Next 实现协调布局效果 假期愉快! 最近大A 的涨势实在是红的让人晕头转向,不知道各位收益如何,这会是在路上,还是已经到目的地了? 言归正传,最近有些忙,关于鸿蒙的实践系列有些脱节了,…...

【自然语言处理】(1) --语言转换方法
文章目录 语言转换方法一、统计语言模型1. 词向量转换2. 统计模型问题 二、神经语言模型1. 词向量化2. 维度灾难3. 解决维度灾难4. embedding词嵌入5. Word2Vec技术5.1 连续词袋模型(CBOW)5.2 跳字模型(Skip-gram) 总结 语言转换方…...

叉车防撞系统方案,引领安全作业新时代
在现代工业的舞台上,叉车如同忙碌的“搬运工”,在仓储和制造环境中发挥着不可或缺的作用。然而,随着叉车使用频率的不断攀升,安全事故也如影随形,给企业带来经济损失的同时,更严重威胁着操作人员的生命安全…...

Nginx的核心架构和设计原理
Nginx 是一个免费的、开源的、高性能 Http 服务器和反向代理。Nginx 的架构设计是为了提供高性能、稳定性和可扩展性。 Nginx 的主要架构组件和工作原理: 1、Master 进程:Nginx 的运行始于一个 master 进程,它负责管理所有的工作进程。mast…...

leetcode35--搜索插入位置--二分查找刷题
搜索插入位置 一共会出现下面四种情况: 目标值在数组所有元素之前 目标值等于数组中某一个元素 目标值插入数组中的位置 目标值在数组所有元素之后 首先在二分查找的代码之前处理掉目标值在数组所有元素之前和之后的情况如果目标值在数组中的某个位置,…...

Django对接支付宝沙箱环境(2024年9月新测有效)
1、申请沙箱环境 #需要填一些个人信息 https://opendocs.alipay.com/ 2、使用支付宝登入,并进入控制台,进入开发者工具推荐-->沙箱 3、获取基本信息 主要是APPID,和支付宝网关地址 4、生成应用私钥和应用公钥和支付宝公钥 上面的接口加签方式选择…...

【MySQL】-- 库的操作
文章目录 1. 查看数据库1.1 语法 2. 创建数据库2.1 语法2.2 示例2.2.1 创建一个名为java114的数据库2.2.2 创建数据库java114,如果数据库不存在则创建2.2.3 查看警告信息 3. 字符集编码和校验(排序)规则3.1 查看数据库支持的字符集编码3.2 查…...

linux桌面软件(wps)内嵌到主窗口后的关闭问题
程序测试环境是:slackware系统,属于linux系统,有桌面(Xface Session)。系统镜像是:slackware64-15.0-install-dvd.iso。qt、c代码实现。 问题描述:延续上一篇文章,将wps软件窗口内嵌…...

WindowsTerminal 美化-壁纸随机更换
目录 一. 相关网址二. 壁纸随机更换思路三. 指定 WindowsTermina 壁纸路径四. 编写脚本,随机替换壁纸4.1 powershell脚本4.2 .bat批处理脚本 四. 配置定时任务,添加触发器五. 效果 一. 相关网址 官方下载 Windows Terminal 官方Github微软商店 美化 Oh …...

iOS 多次获取图片主题色不一样
一个需求中,要求获取图片的主题色 代码如下 -(void)kk_getImage:(UIImage *)image fetchthemeColor:(void(^)(UIColor *color))callBack {dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{// 第一步 先把图片缩小 加快计算速度.…...

UE5 武器IK瞄准系统
创建空项目 创建基础蓝图类My_GameMode,My_HUD,My_PlayChar,My_PlayController 项目设置地图模式 近裁平面 0.1 My_PlayChar蓝图中添加摄像机,角色骨骼网格体,武器骨骼网格体 编辑角色骨骼,预览控制器使用特定动画,动画选择ANM_ark-47-Idle hand_r 添加插槽WeaponMes…...

①EtherCAT转ModbusTCP, EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关
EtherCAT/Ethernet/IP/Profinet/ModbusTCP协议互转工业串口网关https://item.taobao.com/item.htm?ftt&id822721028899 协议转换通信网关 EtherCAT 转 ModbusTCP GW系列型号 MS-GW15 简介 MS-GW15 是 EtherCAT 和 Modbus TCP 协议转换网关,为用户提供一种 …...

在macOS上进行开发环境配置与应用开发详细的配置指南
在macOS上进行开发环境配置与应用开发,需要遵循一系列步骤来确保你的开发环境既高效又稳定。以下是一个详细的配置指南,涵盖了从安装基本工具到创建应用的整个过程。 1. 安装和更新macOS 首先,确保你的macOS是最新版本。更新系统可以提供更…...