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

佛山建站怎么做宜昌当阳网站开发

佛山建站怎么做,宜昌当阳网站开发,国家高新技术企业认定的要求,网站系统分析的步骤有哪些setState详解 实现原理 开发中我们并不能直接修改State来重新渲染界面: 因为修改State之后,希望React根据最新的State来重新渲染界面,但这种方式的修改React并不知道数据发生了变化; React并没有类似于Vue2中的Object.defineP…

setState详解

实现原理

开发中我们并不能直接修改State来重新渲染界面:

因为修改State之后,希望React根据最新的State来重新渲染界面,但这种方式的修改React并不知道数据发生了变化;

React并没有类似于Vue2中的Object.defineProperty或Vue3中的Proxy的方式来监听数据的变化;

我们必须通过setState来告知React数据已经发生了变化;

该方法的源码实现如下:

三种使用方式

import React, { Component } from 'react'export class App extends Component {constructor () {super () this.state={message:'hello',count:20}}changeText() {// 1.setState更多用法// 1.1基本使用// this.setState({//   message:'你好'// })/* 1.2setState可以传入一个回调函数好处一:可在回调函数中编写新的state处理逻辑好处二:当前回调函数会将之前的state和props传递进来*/// this.setState((state,props) => {//   console.log(state,props);//   return {//     message:'你好'//   }// })/* 1.3setState在React的事件处理中是一个异步调用如果希望在数据更新之后(数据合并),获取到对应的结果执行一些逻辑代码那么可以在setState中传入第二个参数:callback*/this.setState({message:"你好呀,小橙子"},() => {console.log(this.state.message);//你好呀,小橙子})// 会先执行这行代码console.log("-----------",this.state.message);// hello}addCount () {}render() {const { message,count } = this.statereturn (<div><h2>{message}</h2><button onClick={() => this.changeText()}>修改文本</button><h2>当前计数:{count}</h2><button onClick={() => this.addCount()}>count+1</button></div>)}
}export default App

setState异步更新

为什么setState设计为异步呢?

React核心成员(Redux的作者)Dan Abramov也有对应的回复:RFClarification: why is `setState` asynchronous? · Issue #11527 · facebook/react · GitHub

  1. setState设计为异步,可以显著的提升性能;
  • 如果每次调用 setState都进行一次更新,那么意味着render函数会被频繁调用,界面重新渲染,这样效率是很低的;
  • 最好的办法应该是获取到多个更新,之后进行批量更新;
  1. 如果同步更新了state,但是还没有执行render函数,那么state和props不能保持同步;
  • state和props不能保持一致性,会在开发中产生很多的问题;
import React, { Component } from 'react'
function Hello (props) {return <h2>{props.message}</h2>
}export class App extends Component {constructor () {super () this.state={message:'hello',count:20}}changeText() {}addCount () {// 一直是20+1——也说明setState是异步的/* this.setState({count:this.state.count + 1})this.setState({count:this.state.count + 1})this.setState({count:this.state.count + 1}) */this.setState((state) => {console.log(this.state.count);//20return {count:state.count + 1}})this.setState((state) => {console.log(this.state.count);//20return {count:state.count + 1}})this.setState((state) => {console.log(this.state.count);//20return {count:state.count + 1}})}/* 假设setState是同步的,那么点击按钮后,this.state.message已经改变——但是还未执行render函数——那么页面上的数据就还是之前的-即state和props不能保持同步*/render() {// 调用addCount函数,里面有三个setState,但render只会重新渲染一次——批量更新console.log("render函数被执行了几次");const { message,count } = this.statereturn (<div><h2>{message}</h2><button onClick={() => this.changeText()}>修改文本</button><h2>当前计数:{count}</h2><button onClick={() => this.addCount()}>count+1</button><Hello message={message} /></div>)}
}export default App

如何获取异步修改完的结果?

方式一:setState的回调

setState接受两个参数:第二个参数是一个回调函数,这个回调函数会在更新后会执行;

方式二:生命周期函数

注意:在React18之前,如果在setState外边包个setTimeout这种宏任务,它不由React回调,而是浏览器。故setState就变成了同步操作

React18之前:setTimeout中setState操作,是同步操作
React18之后:setTimeout中setState操作,是异步操作
setTimeout ( () => {this.setState({message:'你好'})console.log(this.state.message);//React18之前:你好;React18之后:hello
},0) 

性能优化SCU

当我们修改根组件中的数据,所有组件都需要重新render,进行diff算法,性能极低!——只更新数据改变的即可——通过shouldComponentUpdate方法

//nextProps:修改之后最新的props; nextState:修改之后最新的state
shouldComponentUpdate(nextProps, nextState) {// 性能优化:自己对前后state进行对比,如果前后state没有变化,就不更新组件if(this.state.message !== nextState.message  || this.state.count !== nextState.count){return true}//根据返回值觉得是否调用render方法return false
}

但如果所有的类都需要手动设置,那工作量也太大了!

React内部已帮我们实现PureComponent

底层原理实现:

注意:PureComponent只能检测第一层数据的变化,也就是复杂数据类型若地址未发生变化,是检测不到的

import React, { PureComponent } from 'react'export default class App extends PureComponent {constructor () {super()this.state = {books:[{name:"你不知道的JS",price:99,count:2},{name:"JS高级程序设计",price:78,count:2},{name:"React高级设计",price:94,count:2},{name:"LeetCode",price:88,count:2},]}}/* PureComponent底层实现原理:shouldComponentUpdate(nextProps,nextState) {浅层比较return (!shallowEqual(nextProps,this.props) || shallowEqual(nextState,this.state))}*/addBook() {const newBook = {name:"算法",price:99,count:8}/* React 依赖于状态的不可变性来确定何时需要更新 UI直接修改状态对象的属性不会让 React 知道状态已经发生了变化,因此不会重新渲染组件该做法在PureComponent中是不能引起重新渲染的this.state.books.push(newBook)  */this.setState({books:[...this.state.books,newBook]})}addCount (index) {// this.state.books[index]++   //引用对象并未发生改变const newBooks = [...this.state.books]//引用发生改变newBooks[index].count++this.setState({books:newBooks})}render() {const {books} = this.statereturn (<div><h2>书籍列表</h2><ul>{books.map((item,index) => {return (<li key={item.name}><span>{item.name}-{item.price}-{item.count}</span><button onClick={() => this.addCount(index)}>+1</button></li>)})}</ul><button onClick={() => this.addBook()}>添加新书籍</button></div>)}
}

针对类组件可使用 PureComponent。那函数组件那???

我们可使用高阶函数memo将组件都包裹一层

import { memo } from "react";
const Profile = memo(function(props) {console.log("Profile render函数");return (<div><h2>Profile-{props.message}</h2></div>)
})export default Profile

ref获取元素或组件实例

传入一个对象

1.类组件:通过 React.createRef() 创建 ref 对象,并绑定到 JSX 元素的 ref 属性

class ClassComponent extends React.Component {constructor(props) {super(props);this.myRef = React.createRef(); // 创建 ref 对象}componentDidMount() {console.log(this.myRef.current); // 获取 DOM 元素}render() {return <div ref={this.myRef}>类组件中使用 ref 对象</div>;}
}

2.函数组件:通过 React.useRef() Hook 创建 ref 对象,并绑定到 JSX 元素

function FunctionComponent() {const myRef = React.useRef(null); // 创建 ref 对象React.useEffect(() => {console.log(myRef.current); // 获取 DOM 元素}, []);return <div ref={myRef}>函数组件中使用 useRef</div>;
}

使用回调 ref

原理:将回调函数传递给元素的 ref 属性,React 在挂载/卸载时调用该回调,参数为 DOM 元素

1.类组件

class ClassComponent extends React.Component {constructor(props) {super(props);this.myRef = null; // 直接保存 DOM 引用}componentDidMount() {console.log(this.myRef); // 直接访问 DOM 元素}render() {return (<div ref={(el) => { this.myRef = el; }}> {/* 回调 ref */}类组件中使用回调 ref</div>);}
}

2.函数组件:

function FunctionComponent() {const myRef = React.useRef(null); // 持久化保存 DOM 引用const setRef = (el) => {myRef.current = el; // 通过回调更新 ref};React.useEffect(() => {console.log(myRef.current); // 获取 DOM 元素}, []);return <div ref={setRef}>函数组件中使用回调 ref</div>;
}

获取函数子组件的DOM

import React, { PureComponent, createRef,forwardRef } from 'react'const HelloWorld = forwardRef(function(props,ref) {return(<h1 ref={ref}>Hello World</h1>)
})export class App extends PureComponent {constructor(props) {super(props);this.whyRef = createRef();}getNativeDOM(){console.log(this.whyRef.current);}render() {return (<div>{/* 不能在函数组件上直接使用 ref属性,因为他们没有实例——通过forwardRef做一个转发*/}<HelloWorld ref={this.whyRef}/><button onClick={() => this.getNativeDOM()}>获取组件实例</button></div>)}
}export default App
http://www.dtcms.com/wzjs/584305.html

相关文章:

  • iapp网站做软件郑州网站建设知名公司排名
  • 传统文化网站建设方案哈尔滨关键词优化推广
  • 中企动力 网站模板购物网站功能模块说明
  • 做设计一般在那个网站找图网站建设推广的10种方法
  • 建设公司网站需要什么技术天翼云主机怎么建设网站
  • 企业宣传网站案例太原富库网站建设
  • 分析海尔网站的建设特点和优势济宁网站建设 果壳科技
  • 四川建设厅网站打不开做美容行业的网站哪个好
  • 睢宁建设局网站网站添加链接
  • 网站怎么做最省钱网站后台首页
  • 黄岐建网站做网站的维护成本
  • 在网络上做兼职的网站wordpress播放优酷视频
  • 福州企业网站建设专业服务网页页面设计模板
  • saas建站平台介绍帝国cms如何做网站
  • 服装公司网站多少钱建设银行网上银行
  • 建站总结报告磁力吧
  • 画出网站和目录结构图admin登录网站
  • php网站开发主要内容南平公司做网站
  • 丹阳市建设局网站电子商务网站设计与开发
  • 网站建设推广 seo网络推广优化方案
  • html制作电影网站网站代下单怎么做
  • 玄武模板网站制作品牌东莞专业网站推广公司
  • 南京网站设计 联络南京乐识建立网站就是制作网页
  • 怎么制作网站地图长春网站建设大概需要多少钱
  • 新乡哪个公司做网站好网站开发的数据库设计实体是什么
  • 网站设计建设合同小说网页网站建设
  • 网站做app安全吗商城网站建站程序
  • 中国建设银行网站结构网站界面设计说明
  • 邢台无忧网站建设公司python学习网站
  • 北京行业网站建设自己做网站出口