React快速入门之交互性

响应事件

  • 创建事件处理函数
    处理函数名常以handle+事件名命名
javascript 复制代码
  function handlePlayClick() {
    alert(`Playing`);
  }
  • 传递事件处理函数
    函数名、匿名两种方式!
javascript 复制代码
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:事件名,仅支持浏览器事件名称
javascript 复制代码
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响应的函数,事件继续冒泡上传...
javascript 复制代码
<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
javascript 复制代码
<div id={1} className="Toolbar" onClick={e => {
	e.stopPropagation();
	alert('You clicked on the toolbar!');
	}}>
	......
</div>
  • e.preventDefault(): 阻止了少数事件的默认浏览器行为
    例如在表单提交事件中,浏览器默认会刷新整个页面,e.preventDefault()可以阻止这一行为。
javascript 复制代码
    <form onSubmit={e => {
      e.preventDefault();
      alert('Submitting!');
    }}>......
    </form>

Hooks :以 use 开头的函数

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

状态:useState

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

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

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


function App() {
  ......
  function updateName(name) {
    updatePerson(draft => {
      draft.name = name;
    });
  }
  ......
}
2. something是一个数组时
  • 添加元素
javascript 复制代码
setArtists([
	...artists,
	{ id: nextId++, name: name } // Put new item at the end
]);
或
setArtists([
  { id: nextId++, name: name }, // Put new item at the head
  ...artists 
]);
  • 删除元素
javascript 复制代码
setArtists(
  artists.filter(a => a.id !== artist.id)
);
  • 使用返回新数组的方法(a:元素,i:下标)
    map():遍历每个元素
    filter():返还条件为true的元素
javascript 复制代码
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()方法拷贝数组后,操作新数组。
    ⚠️这种拷贝都是浅拷贝(新数组中的对象仍然是对原始对象的引用)
javascript 复制代码
/ 拷贝
let citrus = [...fruits] / 拷贝
let citrus = fruits.slice(); / 全部拷贝
let citrus = fruits.slice(1, 3); / 拷贝fruits[1,3)
/ 操作
const item = citrus.find(a => a.id === 2);
citrus.reverse();
citrus.sort();
/ 更新
setFruits(citrus);
  • 当然,当数组元素为对象时,仍要创建一个新的值去更新
javascript 复制代码
    setMyList(myList.map(artwork => {
      return { ...artwork, seen: nextSeen };
    }));

状态与渲染

  • ⚠️React将something状态值存储在组件之外(组件存储的只是状态值的快照),每次setSomething()更改的是组件外的状态值,当组件"稳定"(没有代码在执行)后 ,React会更改DOM从而触发组件渲染,通过渲染将更新后的状态值刷新到页面!!!
  • 代码中number默认为0
    当点击🔘+5时,alert(number)的值仍然是0!
javascript 复制代码
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>
    </>
  )
}
  • 那如果需要多次修改状态值时,怎么办?传入函数(参数名通常为状态值首字母)
javascript 复制代码
setNumber(n => n + 1);
setNumber(n => n + 1);
setNumber(n => n + 1);
setEnabled(e => !e);
setLastName(ln => ln.reverse());
setFriendCount(fc => fc * 2);
相关推荐
辻戋2 小时前
从零实现React Scheduler调度器
前端·react.js·前端框架
徐同保2 小时前
使用yarn@4.6.0装包,项目是react+vite搭建的,项目无法启动,报错:
前端·react.js·前端框架
Qrun3 小时前
Windows11安装nvm管理node多版本
前端·vscode·react.js·ajax·npm·html5
中国lanwp3 小时前
全局 npm config 与多环境配置
前端·npm·node.js
JELEE.4 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
TeleostNaCl6 小时前
解决 Chrome 无法访问网页但无痕模式下可以访问该网页 的问题
前端·网络·chrome·windows·经验分享
前端大卫7 小时前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友7 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理9 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design
毕设十刻9 小时前
基于Vue的学分预警系统98k51(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js