函数组件解析

 

React框架对前端开发的意义

1.页面组件化

组件化使用更加方便,维护更加容易,适合做复用:在其他页面也可以使用。

React函数组件(首字母要大写)

组件被调用的位置,填入的就是组件返回的部分。

2.数据驱动视图

数据的变化会引起视图的变化,对数据修改后React会修改Dom元素。

style样式

行间样式、全局样式、局部样式

行间样式

function App(){
    const myStyle={width: '100px',height: '100px' ,background:'red'}
    return (
    <div style={myStyle}>hello App</div>
    )
}
export default App

全局样式

import "全局样式.css"
function App(){
    
    return(
        <>
        <div className="box3"> aaaaaaaa</div>
        </>
        
    )
}
export default App

全局样式.css

.box{
    width: 300px;
    height: 100px;
    background: blue;
}

 

局部样式

​
import sytle from '局部样式.module.css'
​
function App(){
    
    return(
        <>
       
        <div className={sytle.box2}>aaaaaaaaaa</div> 
      
        </>
        
    )
}
export default App

局部样式.css

​
​
.box2{background:green;
color: white;}
.head-title{
    background: pink;
​
}
.head-title-icon{
    background: yellow;
}

className模块

安装:

npm i classnames

 

引入:

import classNames from {classnames}

示例:

​
import style from '局部样式.module.css'
import classNames from "classnames"
​
function App () {
​
  const myClass = classNames({
    box1: true,
    box2: false,
    [style.headTitle]: true
  })
​
  return (
    <>     
      <div className={myClass}>
        hello App
      </div>
    </>
  )
}
​
export default App 

事件

事件的概念

在编程中,事件是指在特定情况下发生的动作,如用户点击按钮、提交表单、移动鼠标等。在 React 中,事件是用户与组件交互的触发点。通过处理事件,开发者可以对用户的操作做出响应,从而更新 UI、发送网络请求、或执行其他逻辑。

在react中事件的命名要采用小驼峰式的写法。

在 React 中,事件处理函数是响应用户交互的主要方式。添加事件处理函数非常简单,通常通过 JSX 属性进行绑定。

示例

function App(){
    const headleClick=()=>{
        console.log(123)
    }
    const headleClick2=(num)=>{
        return ()=>{
            console.log(num)
        }
    }
    const headleClick3=(num,e)=>{
        console.log(num,e)
    }
    return (
        <div>
            hello app
            <button onClick={headleClick}>点击</button>
            <button onClick={headleClick2(123)}>点击2-传参</button>
            <button onClick={(e)=>headleClick3(123,e)}>点击3-传参</button>
            <button onClick={headleClick3}>点击4-传参</button>
        </div>
    )
}
export default App 

我们把事件中的函数部分抽离出去,用变量来表示。

条件渲染

1.使用if-else

function App () {
  
  let content
  let count = 0
  if( count > 1 ) {
    content = <div>hello react</div>
  }
  else {
    content = <p>hi JavaScript</p>
  }
​
  return (
    <div>
      Hello App
      <br />
      { content }
    </div>
  )
}
​
export default App 

 

2.条件运算符: ? :

function App() {
  let count = 5
  return (
    <div>
      Hello App
      <br />
      {count > 3 ? <div>hello react</div> : <p>hi JavaScript</p>}
    </div>
  )
}
​
export default App 

 

3.逻辑运算符: &&,||

 function App() {
  // && || -> 适合做一个条件的渲染
  // 而 if else 和 ? : -> 适合做多个条件的渲染
  let count = 0
  return (
    <div>
      Hello App
      <br />
      {count > 3 && <div>hello React</div>}
    </div>
  )
}
​
export default App 
​
​

列表渲染

方法1.for ,while

​
function App () {
  const list = ['aaaa', 'bbbb', 'cccc']
​
  for(let i=0;i<list.length;i++) {
    list[i] = <li>{ list[i] }</li>
  }
​
  return (
    <div>
      hello App
      <br />
      <ul>
        { list }
      </ul>
    </div>
  )
}
​
export default App 

 

方法2.map

function App () {
  const list = ['aaaa', 'bbbb', 'cccc']
​
​
  return (
    <div>
      hello App
      <br />
      <ul>
        { list.map((item) => <li>{item}</li>) }
      </ul>
    </div>
  )
}
​
export default App

 

方法3.key

function App () {
​
​
  const list = [
    { id: 0, text: 'aaaa' },
    { id: 1, text: 'bbbb' },
    { id: 2, text: 'cccc' },
  ]
​
​
​
  return (
    <div>
      hello App
      <br />
      <ul>
        { list.map((item, index) => <li key={item.id}>{item.text}</li>) }
      </ul>
    </div>
  )
}
​
export default App

 

key方法的好处:这些key会告诉React,每个组件对应着数组里的哪一项,可以帮助React推断发生了什么,从而得以正确的更新DOM树。

