- 最近在学React,笔记同步一下
- 回退到导航分享页
描述UI
- React 组件本质上是可以任意添加标签的 JavaScript 函数
- 组件可以导入和导出
- 每个组件都是一个JS函数,JSX是Js拓展,可以显示动态信息这个可以转化Html到jsx
- 大括号访问动态属性
- 父子传参
- 条件渲染 通过Js的
if && ? :
来决定 - 列表渲染 filiter和map 通常需要绑定key
- 保证组件纯粹(只负责自己的责任:输入相同那么输出也相同) 可以通过传递props来变得纯粹
- 将Ui看成一个树,展示组件和模块之间的关系
import { getImageUrl } from './utils.js'
export default function Profile() {
return (
<Card>
<Avatar
size={100}
person={{
name: 'Katsuko Saruhashi',
imageId: 'YfeOqp2'
}}
/>
</Card>
);
}
function Avatar({ person, size }) {
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>);
}
function Card({ children }) {
return (
<div className="card">
{children}//类似于slot
</div>
);
}
// ----------- section 2
function Item({ name, isPacked }) {
return (
<li className="item">
{name} {isPacked && '✅'}
// 通过Js的&&来决定后边是否返回
</li>
);
}
export default function PackingList() {
return (
<section>
<h1>Sally Ride's Packing List</h1>
<ul>
<Item
isPacked={true}
name="Space suit"
/>
<Item
isPacked={false}
name="Photo of Tam"
/>
</ul>
</section>
);
}
// ----------- section 8
let guest = 0;
function Cup() {
// Bad: changing a preexisting variable!
guest = guest + 1;//这个就不是纯粹的函数
return <h2>Tea cup for guest #{guest}</h2>;
}
你的第一个组件
- 导出组件export default是标准JS语法
- 推荐ChakraUI和MaterialUI快速启动项目
- React 组件是常规的 JavaScript 函数,但 组件的名称必须以大写字母开头,否则它们将无法运行!
- 首先定义一个JS函数(大写字母开头),书写html标签,返回JSX
- React看见小写,知道是HTML标签;如果大写P开头,React将知道使用组件
- 补充:
- 你可以只定义组件一次,然后按需多处和多次使用以及嵌套引用(注意不是嵌套定义,嵌套定义将非常慢并且导致Bug)
- 需要父组件数据,应该是Props传递而不是嵌套定义
export default function Profile() {
return (//如果不在同一行 必须用圆括号包裹起来 否则return 下边将被忽略
<img
src="https://i.imgur.com/MK3eW3Am.jpg"
alt="Katherine Johnson"
/>
)
}
组件导入导出
- 流程:新建一个Js文件,导出(默认或者具名)一个函数组件,导入(默认或者具名)
- 导入
.js
后缀有没有都可以,只是有更符合原生Es模块 - 默认导出只能有一个,具名导出可以有多个(一般来说团队只会选择一种风格)
// ----------- section 具名导出
export function Profile() {
// ...
}
import { Profile } from './Gallery.js';
// ----------- section 默认导出
export default function Gallery() {
return (
<section>
<h1>了不起的科学家们</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
import Gallery from './Gallery.js';
// ----------- section 使用
export default function App() {
return (
<Gallery />
);
}
使用JSX
- 网站交互性越来越决定页面内容: 在React中渲染逻辑和标签共同存在于同一个地方——组件.
- JSX是语法拓展,React是Js库.JSX和React是独立的,只不过经常一起使用
- Jsx规则
- 只能返回一个根元素,使用div或者
<></>
(Fragment)包裹起来 - 标签必须闭合
- 必须是驼峰命名法给大部分属性命名(历史原因aria- ,data- 只能用
-
符号)
export default function Bio() {
return (
<>//只能一个根元素
<div className="intro">//大驼峰
<h1>欢迎来到我的站点!</h1>
</div>
<p className="summary">
你可以在这里了解我的想法.
<br/>//这里是单标签
<b>还有科学家们的<i>照片</i></b>!
</p>
</>
);
}
摘要
- 由于渲染逻辑和标签是紧密相关的,所以 React 将它们存放在一个组件中.
- JSX 类似 HTML,不过有一些区别.如果需要的话可以使用 转化器 将 HTML 转化为 JSX.
- 错误提示通常会指引你将标签修改为正确的格式.
Jsx使用大括号
现在你知道了为什么我们需要 JSX 以及如何在组件中使用它:
1. 引用场景:在标签中添加一些 JavaScript 逻辑或者引用动态的属性
2. 体现形式:引号传递字符串,以及使用Js变量函数和对象(对应的也要写成大驼峰命名法)
3. 使用限制:只能在JSX标签内和=
后边的属性使用大括号
const person = {
name: 'Gregorio Y. Zara',
theme: {
backgroundColor: 'black',
color: 'pink'
}
};
export default function Avatar() {
const avatar = 'https://i.imgur.com/7vQD0fPs.jpg';
const description = 'Gregorio Y. Zara';
return (
<>
<img
className="avatar"// 这个就是引号传递一个字符串 体现1
src={avatar}// 动态指定src和alt的值 体现2 变量 使用{} 替代
alt={person.name}
/>
<h1
style={{backgroundColor:'black'}}//尽量少用 不过有需求可以这样写
>To Do List for {formatDate(today)}</h1>// 大括号任何Js表达式都能运行 这里是函数调用
</>
);
}
// ----------- section 易错题
const baseUrl = 'https://i.imgur.com/';
const person = {
name: 'Gregorio Y. Zara',
imageId: '7vQD0fP',
imageSize: 's',
theme: {
backgroundColor: 'black',
color: 'pink'
}
};
export default function TodoList() {
return (
<div style={person.theme}>
<h1>{person.name}'s Todos</h1>
<img
src='{baseUrl}{person.imageId}{person.imageSize}+.jpg'
//src={{baseUrl}{person.imageId}{person.imageSize}+.jpg} 这种是错误
//src={baseUrl + person.imageId + person.imageSize + '.jpg'} //可以给他封装成一个函数
alt={person.name}
/>
<ul>
<li>Improve the videophone</li>
<li>Prepare aeronautics lectures</li>
<li>Work on the alcohol-fuelled engine</li>
</ul>
</div>
);
}
摘要
现在你几乎了解了有关 JSX 的一切:
- JSX 引号内的值会作为字符串传递给属性.
- 大括号让你可以将 JavaScript 的逻辑和变量带入到标签中.
- 它们会在 JSX 标签中的内容区域或紧随属性的 = 后起作用.
- {{ 和 }} 并不是什么特殊的语法:它只是包在 JSX 大括号内的 JavaScript 对象.
Props传递给组件
- 组件中props传递和读取,指定默认值,随时间变化与传递props给jsx
- React 组件函数接受一个参数,一个props对象(他们作用基本和函数参数相同)
- 不要忘记
{}
,这种语法叫做解构,从函数参数中读取属性 - 默认值:将在没有传递或者值为undefined生效(size={null}和{0}不会生效)
- 转发props:使用展开语法转发Props(克制使用,很多地方都需要拆分意味着更好的选择是
拆分组件并将组件作为JSX传递
) - 将JSX作为子组件传递(子组件)
- 随时间变化:(props不是静态的,而是动态的.但是props是不可变的,这意味着props不能修改props只能向父组件请求一个新的)
- 不要尝试更改props:(是只读的时间快照:每次渲染都会收到新版本的 props,需要交互性设置state)
import { getImageUrl } from './utils.js';
function Avatar({ person, size =100}) {//peron和size在子组件中将是可访问的
// size=100 就是设置默认值
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}// 熟悉的Props就是这个 叫做
height={size}
/>
);
}
export default function Profile() {
return (
<div>
<Avatar
size={100}
person={{
name: 'Katsuko Saruhashi',
imageId: 'YfeOqp2'
}}
/>
<Avatar
size={80}
person={{
name: 'Aklilu Lemma',
imageId: 'OKS67lh'
}}
/>
</div>
);
}
//utils.js
export function getImageUrl(person, size = 's') {
return (
'https://i.imgur.com/' +
person.imageId +
size +
'.jpg'
);
}
// ----------- section 5
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
<Avatar
person={person}//注意是这种
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}
// ----------- section 6
import Avatar from './Avatar.js';
function Card({ children }) {// 这里就是传递进去 将props包裹在div中渲染
return (
<div className="card">
{children}
</div>
);
}
export default function Profile() {
return (
<Card>
<Avatar
size={100}
person={{
name: 'Katsuko Saruhashi',
imageId: 'YfeOqp2'
}}
/>
</Card>
);
}
摘要
- 要传递 props,请将它们添加到 JSX,就像使用 HTML 属性一样.
- 要读取 props,请使用
function Avatar({ person, size })
解构语法. - 你可以指定一个默认值,如
size = 100
,用于缺少值或值为 undefined 的 props . - 你可以使用
<Avatar {...props} />
JSX 展开语法转发所有 props,但不要过度使用它! - 像
<Card><Avatar /></Card>
这样的嵌套 JSX,将被视为Card
组件的children prop
. - Props 是只读的时间快照:每次渲染都会收到新版本的
props
. - 你不能改变 props.当你需要交互性时,你可以设置
state
.
条件渲染
- 通过JS的
if && ?:
来选择性渲染JSX - 条件返回JSX(if控制渲染逻辑)
- 选择性返回null(因为组件必须返回一些东西,你可以直接返回null)
- 选择性包含JSX,三目运算符
?:
(选择性渲染某个JSX 2选1) - 与运算符(
&&
:左侧为true返回右侧的值):(渲染某些JSX或者不做渲染 1或者0)注意左侧不要放置数字(0&&组件,将渲染0而不是不渲染)
- 选择性赋值给变量(冗长但是最灵活)
function Item({ name, isPacked }) {
if (isPacked) {
if(name) return null;//必须返回一些东西 不过会让开发者感到奇怪,因为可以直接在父组件决定是否渲染这个组件
return <li className="item">{name} ✅</li>;
}
return <li className="item">{name}</li>;//很明显 这里有重复的逻辑
}
export default function PackingList() {
return (
<section>
<h1>Sally Ride 的行李清单</h1>
<ul>
<Item
isPacked={true}
name="宇航服"
/>
<Item
isPacked={true}
name="带金箔的头盔"
/>
<Item
isPacked={false}
name="Tam 的照片"
/>
</ul>
</section>
);
}
// ----------- section 4
return (
<li className="item">
{isPacked ? name + ' ✅' : name}
</li>
);
function Item({ name, isPacked }) {
return (
<li className="item">
{isPacked ? (//这里就是三目运算符 不过不要使用过多 过多的最好选择还是使用组件
<del>
{name + ' ✅'}
</del>
) : (
name
)}
</li>
);
}
// ----------- section 5
return (
<li className="item">
{name} {isPacked && '✅'}
{
messageCount && <p>New messages</p>// 这里会渲染0而不是不渲染
}
{
messageCount > 0 && <p>New messages</p>//可以这样写
}
</li>
);
// ----------- section 6
function Item({ name, isPacked }) {
let itemContent = name;//通过重新声明并赋值默认值
if (isPacked) {
itemContent = (//重新赋值 不仅适用于文本,JSX也适用
<del>
{name + " ✅"}
</del>
);
}
return (
<li className="item">
{itemContent}
</li>
);
}
export default function PackingList() {
return (
<section>
<h1>Sally Ride 的行李清单</h1>
<ul>
<Item
isPacked={true}
name="宇航服"
/>
<Item
isPacked={true}
name="带金箔的头盔"
/>
<Item
isPacked={false}
name="Tam 的照片"
/>
</ul>
</section>
);
}
摘要
- 在 React,你可以使用 JavaScript 来控制分支逻辑.
- 你可以使用 if 语句来选择性地返回 JSX 表达式.
- 你可以选择性地将一些 JSX 赋值给变量,然后用大括号将其嵌入到其他 JSX 中.
- 在 JSX 中,
{cond ? <A /> : <B />}
表示 “当 cond 为真值时, 渲染 [HTML_REMOVED],否则 [HTML_REMOVED]”. - 在 JSX 中,
{cond && <A />}
表示 “当 cond 为真值时, 渲染 [HTML_REMOVED],否则不进行渲染”. - 快捷的表达式很常见,但如果你更倾向于使用 if,你也可以不使用它们