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

React尝鲜

组件

React的组件就是一个js函数,函数内部return一个由jsx语法创建的html代码片段。

//MyComp.js
export default function MyComp(){return (<h1>我是新组件MyComp</h1>)
} 

在需要引入组件的地方import导入组件,并放在相应位置

//App.js
import MyComp from './components/MyComp'
function App() {return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><p>编辑 <code>src/App.js</code> 并且重新加载</p><aclassName="App-link"href="https://reactjs.org"target="_blank"rel="noopener noreferrer">Learn React</a>//新组件<MyComp></MyComp></header></div>);
}export default App;

需要注意的地方

  • 组件名称首字母必须大写
  • 如果return的内容太大,不能与return 处于同一行,则需要对return的内容添加小括号()

JSX规则

  1. 要从组件返回多个元素,使用一个父标签封装他们。如果你不想在标记中额外添加div可以使用<></>
  2. JSX要求标记被显示闭合:像这样的自闭标签一定要写成,想
  3. 这样的环绕标签一定要写成
  4. 驼峰式大多数东西。比如class要命名成className

JSX中使用大括号

js中的变量可以通过"{}"的方式传入JSX中,从而使html中渲染的数据可以得到控制。任何 JavaScript 表达式都可以在大括号之间工作,包括像 formatDate() 这样的函数调用:

