【Typescript学习】使用 React 和 TypeScript 构建web应用(二)部分UI、useState、useRef、Props

news2024/11/28 4:37:53

教程来自freecodeCamp:【英字】使用 React 和 TypeScript 构建应用程序
跟做,仅记录用
其他资料:https://www.freecodecamp.org/chinese/news/learn-typescript-beginners-guide/


第二天

以下是视频(0:18-0:40) 的内容

目录

  • 第二天
    • 1 App 函数组件的类型
    • 2 头部及其 UI
    • 3 Todo的input框 UI
    • 4 useState Hook
    • 5 函数作为props传递
    • 6 useRef Hook

1 App 函数组件的类型

是React.FC

const App: React.FC = () => {
  //
}

2 头部及其 UI

先做个头部,效果如下
在这里插入图片描述

App.tsx

import React from 'react';
import './App.css';
const App: React.FC = () => {
  return (
    <div className="App">
      <span className='heading'>Taskify</span>
    </div>
  );
}

想引入一个叫neucha的谷歌字体,搜索一下
在这里插入图片描述
进入后在这里插入图片描述
复制import信息到css文件
在这里插入图片描述

App.css文件中引入并使用

@import url('https://fonts.googleapis.com/css2?family=Neucha&display=swap');

.App {
    width: 100vw;
    height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    background-color: #2f74c0;
    font-family: 'Neucha', cursive;  /* 使用字体 */
}

.heading {
    text-transform: uppercase;
    font-size: 40px;
    color: white;
    margin: 30px 0;
    text-align: center;
    z-index: 1; /* 保持最顶层,为了之后的动画效果 */
    
/* 窗口适应 */
@media (max-width: 800px) { 
    .heading {
        margin: 15px 0;
        font-size: 35px;
    }
}
}

3 Todo的input框 UI

做一下input框
在这里插入图片描述

可以安装个扩展插件使用模板快捷键,比如在组件.tsx文件中,空白时输入tsrafce快捷填入模板
在这里插入图片描述

新建一个InputField组件
在这里插入图片描述

InputField.tsx

import React from 'react'
import "./styles.css";
type Props = {}

const InputField = (props: Props) => {
  return (
    <form className='input'>
        <input type="input" placeholder="Enter a task" className='input__box'/>
        <button className='input_submit' type='submit'>
            Go
        </button>
    </form>
  )
}

export default InputField

CSS类名都遵循 BEM 命名格式
style.css

.input {
    display: flex;
    width: 90%;
    position: relative;
    align-items: center;
}
.input__box {
    width: 100%;
    border-radius: 50px;
    padding: 20px 30px;
    font-size: 25px;
    border: none;
    transition: 0.2s;
    box-shadow: inset 0 0 5px black;
}

.input__box:focus {
    box-shadow: 0 0 10px 1000px rgba(0, 0, 0, 0.5);
    outline: none;
}

.input_submit {
    position: absolute;
    border-radius: 50%;
    font-size: 15px;
    margin: 12px;
    right: 0px;
    background-color: #2f74c0;
    color: white;
    width: 50px;
    height: 50px;
    border: none;
    box-shadow: 0 0 10px black;
    transition: 0.2s all;
}
.input_submit:hover {
    background-color: #388ae2;
}
/* 按钮点击时 */
.input_submit:active {  
    transform: scale(0.8);  /* 缩放 */
    box-shadow: 0 0 5px black;
}

4 useState Hook

我们需要实时地拿到用户输入到input的文字(一条todo),所以可以使用statestate用来表示和控制组件中的变量的状态。

为了增删改查,todo列表数据应该是放在App中的,但是新建的每一个todo的string内容在子组件InputField里。因此使用prop进行组件间通信,

我们需要使用prop来在App组件InputField组件中传递状态变量

  1. 父(App)向子(InputField)传递传递prop:todo={todo} setTodo={setTodo}

App.tsx

const App: React.FC = () => {
  const [todo, setTodo] = useState<string>(""); // 尖括号加上变量类型

  return (
    <div className="App">
      <span className='heading'>Taskify</span>
      <InputField todo={todo} setTodo={setTodo}/>
    </div>
  );
}
  1. InputField 中用定义Props type,接收所有传来的prop
    setTodo的类型在App.tsx中悬浮一下就可得到,是React.Dispatch<React.SetStateAction<string>>

InputField.tsx

type Props = {
    todo: string,
    setTodo: React.Dispatch<React.SetStateAction<string>>,
}
  1. InputField的元素中使用todosetTodo
