别人中秋节都出去玩或者回家团圆了,只有我还在图书馆学习,我爱学习,从0到1学习react(第二天)

react文档学习之

一、描述ui:

1、组件

可以使用html中的标签的本身样式在页面中使用,使其产生错落的格式:

在react中:

        -函数和导入组件都需要首字母大写,否则将会在控制台报出警告并且无法渲染

        -导出使用export default

2、使用 JSX 书写标签语言

介绍:JSX 是 JavaScript 语法扩展,可以在 JavaScript 文件中书写类似 HTML 的标签

将 HTML 转化为 JSX:

假设你想把一些标签直接放到组件中使用,并不一定是直接可用的,如:

<h1>海蒂·拉玛的待办事项</h1>

<img

src="https://i.imgur.com/yXOvdOSs.jpg"

alt="Hedy Lamarr"

class="photo"

>

<ul>

<li>发明一种新式交通信号灯

<li>排练一个电影场景

<li>改进频谱技术

</ul>

页面报错如下: 

可以根据报错的提示来逐步修改,也可以提前了解jsx的规则:

1、只能返回一个根节点

一个组件中有多个元素,需要用一个父标签将他们包裹起来,如果不想渲染额外的标签,可以使用<>和</>元素来替代(空标签:Fragment )

2、标签需要闭合

3、使用驼峰法命名给大部分属性命名

变量名称不能包含 - 符号或者像 class 这样的保留字(class要改为className)

修改完以后的代码如下:

3、在 JSX 中通过大括号使用 JavaScript

注:如果要使用内联样式,大括号中需包裹一个对象 

4、将 Props 传递给组件

1、将变量或者文本传递给组件

2、将JSX作为子组件传递

function Avatar ({src,alt}) {
  return (
    <img
      src={src}
      alt={alt}
    />
  )
}
function Card ({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  )
}
export default function ProApp() {
  const src = 'https://i.imgur.com/7vQD0fPs.jpg'
  return (
    <Card>
      <Avatar
        src={src}
        alt='这是一个图片'
      />
    </Card>
  )
}

5、条件渲染

通过使用 JavaScript 的 if 语句、&&? : 运算符来选择性地渲染 JSX

实现同样效果还可以:

function ListItem ({ name, isPacked }) {
  return <li>{ isPacked ? name + '✅' : name}</li>
}

或者:

function ListItem ({ name, isPacked }) {
  return <li>{ name } { isPacked && '✅' }</li>
}

6、渲染列表

通过 JavaScript 的数组方法 来操作数组中的数据,从而将一个数据集渲染成多个相似的组件

const people = [
  {
    id: 0,
    name: '凯瑟琳·约翰逊',
    profession: '数学家',
    accomplishment: '太空飞行相关数值的核算'
  },
  {
    id: 1,
    name: '马里奥·莫利纳',
    profession: '化学家',
    accomplishment: '北极臭氧空洞的发现'
  },
  {
    id: 2,
    name: '穆罕默德·阿卜杜勒·萨拉姆',
    profession: '物理学家',
    accomplishment: '关于基本粒子间弱相互作用和电磁相互作用的统一理论'
  },
  {
    id: 3,
    name: '珀西·莱温·朱利亚',
    profession: '化学家',
    accomplishment: '开创性的可的松药物、类固醇和避孕药的研究'
  }
]

export default function ProApp() {
  const chemists = people.filter(person =>
    person.profession === '化学家'
  )
  const listItem = chemists.map(person => 
    <li key={person.id}>
      <b>{person.name}:</b>
      {' ' + person.profession + ' '}
      {`因${person.accomplishment}而闻名于世界`}
    </li>
  )
  return (
    <ul>
      {listItem}
    </ul>
  )
}

运行结果:

7、保持组件纯粹

  • 一个组件必须是纯粹的,就意味着:
    • 只负责自己的任务。 它不会更改在该函数调用前就已存在的对象或变量。
    • 输入相同,则输出相同。 给定相同的输入,组件应该总是返回相同的 JSX。
  • 渲染随时可能发生,因此组件不应依赖于彼此的渲染顺序。
  • 你不应该改变任何用于组件渲染的输入。这包括 props、state 和 context。通过 “设置” state 来更新界面,而不要改变预先存在的对象。
  • 努力在你返回的 JSX 中表达你的组件逻辑。当你需要“改变事物”时,你通常希望在事件处理程序中进行。作为最后的手段,你可以使用 useEffect。

二、添加交互

1、响应事件 

React 允许你向 JSX 中添加事件处理程序。事件处理程序是你自己的函数,它将在用户交互时被触发,如点击、悬停、焦点在表单输入框上等等

也可以将事件处理函数作为 props 传递

按照惯例,事件处理函数 props 应该以 on 开头,后跟一个大写字母。

function Button({onSmash, children}) {
  return (
    <button onClick={onSmash}>
      {children}
    </button>
  )
}
export default function App () {
  return (
    <Button onSmash={() => alert('播放视频!')}>
      播放视频
    </Button>
  )
}

注意:

2、State:组件的记忆

组件通常需要根据交互更改屏幕上显示的内容。输入表单应该更新输入字段,单击轮播图上的“下一个”应该更改显示的图片,单击“购买”应该将商品放入购物车。组件需要“记住”某些东西:当前输入值、当前图片、购物车。在 React 中,这种组件特有的记忆被称为 state

useState Hook 提供了这两个功能:

  1. State 变量 用于保存渲染间的数据。
  2. State setter 函数 更新变量并触发 React 再次渲染组件。

