React快速入门之交互性

news/2024/7/15 19:33:29 标签: react.js, 前端, 前端框架

响应事件

  • 创建事件处理函数
    处理函数名常以handle+事件名命名
  function handlePlayClick() {
    alert(`Playing`);
  }
  • 传递事件处理函数
    函数名、匿名两种方式!
function PlayButton() {
  function handlePlayClick() {
    alert(`Playing`);
  }
  return (
    <Button handleClick={handlePlayClick}>
      Play "{movieName}"
    </Button>
  );
}

function UploadButton() {
  return (
    <Button handleClick={() => alert('Uploading!')}>
      Upload Image
    </Button>
  );
}
  • 接受事件处理函数
    传参、匿名两种方式(⚠️传递的是函数名handlePlayClick并非handlePlayClick()!后者会在组件渲染时执行!)
  • onClick:事件名,仅支持浏览器事件名称。
function Button({ handleClick}) {
  function handlePlayClick() {
    alert(`Playing`);
  }
  return (
    <div>
    	<button onClick={handlePlayClick}></button>
    	
    	<button onClick={handleClick}></button>
		// 匿名
		<button onClick={() => alert('Uploading!')}></button>
	</div>
  );
}

事件传播

  • 事件“冒泡”
    单击3号button,会触发自身的onClick事件,接着事件会冒泡上传;
    2号button没有满足当前事件的函数,不执行,事件继续冒泡上传;
    1号div存在满足当前事件的函数,触发1号div响应的函数,事件继续冒泡上传…
<div id={1} className="Toolbar" onClick={() => {alert('You clicked on the toolbar!');}}>

	<button id={2} onDoubleClick={() => alert('Playing!')}>

		<button id={3} onClick={() => alert('Uploading!')}>Uploading</button>

	</button>

</div>
  • 阻止事件传播:e.stopPropagation()
    事件处理函数接收事件对象e(代表 “event”)作为唯一的参数。
    在事件名称末尾添加 Capture获取被捕获的事件,eg:onClickCapture
<div id={1} className="Toolbar" onClick={e => {
	e.stopPropagation();
	alert('You clicked on the toolbar!');
	}}>
	......
</div>
  • e.preventDefault(): 阻止了少数事件的默认浏览器行为
    例如在表单提交事件中,浏览器默认会刷新整个页面,e.preventDefault()可以阻止这一行为。
    <form onSubmit={e => {
      e.preventDefault();
      alert('Submitting!');
    }}>......
    </form>

Hooks :以 use 开头的函数

⚠️只能在组件或自定义的钩子函数的顶层被调用。 不能在条件、循环或其他嵌套函数中调用

状态:useState

  • 导入
import { useState } from 'react';
  • 使用
    0是默认值
    something 是状态变量,setSomething 是设置函数。(均为自定义)
const [something, setSomething] = useState(0);

纯粹原则表明应视something为只读,应通过setSomething函数创建一个新的值去更新!

1. something是一个对象时
  • 更新person对象部分属性
function handleChange(e) {
    setPerson({
  		firstName: e.target.value, // New first name from the input
  		lastName: person.lastName,
  		email: person.email
	});
  }
  • 展开对象写法
function handleChange(e) {
    setPerson({
  		...person, // Copy the old fields
  		firstName: e.target.value // But override this one
	});
  }
  • 动态[变量名]写法
function handleChange(e) {
    setPerson({
      ...person,
      [e.target.name]: e.target.value
    });
  }
  • 当要修改的对象属性名被嵌套太深,可以使用Immer三方库
import React from "react";
import { useImmer } from "use-immer";


function App() {
  ......
  function updateName(name) {
    updatePerson(draft => {
      draft.name = name;
    });
  }
  ......
}
2. something是一个数组时
  • 添加元素
setArtists([
	...artists,
	{ id: nextId++, name: name } // Put new item at the end
]);setArtists([
  { id: nextId++, name: name }, // Put new item at the head
  ...artists 
]);
  • 删除元素
setArtists(
  artists.filter(a => a.id !== artist.id)
);
  • 使用返回新数组的方法(a:元素,i:下标)
    map():遍历每个元素
    filter():返还条件为true的元素
artists.map(a => <li>a/<li>)
artists.map((a,i) => <li key={i}>a/<li>)

artists.filter(a => a.id !== artist.id)
artists.filter((a,i) => i<10)
  • 需要使用原地操作数组的方法时,使用slice()方法拷贝数组后,操作新数组。
    ⚠️这种拷贝都是浅拷贝(新数组中的对象仍然是对原始对象的引用)