const InputField: React.FC<Props> = ({todo, setTodo}: Props) => {
  return (
    <form className='input'>
        <input type="input"
          value={todo} 
          onChange={
            (e)=>setTodo(e.target.value)
          }
          placeholder="Enter a task" 
          className='input__box'
        />
        <button className='input_submit' type='submit'>
            Go
        </button>
    </form>
  )
}

Todo列表
因为许多地方复用,所以创建一个model.ts,里面定义interface Todo

export interface Todo {
    id: number;
    todo: string;      // 内容
    isDone: boolean;  // 是否完成
}

App.tsx中定义Todo为元素的数组todos,代表Todo列表

const [todos, setTodos] = useState<Todo[]>([]); 

5 函数作为props传递

handleAdd函数(填完todo后点击GO时的回调)的逻辑,

// 点击GO后
  const handleAdd = (e: React.FormEvent):void => {
    e.preventDefault(); // 取消默认的页面刷新行为
    if(todo) {
      // 在列表尾部加一条Todo,时间作为id
      setTodos([...todos, {id: Date.now(), 
                           todo: todo, 
                           isDone: false}
      ])
      setTodo("");  // 清空input框
      // 在App里setTodo("")是因为将父组件的state(todo)作为子组件的props
      // 当父组件的state改变,子组件的props也跟着改变。
    }
  };

将函数作为props传递
App.tsx

const App: React.FC = () => {
const [todo, setTodo] = useState<string>("");
const [todos, setTodos] = useState<Todo[]>([]);  
// 点击GO后
  const handleAdd = (e: React.FormEvent):void => {
    e.preventDefault(); // 取消默认的页面刷新行为
    if(todo) {
      // 在列表尾部加一条Todo,时间作为id
      setTodos([...todos, {id: Date.now(), 
                           todo: todo, 
                           isDone: false}
      ])
      setTodo("");  // 清空input框
      // 在App里setTodo(""),因为将父组件的state(todo)作为子组件的props
      // 当父组件的state改变,子组件的props也跟着改变。
    }
  };
  
  return (
    <div className="App">
      <span className='heading'>Taskify</span>
      <InputField todo={todo} setTodo={setTodo} handleAdd={handleAdd}/>
    </div>
  );
 }

InputField.tsx中的Props定义里加上handleAdd,形参类型为React.FormEvent,若类型不清楚可以google到的

type Props = {
    todo: string,
    setTodo: React.Dispatch<React.SetStateAction<string>>,
    handleAdd: (e: React.FormEvent) => void,
}

const InputField: React.FC<Props> = ({todo, setTodo, handleAdd}: Props) => {
  return (
    <form className='input' onSubmit={handleAdd}>
        ...
    </form>
  )
}

export default InputField

6 useRef Hook

我们发现回车后input的focus还没有解除,即样式上input周围都是暗色的,这不符合需求。
可以在InputField.tsx中用useRef来控制,useRef 的作用之一是用于获取DOM元素

  1. 先通过useRef创建一个变量,类型是HTMLInputElement
const inputRef = useRef<HTMLInputElement>(null)
  1. 然后在jsx中通过ref={inputRef}给对应元素节点添加属性
<input type="input"
       ref={inputRef}
       value={todo} 
       onChange={
         (e)=>setTodo(e.target.value)
       }
       placeholder="Enter a task" 
       className='input__box'
 />
  1. 在页面挂载后通过inputRef.current就可以获取对应节点的真实DOM元素了
 <form className='input' onSubmit={(e) => {
            handleAdd(e);
            console.log(e);
            inputRef.current?.blur();  // 移除focus状态
            // 如果这里报错可以外加一个if先对inputRef.current判非空
        }}
  >

第二天 done!
我们构建了InputField组件,完善了UI,复习了useState、useRef、props,截止今天,代码如下:
InputField.tsx

import React, {useRef} from 'react'
import "./styles.css";
type Props = {
    todo: string,
    setTodo: React.Dispatch<React.SetStateAction<string>>,
    handleAdd: (e: React.FormEvent) => void,
}

const InputField: React.FC<Props> = ({todo, setTodo, handleAdd}: Props) => {
  const inputRef = useRef<HTMLInputElement>(null)
  return (
    <form className='input' onSubmit={(e) => {
            handleAdd(e);
            console.log(e);
            inputRef.current?.blur();  // 移除focus状态
        }}
    >
        <input type="input"
          ref={inputRef}
          value={todo} 
          onChange={
            (e)=>setTodo(e.target.value)
          }
          placeholder="Enter a task" 
          className='input__box'
        />
        <button className='input_submit' type='submit'>
            GO
        </button>
    </form>
  )
}