使用json中的id作为key的好处:当列表出现删除时,key不会因为索引值的 变化而改变。

组件的点标记写法

对象形式

const Qf = {
  Welcome() {
    return (
      <div>
        hello Welcome
      </div>
    )
  }
}
​
const { Welcome } = Qf
​
function App () {
  return (
    <div>
      hello App
      <br />
      <Qf.Welcome />
      <Welcome />
    </div>
  )
}
​
export default App 

 

函数形式

const Qf = () => {
  return (
    <div>
      hello Qf
    </div>
  )
}
​
Qf.Welcome = () => {
  return (
    <div>
      hello Welcome
    </div>
  )
}
​
const { Welcome } = Qf
​
function App () {
  return (
    <div>
      hello App
      <br />
      <Qf />
      <Qf.Welcome />
      <Welcome />
    </div>
  )
}
​
export default App

组件间的通信

使用props

1.整体接收

// 子组件 -> 整体接收
function Welcome (props) {
  return (
    <div>
      hello Welcome, { props.count }, { props.msg }
    </div>
  )
}
// 父组件
function App () {
  return (
    <div>
      hello App
      <Welcome count="123" msg="hi react" />
    </div>
  )
}
​
export default App 

 

2.解构接收

// 当传递的数据,只有属性名没有值,那么就是传递了一个布尔值true过来
function Welcome ({ count, msg, isShow }) {
  return (
    <div>
      hello Welcome, { count }, { msg }, { isShow + '' }
    </div>
  )
}
​
// 父组件
function App () {
  const count = 123
  return (
    <div>
      hello App
      <Welcome count={count} msg="hi react" isShow />
    </div>
  )
}
​
export default App 

 

3.传递事件,函数

function Welcome ({ onClick, getData }) {
  getData('我是子组件的数据')
  return (
    <div onClick={onClick}>
      hello Welcome
    </div>
  )
}
​
// 父组件
function App () {
  const count = 123
  const handleClick = () => {
    console.log(1234)
  }
  const getData = (data) => {
    console.log(data)
  }
  return (
    <div>
      hello App
      <Welcome onClick={handleClick} getData={getData} />
    </div>
  )
}
​
export default App */

 

4.使用{...}批量传输数据

// 子组件
function Welcome ({ count, msg, num, id }) {
  return (
    <div>
      hello Welcome, { count }, { msg }, { num }, { id }
    </div>
  )
}
​
// 父组件
function App () {
  const info = {
    count: 123,
    msg: 'hi react',
    num: 456,
    id: 789
  }
  return (
    <div>
      hello App
      <Welcome {...info} />
    </div>
  )
}
​
export default App

5.添加默认值

a.解构式的添加

 function Welcome ({ count=0, msg='default content' }) {
  return (
    <div>
      hello Welcome, { count }, { msg }
    </div>
  )
} 
​

b.使用defaultProps属性

​
function Welcome ({ count, msg }) {
  return (
    <div>
      hello Welcome, { count }, { msg }
    </div>
  )
}
Welcome.defaultProps = {
  count: 0,
  msg: 'default content'
}
​
function App () {
  return (
    <div>
      hello App
      <Welcome count={123} msg="hello react" />
      <Welcome />
    </div>
  )
}
​
export default App

6.限定通信时的数据类型

组件的PropTypes属性

import PropTypes from 'prop-types'
​
function Welcome ({ count, msg }) {
  return (
    <div>
      hello Welcome, { count }, { msg }
    </div>
  )
}
​
Welcome.propTypes = {
  //count: PropTypes.number
  count: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.number,
  ]),
  type: PropTypes.oneOf(['primary', 'success', 'error']),
  icon: PropTypes.element
}
​
function App () {
  return (
    <div>
      hello App
      <Welcome count={'123'} msg="hello react" type="primary" icon={ <div className="icon-close">✖</div> } />
    </div>
  )
}
​
export default App

 

组件组合

props的children属性

​
function Head ({ count }) {
  return (
    <div>
      hello Head, { count }
    </div>
  )
}
​
​
function Welcome ({ children }) {
  const count = 456
  return (
    <div>
      hello Welcome
      { children }
    </div>
  )
}
​
function App () {
  const count = 123
  return (
    <div>
      hello App
      <Welcome>
        <Head count={count} />//作用域来自于当前的数据
      </Welcome>
    </div>
  )
}
​
export default App 
​
输出123

 

 

 function Head ({ count }) {
  return (
    <div>
      hello Head, { count }
    </div>
  )
}
​
​
function Welcome () {
  const count = 456
  return (
    <div>
      hello Welcome
      <Head count={count} />//在挂载count时,使用当前作用域的count
    </div>
  )
}
​
function App () {
  const count = 123
  return (
    <div>
      hello App
      <Welcome />
    </div>
  )
}
​
export default App 
​
输出456

 

分别传递多组数据:直接写在welcom组件里,用属性挂载jsx