/ 拷贝
let citrus = [...fruits] / 拷贝
let citrus = fruits.slice(); / 全部拷贝
let citrus = fruits.slice(1, 3); / 拷贝fruits[13/ 操作
const item = citrus.find(a => a.id === 2);
citrus.reverse();
citrus.sort();
/ 更新
setFruits(citrus);
  • 当然,当数组元素为对象时,仍要创建一个新的值去更新
    setMyList(myList.map(artwork => {
      return { ...artwork, seen: nextSeen };
    }));
  • 使用Immer三方库简化数组嵌套

状态与渲染

  • ⚠️React将something状态值存储在组件之外(组件存储的只是状态值的快照),每次setSomething()更改的是组件外的状态值,当组件“稳定”(没有代码在执行)后,React会更改DOM从而触发组件渲染,通过渲染将更新后的状态值刷新到页面!!!
    在这里插入图片描述
  • 代码中number默认为0
    当点击🔘+5时,alert(number)的值仍然是0!
import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 5);
        alert(number);
      }}>+5</button>
    </>
  )
}
  • 那如果需要多次修改状态值时,怎么办?传入函数(参数名通常为状态值首字母)
setNumber(n => n + 1);
setNumber(n => n + 1);
setNumber(n => n + 1);
setEnabled(e => !e);
setLastName(ln => ln.reverse());
setFriendCount(fc => fc * 2);

http://www.niftyadmin.cn/n/5297147.html

相关文章

Canal的学习

Canal 基本概念整合SpringBoot 基本概念 Canal是一个基于MySQL数据库增量日志解析&#xff0c;提供增量数据订阅和消费&#xff0c;支持将增量数据投递到下游消费者&#xff08;如Kafka、RocketMQ等&#xff09;或者存储&#xff08;如 Elasticsearch、HBase 等&#xff09;的…

流逝的时光

文章目录 创作历程展望2024 创作历程 自2019.6.28注册csdn&#xff0c;期间断断续续的通过其查找相应资料&#xff0c;受益颇多 今研一&#xff0c;发现论文看了又忘&#xff0c;于是借此平台来记录&#xff0c;可以看到基本都是基于原论文进行翻译&#xff0c;并没有所思所想&…

【译】MongoDB 性能最佳实践指南

原文地址&#xff1a;Best Practices Guide for MongoDB Performance 一、前言 MongoDB 是面向开发高性能应用程序的现代开发人员的主要 NoSQL 文档数据库。MongoDB 采用类似 JSON 的文档&#xff0c;以水平扩展和负载平衡著称&#xff0c;为开发人员提供了定制化和可扩展性之…

vite-ts-vue3笔记

vite npm create vitelatest npm run dev 开始预览时 使用模块 是 es module 打包生产环境 使用rollup webpack基于node vite 基于 原生 module和 rollup vite的基础配置 根目录下的vite.config.js import { fileURLToPath, URL } from node:urlimport { defineConfig } f…

SQL 解析 — 如何轻松实现新增语句

KaiwuDB 支持多种不同类型的 SQL 语句&#xff0c;例如 create、insert 等。本文将介绍在 KaiwuDB SQL Parser&#xff08;下文统称解析器&#xff09;中添加新语句的过程及其实现。我们将了解如何使用 goyacc 工具更新解析器&#xff0c;以及执行器和查询计划器&#xff08;pl…

Rust学习笔记002: 猜字游戏

version0.1 // 导入标准库中的 io 模块&#xff0c;它包含了输入输出相关的功能 use std::io;// 程序的入口点 fn main() {println!("Guess the number!");println!("Please input your guess.");// 创建一个可变的字符串变量 guess&#xff0c;用于存储用…

用DevExpress WPF Windows 10 UI组件,轻松构建触摸优先的业务型应用UX(上)

DevExpress WPF的Windows 10 UI组件包含了一系列应用导航组件、Toast通知、对话框组件等&#xff0c;能帮助用户轻松开发漂亮的业务型应用程序&#xff0c;并模仿触摸优先的Windows 10 Pro UX。 P.S&#xff1a;DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚…

linux安全

文章目录 前言一、防火墙二、selinux总结 前言 防火墙是服务器对外开放的窗口&#xff0c;在安装软件的时候&#xff0c;很难避免服务器各种各样的安全防护&#xff0c;导致安装失败&#xff0c;多学些指令可以事半功倍。 一、防火墙 查看防火墙状态: systemctl status firew…