export default InputField

App.tsx

import React, { useState } from 'react';
import './App.css';
import InputField from './components/InputField';
import { Todo } from "./model";

const App: React.FC = () => {
  const [todo, setTodo] = useState<string>(""); // 尖括号加上变量类型
  const [todos, setTodos] = useState<Todo[]>([])  
  // 点击GO后
  const handleAdd = (e: React.FormEvent):void => {
    e.preventDefault(); // 取消默认的页面刷新行为
    if(todo) {
      setTodos([...todos, {id: Date.now(), 
                           todo: todo, 
                           isDone: false}
      ])
      setTodo("");
    }
  };  
  return (
    <div className="App">
      <span className='heading'>Taskify</span>
      <InputField todo={todo} setTodo={setTodo} handleAdd={handleAdd}/>
    </div>
  );
}

export default App;

心得体会:
React 一段时间不用就容易忘,几种Hook需要捋一捋

使用到的:

  • neucha font
    neucha font
  • 一种CSS命名规范——BEM
  • VSCode 代码模板插件 “ES7 + React/Redux/React-Native snippets”
  • useState
  • useRef
  • props

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

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

相关文章

【二叉树】java实现代码,详解二叉树,带大家更深刻的掌握二叉树递归思想

前言&#xff1a; 大家好&#xff0c;我是良辰丫&#x1fa90;&#x1fa90;&#x1fa90;&#xff0c;在探索数据结构的旅程中&#xff0c;二叉树可以说是数据结构中的重点&#xff0c;笔试面试经常出现的问题&#xff0c;同时也是难点。&#x1f425;&#x1f425;&#x1f4…

【Java开发】Spring Cloud 09 :微服务网关 Gateway

Spring Cloud Gateway&#xff08;简称 Gateway&#xff09;&#xff0c;它在微服务架构中扮演的角色是“微服务网关”&#xff0c;Nginx 和 Gateway 在微服务体系中的分工是不一样的。Gateway 作为更底层的微服务网关&#xff0c;通常是作为外部 Nginx 网关和内部微服务系统之…

Markdown编辑器基本语法

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

【C语言从0到1之文件操作(FILE)】(原理 画图 举例 不信教不会你 不要放收藏夹落灰 学起来好嘛)

&#x1f57a;作者&#xff1a;迷茫的启明星 &#x1f383;专栏&#xff1a;《数据库》《C语言从0到1专栏》《数据结构》《C语言杂谈》&#x1f3c7;分享喜欢的一句话&#xff1a;心如花木&#xff0c;向阳而生前言在我们的学习中&#xff0c;文件操作是被我们忽略&#xff0c;…

NodeJS 与第三方模块 mysql(基本操作)

文章目录参考描述mysql 模块连接数据库检测基本操作查询数据与代码分离原则占位符插入另一种姿态修改另一种姿态删除标记删除参考 项目描述哔哩哔哩黑马程序员搜索引擎Bing 描述 项目描述NodeJSv18.13.0nodemon2.0.20MySQL5.7.40mysql2.18.1 mysql 模块 npm&#xff08;Node…

Linux——进程

目录 冯诺依曼体系结构 操作系统(Operator System) 概念 设计OS的目的 定位 如何理解 "管理" 总结 系统调用和库函数概念 承上启下 进程 基本概念 描述进程-PCB task_struct-PCB的一种 task_ struct内容分类 组织进程 查看进程 通过系统调用获取进程…

Pycharm使用Git进行版本控制(自建远端Git仓库)

目录本地Git安装远端Git仓库搭建在Pycharm中使用Git进行版本控制设置Git可执行文件路径创建本地Git仓库设置远端Git仓库提交及推送本地Git安装 安装本地Git用于被Pycharm调用&#xff0c;安装方法参考以下博客&#xff1a; Git 的下载与安装_作者&#xff1a;fengzhx0820 远端…

四轮两驱小车(四):STM32驱动5路灰度传感器PID循迹

目录 前言&#xff1a; 小车效果展示&#xff1a; 5路数字灰度传感器&#xff1a; 巡线思路&#xff1a; 加入PID调节的代码&#xff1a; 前言&#xff1a; 之前买了一批5路灰度传感器&#xff0c;想用这传感器进行循迹&#xff0c;无奈网上和官方的资料提供的还是比较少&a…

ARM X210 官方 uboot 配置编译实践