useState 的唯一参数是 state 变量的初始值。在这个例子中,index 的初始值被useState(0)设置为 0

每次你的组件渲染时,useState 都会给你一个包含两个值的数组:

  1. state 变量 (index) 会保存上次渲染的值。
  2. state setter 函数 (setIndex) 可以更新 state 变量并触发 React 重新渲染组件。

注意:

State 是隔离且私有的:如果你渲染同一个组件两次,每个副本都会有完全隔离的 state!改变其中一个不会影响另一个。

3、把一系列 state 更新加入队列

设置组件 state 会把一次重新渲染加入队列。但有时你可能会希望在下次渲染加入队列之前对 state 的值执行多次操作。

 - React 会对 state 更新进行批处理

在下面的示例中,你可能会认为点击 “+3” 按钮会使计数器递增三次,因为它调用了 setNumber(number + 1) 三次:

import { useState } from 'react';

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

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 1);
        setNumber(number + 1);
        setNumber(number + 1);
      }}>+3</button>
    </>
  )
}

但结果却是1,这是因为React 会等到事件处理函数中的 所有 代码都运行完毕再处理你的 state 更新。 这就是重新渲染只会发生在所有这些 setNumber() 调用 之后 的原因。

 - 在下次渲染前多次更新同一个 state 

这是一个不常见的用例,但是如果你想在下次渲染之前多次更新同一个 state,你可以像 setNumber(n => n + 1) 这样传入一个根据队列中的前一个 state 计算下一个 state 的 函数,而不是像 setNumber(number + 1) 这样传入 下一个 state 值。这是一种告诉 React “用 state 值做某事”而不是仅仅替换它的方法。

import { useState } from 'react';

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

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(n => n + 1);
        setNumber(n => n + 1);
        setNumber(n => n + 1);
      }}>+3</button>
    </>
  )
}

在这里,n => n + 1 被称为 更新函数。当你将它传递给一个 state 设置函数时:

  1. React 会将此函数加入队列,以便在事件处理函数中的所有其他代码运行后进行处理。
  2. 在下一次渲染期间,React 会遍历队列并给你更新之后的最终 state。

4、更新 state 中的对象

state 中可以保存任意类型的 JavaScript 值,包括对象。但是,你不应该直接修改存放在 React state 中的对象。相反,当你想要更新一个对象时,你需要创建一个新的对象(或者将其拷贝一份),然后将 state 更新为此对象。

 - 将 state 视为只读的

换句话说,应该 把所有存放在 state 中的 JavaScript 对象都视为只读的

import { useState } from 'react';

export default function Counter() {
  const [person, setPerson] = useState({
    name: 'jack',
    age: 22
  });

  return (
    <>
      <h1>小明的男朋友是{person.name},他今年{person.age}</h1>
      <button onClick={() => {
        setPerson({
          name: '张三',
          age: 18
        })
      }}>换人</button>
    </>
  )
}

当对象结构比较复杂的时候,修改的代码也会变得冗长如:

import { useState } from 'react';

export default function Counter() {
  const [person, setPerson] = useState({
    name: 'jack',
    age: 22,
    school: {
      name: '北京大学',
      address: '北京'
    }
  });
  function handleSchoolChange (e) {
    setPerson({
      ...person,
      school: {
        ...person.school,
        name: e.target.value
      }
    })
  }
  return (
    <>
      <h1>小明的男朋友是{person.name},他今年{person.age},他的学校是{person.school.name}</h1>
      <button onClick={() => {
        setPerson({
          ...person,
          name: '张三',
          age: 18
        })
      }}>换人</button>
      <div>
        学校名称:
        <input
          value={person.school.name}
          onChange={handleSchoolChange}
        />
      </div>
    </>
  )
}

 - 使用 Immer 编写简洁的更新逻辑

如果 state 有多层的嵌套,应该考虑 将其扁平化。但是,如果你不想改变 state 的数据结构,你可能更喜欢用一种更便捷的方式来实现嵌套展开的效果。Immer 是一个非常流行的库,它可以让你使用简便但可以直接修改的语法编写代码,并会帮你处理好复制的过程。通过使用 Immer,你写出的代码看起来就像是你“打破了规则”而直接修改了对象。

尝试使用 Immer:

  1. 运行 npm install use-immer 添加 Immer 依赖
  2. 用 import { useImmer } from 'use-immer' 替换掉 import { useState } from 'react'

将上面例子修改为Immer:

import { useImmer } from 'use-immer'

export default function Counter() {
  const [person, setPerson] = useImmer({
    name: 'jack',
    age: 22,
    school: {
      name: '北京大学',
      address: '北京'
    }
  });
  function handleSchoolChange (e) {
    setPerson(draft => {
      draft.school.name = e.target.value
    })
  }
  return (
    <>
      <h1>小明的男朋友是{person.name},他今年{person.age},他的学校是{person.school.name}</h1>
      <button onClick={() => {
        setPerson(draft => {
          draft.name = '张三'
          draft.age = 18
        })
      }}>换人</button>
      <div>
        学校名称:
        <input
          value={person.school.name}
          onChange={handleSchoolChange}
        />
      </div>
    </>
  )
}

5、更新 state 中的数组 

数组和对象一样,当你想要更新存储于 state 中的数组时,你需要用一个新数组设置 state。

下面是常见数组操作的参考表。当你操作 React state 中的数组时,你需要避免使用左列的方法,而首选右列的方法:

或者,你可以使用 Immer ,这样你便可以使用表格中的所有方法了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值