export default function TodoList() {const name = 'Gregorio Y. Zara';return (<h1>{name}'s To Do List</h1>);
}
//函数调用
const today = new Date();function formatDate(date) {return new Intl.DateTimeFormat('en-US',{ weekday: 'long' }).format(date);
}export default function TodoList() {return (<h1>To Do List for {formatDate(today)}</h1>);
}
何处使用{}
  • 作为文本 直接在 JSX 标签内<div>{name}'s To Do List\.</div>有效,但<{tag}>Gregorio Y. Zara's To Do List</{tag}>无效。
  • 作为属性 紧跟在 = 符号之后: src={avatar} 将读取 avatar 变量,但 src=“{avatar}” 将传递字符串 “{avatar}”。
使用双大括号

除了字符串、数字和其他js表达式外,甚至可以在jsx中插入对象。在jsx中插入对象,必须将对象封装在另一个对大括号中。person={{name:'henry',age:22}}
一般在插入内联样式的时候会用到双大括号

export default function TodoList() {return (<ul style={{backgroundColor: 'black',color: 'pink'}}><li>Improve the videophone</li><li>Prepare aeronautics lectures</li><li>Work on the alcohol-fuelled engine</li></ul>);

传递属性

React通过传递属性(props)相互通信。每个父组件都可以通过给他们属性将一些信息传递给他们的子组件

第一步 将属性传递给子组件

首先在父组件中给子组件添加属性

export default function Profile() {return (<Avatarperson={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}size={100}/>);
}

第二步 子组件读取属性

function Avatar({ person, size }) {// person and size are available here
}

默认属性

可以在接受时为属性添加默认值

function Avatar({ person, size = 100 }) {// ...
}

使用JSX的展开语法转发属性

当组件需要把自身接受到的属性转发给子组件时,可用展开语法精简代码

function Profile({ person, size, isSepia, thickBorder }) {return (<div className="card"><Avatarperson={person}size={size}isSepia={isSepia}thickBorder={thickBorder}/></div>);
}

简化后:

function Profile(props) {return (<div className="card"><Avatar {...props} /></div>);
}

传递JSX

可以把组件作为prop参数传递,父组件通过{children}来接收,类似于vue的slot

import Avatar from './Avatar.js';function Card({ children }) {return (<div className="card">{children}</div>);
}export default function Profile() {return (<Card><Avatarsize={100}person={{ name: 'Katsuko Saruhashi',imageId: 'YfeOqp2'}}/></Card>);
}

条件渲染

通过if判断渲染

通过变量来控制返回的jsx

if (isPacked) {return <li className="item">{name}</li>;
}
return <li className="item">{name}</li>;

条件(三元)运算符 (? : )

还可以用更简洁的三元运算符进行条件渲染

return (<li className="item">{isPacked ? name + ' ✔' : name}</li>
);

逻辑与运算符(&&)

当你想在条件为真时渲染一些jsx,或者什么也不渲染,可以使用“&&”

return (<li className="item">{name} {isPacked && '✔'}</li>
);

渲染列表

可以通过js数组的filter() 和 map() 来过滤数据数组并将其转换为组件数组。

从数组中渲染组件

const people = ['Creola Katherine Johnson: mathematician','Mario José Molina-Pasquel Henríquez: chemist','Mohammad Abdus Salam: physicist','Percy Lavon Julian: chemist','Subrahmanyan Chandrasekhar: astrophysicist'
];export default function List() {const listItems = people.map(person =><li>{person}</li>);return <ul>{listItems}</ul>;
}

通过filter()方法过滤条目数组

const people = [{id: 0,name: 'Creola Katherine Johnson',profession: 'mathematician',
}, {id: 1,name: 'Mario José Molina-Pasquel Henríquez',profession: 'chemist',
}, {id: 2,name: 'Mohammad Abdus Salam',profession: 'physicist',
}, {name: 'Percy Lavon Julian',profession: 'chemist',  
}, {name: 'Subrahmanyan Chandrasekhar',profession: 'astrophysicist',
}];
export default function List() {const chemists = people.filter(person =>person.profession === 'chemist');const listItems = chemists.map(person =><li><imgsrc={getImageUrl(person)}alt={person.name}/><p><b>{person.name}:</b>{' ' + person.profession + ' '}known for {person.accomplishment}</p></li>);return <ul>{listItems}</ul>;
}

响应事件

在组件内定义事件响应函数,并把函数作为属性值传递到JSX上

export default function Button() {function handleClick() {alert('You clicked me!');}return (<button onClick={handleClick}>Click me</button>);
}

也可以直接在JSX中内联事件

<button onClick={function handleClick() {alert('You clicked me!');
}}>

状态:组件的内存

组件内需要存储的数据叫做状态。状态相当于组件的内存,存放着需要记忆的数据。

使用useState()

import { useState } from 'react';

创建state使用useState()来创建,他需要给定一个初始值作为参数。创建一个数组来接收这个状态,这个数组包含一个state的名称,和一个修改这个state的方法。

const [isSent, setIsSent] = useState(false);
const [message, setMessage] = useState('Hi!');

修改state的值

state的值不能直接修改,需要借用useState提供的第二个参数。

setIsSent(true);

setXXX()方法会触发React进行重新渲染。

将state中的引用类型视为只读

如果state的值是数组或者对象,那么使用setXXX()方法修改时就不能直接修改原值,而是需要重新创建一份赋给state

对象

修改对象一般通过扩展运算符、Object.assign()等方法来复制原对象然后重新赋值给state

export default function Form() {const [person, setPerson] = useState({firstName: 'Barbara',lastName: 'Hepworth',email: 'bhepworth@sculpture.com'});function handleFirstNameChange(e) {setPerson({//通过扩展运算符复制一份原对象给新对象再赋值给state...person,firstName: e.target.value});}

数组

修改数组一般通过map()、filter()、slice()等方法复制一份新数组再赋值给state

import { useState } from 'react';let nextId = 0;export default function List() {const [name, setName] = useState('');const [artists, setArtists] = useState([]);return (<><h1>Inspiring sculptors:</h1><inputvalue={name}onChange={e => setName(e.target.value)}/><button onClick={() => {setArtists([...artists,{ id: nextId++, name: name }]);}}>Add</button><ul>{artists.map(artist => (<li key={artist.id}>{artist.name}</li>))}</ul></>);
}

Immer插件

如果对象或数组有深层嵌套用普通的复制方法比较复杂,使用immer插件可以简化操作。它可以让你像修改原数组那样直接修改对象的属性或数组中的某项值,但其实他在内部已经帮你创建了一个副本并赋予state
步骤

  1. 运行 npm install use-immer 以将 Immer 添加为依赖
  2. 然后用 import { useImmer } from ‘use-immer’ 替换 import { useState } from ‘react’

使用方法

import { useImmer } from 'use-immer';export default function Form() {const [person, updatePerson] = useImmer({name: 'Niki de Saint Phalle',artwork: {title: 'Blue Nana',city: 'Hamburg',image: 'https://i.imgur.com/Sd1AgUOm.jpg',}});function handleNameChange(e) {updatePerson(draft => {draft.name = e.target.value;});}function handleTitleChange(e) {updatePerson(draft => {draft.artwork.title = e.target.value;});}

组件通信

父传子通过props进行,子传父通过调用父组件定义的方法来实现,此方法通过prop传递给子组件
父传子

//子组件
function Child (prop){return <div>{props.msg}</div>
}//父组件
function Father (){
let msg = 'hello world'return (<Child msg={msg}></Child>)
}

子传父

// 子传父,通过 props 调用父组件的方法
this.props.handleClick(xxx)// 父组件中
<Child handleClick={this.handleClick}></Child>

兄弟传值
可以通过context来进行兄弟组件传值。context不仅可以用于兄弟组件传值,还可以用于更复杂关系的组件的传值。
引入

export const { Provider, Consumer } = React.createContext("sky")

在兄弟组件的共同上层定义一个Provider,通过provider中的value属性把想要传递的值赋予它

export default class ClassComp extends React.Component {constructor(props) {super(props)this.state = {name: 'tracer'}}render() {return (<Provider value={this.state.name}><div><h1>爷爷:{this.state.name}</h1><ClassComp2 /></div></Provider>)}
}

这个Provider所在的组件的所有下级都将共享这个数据。后代组件通过在该组件中创建的Consumer来获取值。

import { Consumer } from './ClassComp' //引入
export default class ClassComp2 extends React.Component {constructor(props) {super(props)this.state = {}}render() {return(<Consumer>{(value)=><div><h1>爸爸:{value}</h1><ClassComp3/></div>}</Consumer>)}
}
http://www.lryc.cn/news/265956.html

相关文章:

  • 锯齿云服务器租赁使用教程
  • HarmonyOS和OpenHarmony的区别
  • Redis Stream消息队列之基本语法与使用方式
  • 制造行业定制软件解决方案——工业信息采集平台
  • [python]用python实现对arxml文件的操作
  • pdf 在线编辑
  • 自然语言处理(NLP):理解语言,赋能未来
  • FastAPI使用loguru时,出现重复日志打印的解决方案
  • 构建每个聚类的profile和deletion_mean特征
  • Milvus数据一致性介绍及选择方法
  • 异常处理和单元测试python
  • 蓝牙物联网在汽车领域的应用
  • 用23种设计模式打造一个cocos creator的游戏框架----(二十二)原型模式
  • paddle 55 使用Paddle Inference部署嵌入nms的PPYoloe模型(端到端fps达到52.63)
  • 自动化测试工具-Selenium:WebDriver的API/方法使用全解
  • 如何通过蓝牙串口启动智能物联网?
  • Linux---基础操作命令
  • uniapp怎么动态渲染导航栏的title?
  • 【机器学习】决策树
  • [node] Node.js的全局对象Global
  • 完整的 Meteor NPM 集成
  • 智能优化算法应用:基于骑手优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码
  • 解决 MATLAB 遗传算法中 exitflg=4 的问题
  • 云卷云舒:云原生业务应用成熟度模型
  • STM32的以太网外设+PHY(LAN8720)使用详解(5):MAC及DMA配置
  • GitHub、Gitee、Gitlab共用一个SSH密钥配置
  • ClickHouse(19)ClickHouse集成Hive表引擎详细解析
  • 用C求斐波那契数列-----(C每日一编程)
  • 在Jetpack Compose中使用ExoPlayer实现直播流和音频均衡器
  • 持续集成交付CICD:Jira 远程触发 Jenkins 实现更新 GitLab 分支