一、X210官方uboot配置编译实践1 1. 找到官方移植好的 uboot&#xff08;BSP 概念&#xff09; (1) 源头的源代码是 uboot 官网下载的。这个下载的源代码可能没有你当前使用的开发板的移植&#xff0c;甚至找不到当前开发板使用的 SoC 对应的移植版本。 (2) SoC 厂商在推出一…

分享145个ASP源码,总有一款适合您

ASP源码 分享145个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 145个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1gxm3rFFLu8pUhVncQga6-g?pwd7n85 提取码&#x…

HJ56、HJ58、JZ4、JZ6、JZ15、JZ17几道题

文章目录HJ56 完全数计算题目描述&#xff1a;具体实现&#xff1a;HJ58 输入n个整数&#xff0c;输出其中最小的k个题目描述&#xff1a;具体实现&#xff1a;JZ4 二维数组中的查找题目描述&#xff1a;具体实现&#xff1a;JZ6 从尾到头打印链表题目描述&#xff1a;具体实现…

springboot文件上传,单文件上传和多文件上传,以及数据遍历和回显

springboot文件上传&#xff0c;单文件上传和多文件上传项目结构及pom.xml创建文件表单页面编写javabean编写controller映射MultipartFile类RequestPart注解controller代码application.properties中的文件上传配置遍历数据显示页面运行显示项目结构及pom.xml pom.xml: <dep…

SQL用法详解补充

本文是对上次“SQL用法详解”的一些补充&#xff0c;一些基本操作可以点击链接查看 目录 一.对表结构的常用操作 查看表结构格式 修改表结构格式 1.修改列名和类型 2.修改添加列 3.修改表删除列 4.修改表名 5.数据删除 二.总结 三.实例 解决 完整代码 一.对表结构的常用操…

TIA博途中启用或禁用DP从站或PROFINET IO设备的具体方法

TIA博途中启用或禁用DP从站或PROFINET IO设备的具体方法 在实际项目中我们会遇到这样的问题, 例如:硬件组态中配置了一个控制器和3个 PN IO设备,但是最后只用到了2个PN IO设备,这样控制器一侧无法连接到第3个PN IO设备时,CPU会产生报警,PLC的Error指示灯会一直闪烁。 那么…

蓝桥杯2021省赛Python

蓝桥杯2021省赛Python 不得不说2021的比2020的难 1.卡片 很明显&#xff0c;最先没的肯定是1或者0&#xff0c;我们只要统计到谁会消耗2022个1或者0就好了 if __name__ __main__:res1 0res0 0for i in range(1,100000):i str(i)res1 i.count(1)res0 i.count(0)if res1…

[Rust笔记] 规则宏的“卫生保健”

规则宏代码的“卫生保健”规则宏mbe即是由macro_rules!宏所定义的宏。它的英文全称是Macro By Example。相比近乎“徒手攀岩”的Cpp模板元编程&#xff0c;rustc提供了有限的编译时宏代码检查功能&#xff08;名曰&#xff1a;Mixed Hygiene宏的混合保健&#xff09;。因为rust…

pointcovn 阅读笔记

各种点云采样算法 https://blog.csdn.net/weixin_41485242/article/details/107150963 Inverse Density 1.2 Inverse Density Importance Sampling (IDIS): 这个也比较好理解&#xff0c;简而言之就是根据每个点的密度来对其重新进行排序&#xff0c;尽可能地保留密度比较低的地…

python第九章 异常笔记

和Java类似程序运行有异常的时候&#xff0c;服务器会采用系统默认的异常处理机制&#xff1a;返回信息&#xff0c;终止程序。异常的类型&#xff1a;常见异常类型&#xff1a;1.NameError&#xff1a;访问了未定义的变量2.IndexError&#xff1a;越界访问3.AttributeError&am…

网络原理-网络发展史和通信基础

目录 1.网络发展史 面向终端的计算机网络 计算机网络阶段(局域网LAN) 组网方式 计算机网络互联阶段(广域网WAN) 2.通信基础 IP地址 端口号 网络协议 协议的作用 知名协议的默认端口 协议分层 分层的作用 OSI七层模型 TCP/IP五层模型 网络设备所在分层 网络分层…

《数据结构》八大排序和拓展的排序(详细教学并提供多种版本、动态图分析)

今天&#xff0c;我将带来数据结构的排序算法&#xff0c;排序算法作为校招中常考知识点之一&#xff0c;我们必须要熟练的掌握它,对自己提出高要求&#xff0c;才能有高回报。 目录排序的概念和应用内部排序和外部排序排序算法需要掌握的知识插入排序1.直接插入排序2.希尔排序…