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

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 = true

function 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 = true

function 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}>
   <EditAndDelete
     onEdit={(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>
       <input
         type="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.kler.cn/a/400630.html

相关文章:

  • HTML and CSS Support HTML 和 CSS 支持
  • 理解 Python 中的 __getitem__ 方法:在自定义类中启用索引和切片操作
  • React Native 全栈开发实战班 - 数据管理与状态之Zustand应用
  • 【Telephony】Android移动数据网络的控制面和数据面含义
  • QT QLabel双击事件
  • 【计算机网络】水平触发与边缘触发有什么优缺点呢?
  • 【Golang】——Gin 框架中的路由与请求处理
  • 【机器学习】SVM原理详解
  • Excel使用-弹窗“此工作簿包含到一个或多个可能不安全的外部源的链接”的发生与处理
  • 网络设备 - 这个有点难!
  • html | 节点操作
  • 手撸 chatgpt 大模型:简述 LLM 的架构,算法和训练流程
  • V-rep学习笔记:机器人路径规划
  • Vue3中使用Axios构建高效的请求处理机制
  • 苍穹外卖-后端部分
  • 【青牛科技】汽车收音机调频中频放大器——D1145
  • 游戏引擎学习第15天
  • 【前端知识】nodejs项目配置package.json深入解读
  • web——upload-labs——第十二关——%00截断
  • shell脚本判断nginx安装和运行
  • 深度学习概览
  • LinuxCentos中安装apache网站服务详细教程
  • JavaEE-网络编程(2)
  • CentOS 修改服务器登录密码的完整指南
  • 使用大语言模型创建 Graph 数据
  • css中的box-sizing,记录