react综合(未完)

发布时间 2023-09-26 13:36:42作者: yxxcl

组件:将html/css/js写在组件内

根组件包裹子组件

React 组件是返回标签的 JavaScript 函数

组件化思想的应用:
  1. 有了组件化的思想,我们在之后的开发中就要充分的利用它。

  2. 尽可能的将页面拆分成一个个小的、可复用的组件。

  3. 这样让我们的代码更加方便组织和管理,并且扩展性也更强。

React的组件相对于Vue更加的灵活和多样,按照不同的方式可以分成很多类组件:

  1. 根据组件的定义方式,可以分为:函数组件(Functional Component )和类组件(Class Component);

  2. 根据组件内部是否有状态需要维护,可以分成:无状态组件(Stateless Component )和有状态组件(Stateful Component);

  3. 根据组件的不同职责,可以分成:展示型组件(Presentational Component)和容器型组件(逻辑组件)(Container Component);

这些概念有很多重叠,但是他们最主要是关注数据逻辑和UI展示的分离:

  • 函数组件、无状态组件、展示型组件主要关注UI的展示

  • 类组件、有状态组件、容器型组件主要关注数据逻辑

React中组件的注意事项:
  1. 在html中是不严格区分大小写的,也就是说h2写成H2, div写成DIV, 在html中都是可以被正常解析的

    但是在JSX中,标签是严格区分大小写的, 因为在JSX中首字母大写的标签会被认为是组件去进行解析,

    所以H2在JSX中是不会被作为h2去进行解析的,而是会作为组件去进行解析,但是我们并没有名其H2的组件,

    所以此时就会报H2 is not defined的错误

  2. 无论是函数式组件还是类组件,其返回的jsx只能有一个根组件,如果有多个根组件,react就不知道具体需要渲染哪一个组件为主,

    如果的确需要返回多个组件,可以使用数组作为render函数的返回值

 

export default:JavaScript 的 export 关键字使此函数可以在此文件之外访问。default 关键字表明它是文件中的主要函数。

类组件

类组件的定义有如下要求

  1. 组件的名称是大写字符开头(无论类组件还是函数组件)

  2. 类组件需要继承自 React.Component

  3. 类组件必须实现render函数, 以告诉react框架需要在页面上渲染什么结构和什么内容,

    rander (){ return{} }

return 出去的是一个大括号,意味着返回的是一个js对象,因此不能直接在return里写html。故出现了jsx的语法(原生js的扩展)。

用()在js里面写html,用{}在html里面写js。

要求将return{}的{}改为(),并且只能有一个根元素,

 

注意
  • 1.组件名必须首字母大写

  • 2.虚拟DOM元素只能有一个根元素

  • 3.虚拟DOM元素必须有结束标签

渲染类组件标签的基本流程
  • 1.React内部会创建组件实例对象

  • 2.调用render()得到虚拟DOM, 并解析为真实DOM

  • 3.插入到指定的页面元素内部

函数组件
三大核心属性
  1. state
  • state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)

  • 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)

tips:

  • 1.组件中render方法中的this为组件实例对象

  • 2.组件自定义的方法中this为undefined,如何解决?

    • a)强制绑定this: 通过函数对象的bind()

    • b)箭头函数

  • 3.状态数据,不能直接修改或更新

 

  1. props
  • 1.每个组件对象都会有props(properties的简写)属性

  • 2.组件标签的所有属性都保存在props中

作用:

  • 1.通过标签属性从组件外向组件内传递变化的数据

  • 2.注意: 组件内部不要修改props数据

 

  1. refs与事件处理

 

constructor/super

在 React 组件中,constructor 方法通常用于初始化组件的状态(state)和绑定事件处理方法。

在构造函数中,需要首先调用 super(props),它是 Component 类的构造函数。这是为了在子类(你的组件)中继承父类的所有属性和方法,并确保正确地设置组件的上下文。通过调用 super(props),你可以使用 this.props 来访问组件的属性。

在构造函数中,你可以使用 this.state 来初始化组件的状态对象。状态是组件的可变数据,当状态发生变化时,React 会重新渲染组件。通过在构造函数中设置 this.state,你可以为组件提供初始状态。

class MyComponent extends React.Component {
 constructor(props) {
   super(props);
   this.state = {
     counter: 0
  };
}
 
 componentDidMount(){
   fetch('###')
  .then(res => res.json)
   //.then(json => console.log(json.result))
  .then(json => {
     
  }
         console.log(json.result))
}
​
 render() {
   return (
     <div>
       <p>Counter: {this.state.counter}</p>
       <button onClick={this.handleClick}>Increment</button>
     </div>
  );
}
}
​