​
function Welcome ({ top, bottom }) {
  return (
    <div>
      { top }
      hello Welcome
      { bottom }
    </div>
  )
}
​
function App () {
  return (
    <div>
      hello App
      <Welcome
        top={<div>aaaaaaaaaaa</div>}
        bottom={<div>bbbbbbbbbbb</div>}
      />
    </div>
  )
}
​
export default App

组件必须是一个纯函数

纯函数

1.只负责自己的任务,它不会更改在该函数调用前就已经存在的变量和对象

 

// 不纯的函数
 let bar = 1
function foo() {
  bar++
}
foo() 
​
// 纯函数
 function foo() {
  let bar = 1
  bar++
}
foo() 

2.输入相同,则输出相同。给定相同的输入,纯函数总是返回相同的结果

// 不纯的函数
 function foo(n) {
  return Math.random()
}
foo(2)
foo(2)
foo(2) 
​
​
// 纯函数
 function foo(n) {
  return n * 2
}
foo(2)
foo(2)
foo(2) 
​

状态和变量的区别

随时间变化的数据称为状态(state),状态是可以驱动视图的,而普通变量不行

useState:引入状态的钩子,可以创建状态和修改状态的方法。

const [count ,setCount]=useState(0)
​
const [状态,改变状态的方法]=useState(初始值)

为什么普通变量不能改变视图?

:因为不会重新渲染jsx

为什么state状态可以改变视图?

重新触发函数组件,并且state状态具备组件的记忆。

状态如何改变视图?

1.触发一次渲染:a.如果是组件的初次渲染:createRoot().render() 。b.内部状态更新时,触发渲染送入队列。

2.渲染组件:a.初次时:调用根组件。b.更新时:重新执行函数

3.提交到DOM上:a.初次时:appendChild( ) DOM API b. 更新时:更新有差异的DOM节点

 

多状态是如何进行正确记忆的

在同一组件的每次渲染中,useState都依托于一个稳定的调用顺序

​
 import { useState } from 'react'
function App() {
  const [count, setCount] = useState(0)
  const [count2, setCount2] = useState(0)
  const [count3, setCount3] = useState(0)
  const handleClick = () => {
    setCount(count + 1)
  }
  return (
    <div>
      hello App
      <button onClick={handleClick}>点击</button>
      {count}, {count2}, {count3}
    </div>
  )
}
​
export default App 

 

在React内部,为每一个组件保存了一个数组,其中每一项都是一个state对。它维护当前state对的索引值,在渲染之前将其设置为0,每次调用useState时,React都会为你提供一个state对并增加索引值。

不要在逻辑中使用useState,会打乱调用顺序

import { useState } from 'react'
let num = 0
function App() {
  const [count, setCount] = useState(0)
  if(num == 0) {
    const [count2, setCount2] = useState(0)
  }
  const [count3, setCount3] = useState(0)
  const handleClick = () => {
    setCount3(count3 + 1)
    setCount(2)
    num++
  }
  return (
    <div>
      hello App
      <button onClick={handleClick}>点击</button>
      {count}, {count3}
    </div>
  )
}
​
export default App
​
​

状态的快照

useState实际上是生成了一张快照,在整个代码中使用的都是这张快照,count的改变发生在下一次刷新时。

 import { useState } from "react"
​
function App () {
  const [count, setCount] = useState(0)
  const handleClick = () => {
    setCount(count + 1)//1
    setCount(count + 1)//1
    setCount(count + 1)//1
    console.log( count )//1
  }
  return (
    <div>
      hello App
      <button onClick={handleClick}>点击</button>
      { count }
    </div>
  )
}
​
export default App  

状态队列与自动批处理

 

自动批处理

合并多个setState()、只触发一次render() 保证了性能

import { useState } from "react"
​
function App () {
  const [count, setCount] = useState(0)
  const handleClick = () => {
    setCount(count + 1)
    setCount(count + 1)
    setCount(count + 1)
    console.log( count )
  }
  console.log(123)
  return (
    <div>
      hello App
      <button onClick={handleClick}>点击</button>
      { count }
    </div>
  )
}
​
export default App 
​

更新函数

​
import { useState } from "react"
​
function App () {
  const [count, setCount] = useState(0)
  const handleClick = () => {
    //setCount(count + 1)   // 0 + 1 找的是当前作用域下的快照
    // setCount((c) => c + 1)  // 0 + 1  c和快照没关系
      
    //setCount(count + 1)   // 0 + 1 
    //setCount(count + 1)   // 0 + 1 
    //setCount(count + 1)   // 0 + 1
    // setCount((c) => c + 1)  // 1 + 1
    // setCount((c) => c + 1)  // 2 + 1
      
      
    // setTimeout(()=>{
    //   console.log( count )  // 0
    // }, 3000)
​
    setCount(count + 1)   // setCount((c) => count + 1)  
  }
  return (
    <div>
      hello App
      <button onClick={handleClick}>点击</button>
      { count }
    </div>
  )
}
​
export default App

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值