Tips:

如果直接用赋值的方式修改对象属性,对象属性所属的内存位置是不会改变的。

 

 

 

 

 

 

PureComponent

把继承类从 Component 换成 PureComponent 即可

可以减少不必要的 render 操作的次数,主要目的就是防止不必要的子组件渲染更新,从而提高性能。

PureComponent原理

当组件更新时,如果组件的 props 和 state 都没发生改变, render 方法就不会触发,省去 Virtual DOM 的生成和比对过程,达到提升性能的目的。具体就是 React 自动帮我们做了一层浅比较:

 

hooks
等价的class示例
class Example extends React.Component {
 constructor(props) {
   super(props);
   this.state = {
     count: 0
  };
}
​
 render() {
   return (
     <div>
       <p>You clicked {this.state.count} times</p>
       <button onClick={() => this.setState({ count: this.state.count + 1 })}>
         Click me
       </button>
     </div>
  );
}
}
UseState
import React, { useState } from 'react';
​
function Example() {
 // 声明一个叫 “count” 的 state 变量。
 const [count, setCount] = useState(0);
​
 return (
   <div>
     <p>You clicked {count} times</p>
     <button onClick={() => setCount(count + 1)}>
       Click me
     </button>
   </div>
);
}

在这里,useState 就是一个 Hook (等下我们会讲到这是什么意思)。通过在函数组件里调用它来给组件添加一些内部 state。React 会在重复渲染时保留这个 state。useState 会返回一对值:当前状态和一个让你更新它的函数,你可以在事件处理函数中或其他一些地方调用这个函数。它类似 class 组件的 this.setState,但是它不会把新的 state 和旧的 state 进行合并。(我们会在使用 State Hook 里展示一个对比 useState 和 this.state 的例子)。

useState 唯一的参数就是初始 state。在上面的例子中,我们的计数器是从零开始的,所以初始 state 就是 0。值得注意的是,不同于 this.state,这里的 state 不一定要是一个对象 —— 如果你有需要,它也可以是。这个初始 state 参数只有在第一次渲染时会被用到。

useState的一些注意事项
  1. 类型值初始化

初始化 useState 的首选方法是将预期的数据类型传递给它,以避免潜在的空白页错误。例如,一个空对象,如下所示,可以传递给状态:

import { useState } from "react";
​
function App() {
 // 使用期望的数据类型初始化状态
 const [user, setUser] = useState({});//初始化为{}
​
 // 渲染 UI
 return (
   <div className='App'>
     <img src={user.image} alt='profile image' />
     <p>User: {user.name}</p>
     <p>About: {user.bio}</p>
   </div>
);
}
​
export default App;

甚至更进一步,在初始化状态时定义用户对象的预期属性:

import { useState } from "react";
​
function App() {
 // 使用期望的数据类型初始化状态
 const [user, setUser] = useState({
   image: "",
   name: "",
   bio: "",
});
​
 // 渲染 UI
 return (
   <div className='App'>
     <img src={user.image} alt='profile image' />
     <p>User: {user.name}</p>
     <p>About: {user.bio}</p>
   </div>
);
}
​
export default App;

 

  1. 没有使用可选链

当尝试通过使用点(.)操作符通过相关对象来访问该对象,例如 user.names.firstName。但是,如果丢失了任何链接的对象或属性,就会出现问题。页面将中断,用户将得到一个空白页错误。

import { useState } from "react";
​
function App() {
 // 使用期望的数据类型初始化状态
 const [user, setUser] = useState({});
​
 // 渲染 UI
 return (
   <div className='App'>
     <img src={user.image} alt='profile image' />
     <p>User: {user?.names?.firstName}</p>
     <p>About: {user.bio}</p>
   </div>
);
}
​
export default App;

例如 user.names && user.names.firstname,它只在左侧表达式为真(如果 user.names存在)时计算右侧表达式。然而,这个解决方案很混乱,因为它需要对每个对象链进行多次检查。

使用可选的链接操作符(?.),你可以读取深埋在相关对象链中的属性值,而不需要验证每个引用的对象是否有效。可选的链接操作符(?.)就像点链接操作符(.),不同的是,如果引用的对象或属性缺失(即 null 或 undefined),表达式短路并返回 undefined 值。简单地说,如果丢失了任何链接对象,它就不会继续进行链接操作(短路)。

例如,user?.names?.firstname 不会抛出任何错误或中断页面,因为一旦它检测到 user 或 names 对象丢失,它将立即终止操作。