都匀网站建设公司成都商城网站开发设计

news/2025/9/23 16:17:20/文章来源:
都匀网站建设公司,成都商城网站开发设计,网络规划设计师 视频 网盘,云酒店网站建设目录 一、React 组件中怎么做事件代理#xff1f;它的原理是什么#xff1f; 二、React.Component 和 React.PureComponent 的区别 三、Component, Element, Instance 之间有什么区别和联系#xff1f; 四、React声明组件有哪几种方法#xff0c;有什么不同#xff1f…目录 一、React 组件中怎么做事件代理它的原理是什么 二、React.Component 和 React.PureComponent 的区别 三、Component, Element, Instance 之间有什么区别和联系 四、React声明组件有哪几种方法有什么不同 React 声明组件的三种方式 React.createClass与React.Component区别 五、React中可以在render访问refs吗为什么 六、React组件的构造函数有什么作用它是必须的吗 七、React中setState的第二个参数作用是什么 八、state 是怎么注入到组件的从 reducer 到组件经历了什么样的过程 九、React中怎么检验props验证props的目的是什么 十、React 废弃了哪些生命周期为什么 十一、React 16.X 中 props 改变后在哪个生命周期中处理 十二、React组件命名推荐的方式是哪个 十三、react 实现一个全局的 dialog 十四、在React中页面重新加载时怎样保留数据 十五、React必须使用JSX吗 十六、在React中怎么使用async/await 十七、如何配置 React-Router 实现路由切换 十八、react-router 里的 Link 标签和 a 标签的区别 十九、React-Router如何获取URL的参数和历史对象 1获取URL的参数 2获取历史对象 二十、Redux 中间件是什么接受几个参数柯里化函数两端的参数具体是什么 二十一、Redux 状态管理器和变量挂载到 window 中有什么区别 二十二、mobox 和 redux 有什么区别 1共同点 2区别 对比总结 二十三、React Hook 的使用限制有哪些 二十四、React Hooks在平时开发中需要注意的问题和原因 1不要在循环条件或嵌套函数中调用Hook必须始终在 React函数的顶层使用Hook 2使用useState时候使用pushpopsplice等直接更改数组对象的坑 3useState设置状态的时候只有第一次生效后期需要更新状态必须通过useEffect 4善用useCallback 5不要滥用useContext 二十五、React Hooks 和生命周期的关系 二十六、为什么React并不推荐优先考虑使用Context 二十七、React中refs的作用是什么有哪些应用场景 二十八、Redux中的connect有什么作用 connect负责连接React和Redux 1获取state 2包装原组件 3监听store tree变化 一、React 组件中怎么做事件代理它的原理是什么 React基于Virtual DOM实现了一个SyntheticEvent层合成事件层定义的事件处理器会接收到一个合成事件对象的实例它符合W3C标准且与原生的浏览器事件拥有同样的接口支持冒泡机制所有的事件都自动绑定在最外层上。 在React底层主要对合成事件做了两件事 事件委派React会把所有的事件绑定到结构的最外层使用统一的事件监听器这个事件监听器上维持了一个映射来保存所有组件内部事件监听和处理函数。自动绑定React组件中每个方法的上下文都会指向该组件的实例即自动绑定this为当前组件。 二、React.Component 和 React.PureComponent 的区别 PureComponent表示一个纯组件可以用来优化React程序减少render函数执行的次数从而提高组件的性能。 在React中当prop或者state发生变化时可以通过在shouldComponentUpdate生命周期函数中执行return false来阻止页面的更新从而减少不必要的render执行。React.PureComponent会自动执行 shouldComponentUpdate。 不过pureComponent中的 shouldComponentUpdate() 进行的是浅比较也就是说如果是引用数据类型的数据只会比较不是同一个地址而不会比较这个地址里面的数据是否一致。浅比较会忽略属性和或状态突变情况其实也就是数据引用指针没有变化而数据发生改变的时候render是不会执行的。如果需要重新渲染那么就需要重新开辟空间引用数据。PureComponent一般会用在一些纯展示组件上。 使用pureComponent的好处当组件更新时如果组件的props或者state都没有改变render函数就不会触发。省去虚拟DOM的生成和对比过程达到提升性能的目的。这是因为react自动做了一层浅比较。 三、Component, Element, Instance 之间有什么区别和联系 元素一个元素element是一个普通对象(plain object)描述了对于一个DOM节点或者其他组件component你想让它在屏幕上呈现成什么样子。元素element可以在它的属性props中包含其他元素(译注:用于形成元素树)。创建一个React元素element成本很低。元素element创建之后是不可变的。组件一个组件component可以通过多种方式声明。可以是带有一个render()方法的类简单点也可以定义为一个函数。这两种情况下它都把属性props作为输入把返回的一棵元素树作为输出。实例一个实例instance是你在所写的组件类component class中使用关键字this所指向的东西(译注:组件实例)。它用来存储本地状态和响应生命周期事件很有用。 函数式组件(Functional component)根本没有实例instance。类组件(Class component)有实例instance但是永远也不需要直接创建一个组件的实例因为React帮我们做了这些。 四、React声明组件有哪几种方法有什么不同 React 声明组件的三种方式 函数式定义的无状态组件ES5原生方式React.createClass定义的组件ES6形式的extends React.Component定义的组件 1无状态函数式组件 它是为了创建纯展示组件这种组件只负责根据传入的props来展示不涉及到state状态的操作 组件不会被实例化整体渲染性能得到提升不能访问this对象不能访问生命周期的方法 2ES5 原生方式 React.createClass // RFC React.createClass会自绑定函数方法导致不必要的性能开销增加代码过时的可能性。 3E6继承形式 React.Component // RCC 目前极为推荐的创建有状态组件的方式最终会取代React.createClass形式相对于 React.createClass可以更好实现代码复用。 无状态组件相对于于后者的区别 与无状态组件相比React.createClass和React.Component都是创建有状态的组件这些组件是要被实例化的并且可以访问组件的生命周期方法。 React.createClass与React.Component区别 ① 函数this自绑定 React.createClass创建的组件其每一个成员函数的this都有React自动绑定函数中的this会被正确设置。React.Component创建的组件其成员函数不会自动绑定this需要开发者手动绑定否则this不能获取当前组件实例对象。 ② 组件属性类型propTypes及其默认props属性defaultProps配置不同 React.createClass在创建组件时有关组件props的属性类型及组件默认的属性会作为组件实例的属性来配置其中defaultProps是使用getDefaultProps的方法来获取默认组件属性的。React.Component在创建组件时配置这两个对应信息时他们是作为组件类的属性不是组件实例的属性也就是所谓的类的静态属性来配置的。 ③ 组件初始状态state的配置不同 React.createClass创建的组件其状态state是通过getInitialState方法来配置组件相关的状态。React.Component创建的组件其状态state是在constructor中像初始化组件属性一样声明的。 五、React中可以在render访问refs吗为什么 span idname ref{this.spanRef}{this.state.title}/spanspan{ this.spanRef.current ? 有值 : 无值 }/span / 不可以render 阶段 DOM 还没有生成无法获取 DOM。DOM 的获取需要在 pre-commit 阶段和 commit 阶段 六、React组件的构造函数有什么作用它是必须的吗 构造函数主要用于两个目的 通过将对象分配给this.state来初始化本地状态将事件处理程序方法绑定到实例上 所以当在React class中需要设置state的初始值或者绑定事件时需要加上构造函数官方Demo class LikeButton extends React.Component {constructor() {super();this.state {liked: false};this.handleClick this.handleClick.bind(this);}handleClick() {this.setState({liked: !this.state.liked});}render() {const text this.state.liked ? liked : haven\t liked;return (div onClick{this.handleClick}You {text} this. Click to toggle./div);} } ReactDOM.render(LikeButton /,document.getElementById(example) ); 构造函数用来新建父类的this对象子类必须在constructor方法中调用super方法否则新建实例时会报错因为子类没有自己的this对象而是继承父类的this对象然后对其进行加工。如果不调用super方法子类就得不到this对象。 注意 constructor () 必须配上 super(), 如果要在constructor 内部使用 this.props 就要 传入props , 否则不用JavaScript中的 bind 每次都会返回一个新的函数, 为了性能等考虑, 尽量在constructor中绑定事件 七、React中setState的第二个参数作用是什么 setState 的第二个参数是一个可选的回调函数。这个回调函数将在组件重新渲染后执行。等价于在 componentDidUpdate 生命周期内执行。通常建议使用 componentDidUpdate 来代替此方式。在这个回调函数中你可以拿到更新后 state 的值 this.setState({key1: newState1,key2: newState2,... }, callback) // 第二个参数是 state 更新完成后的回调函数 八、state 是怎么注入到组件的从 reducer 到组件经历了什么样的过程 通过connect和mapStateToProps将state注入到组件中 import { connect } from react-redux import { setVisibilityFilter } from /reducers/Todo/actions import Link from /containers/Todo/components/Linkconst mapStateToProps (state, ownProps) ({active: ownProps.filter state.visibilityFilter })const mapDispatchToProps (dispatch, ownProps) ({setFilter: () {dispatch(setVisibilityFilter(ownProps.filter))} })export default connect(mapStateToProps,mapDispatchToProps )(Link) 上面代码中active就是注入到Link组件中的状态。 mapStateToPropsstateownProps中带有两个参数含义是∶ state-store管理的全局状态对象所有都组件状态数据都存储在该对象中。ownProps 组件通过props传入的参数。 reducer 到组件经历的过程 reducer对action对象处理更新组件状态并将新的状态值返回store。通过connectmapStateToPropsmapDispatchToPropsComponent对组件 Component进行升级此时将状态值从store取出并作为props参数传递到组件。 高阶组件实现源码∶ import React from react import PropTypes from prop-types// 高阶组件 contect export const connect (mapStateToProps, mapDispatchToProps) (WrappedComponent) {class Connect extends React.Component {// 通过对context调用获取storestatic contextTypes {store: PropTypes.object}constructor() {super()this.state {allProps: {}}}// 第一遍需初始化所有组件初始状态componentWillMount() {const store this.context.storethis._updateProps()store.subscribe(() this._updateProps()); // 加入_updateProps()至store里的监听事件列表}// 执行action后更新props使组件可以更新至最新状态类似于setState_updateProps() {const store this.context.store;let stateProps mapStateToProps ?mapStateToProps(store.getState(), this.props) : {} // 防止 mapStateToProps 没有传入let dispatchProps mapDispatchToProps ?mapDispatchToProps(store.dispatch, this.props) : {dispatch: store.dispatch} // 防止 mapDispatchToProps 没有传入this.setState({allProps: {...stateProps,...dispatchProps,...this.props}})}render() {return WrappedComponent {...this.state.allProps} /}}return Connect } 九、React中怎么检验props验证props的目的是什么 React为我们提供了PropTypes以供验证使用。当我们向Props传入的数据无效向Props传入的数据类型和验证的数据类型不符就会在控制台发出警告信息。它可以避免随着应用越来越复杂从而出现的问题。并且它还可以让程序变得更易读。 import PropTypes from prop-types;class Greeting extends React.Component {render() {return (h1Hello, {this.props.name}/h1);} }Greeting.propTypes {name: PropTypes.string }; 当然如果项目汇中使用了TypeScript那么就可以不用PropTypes来校验而使用TypeScript定义接口来校验props。 十、React 废弃了哪些生命周期为什么 被废弃的三个函数都是在render之前因为fber的出现很可能因为高优先级任务的出现而打断现有任务导致它们会被执行多次。另外的一个原因则是React想约束使用者好的框架能够让人不得已写出容易维护和扩展的代码这一点又是从何谈起可以从新增加以及即将废弃的生命周期分析入手 componentWillMount 首先这个函数的功能完全可以使用componentDidMount和 constructor来代替异步获取的数据的情况上面已经说明了而如果抛去异步获取数据其余的即是初始化而已这些功能都可以在constructor中执行除此之外如果在 willMount 中订阅事件但在服务端这并不会执行 willUnMount事件也就是说服务端会导致内存泄漏所以componentWilIMount完全可以不使用但使用者有时候难免因为各 种各样的情况在 componentWilMount中做一些操作那么React为了约束开发者干脆就抛掉了这个API componentWillReceiveProps 在老版本的 React 中如果组件自身的某个 state 跟其 props 密切相关的话一直都没有一种很优雅的处理方式去更新 state而是需要在 componentWilReceiveProps 中判断前后两个 props 是否相同如果不同再将新的 props更新到相应的 state 上去。这样做一来会破坏 state 数据的单一数据源导致组件状态变得不可预测另一方面也会增加组件的重绘次数。类似的业务需求也有很多如一个可以横向滑动的列表当前高亮的 Tab 显然隶属于列表自身的时根据传入的某个值直接定位到某个 Tab。为了解决这些问题React引入了第一个新的生命周期getDerivedStateFromProps。它有以下的优点∶ getDSFP是静态方法在这里不能使用this也就是一个纯函数开发者不能写出副作用的代码开发者只能通过prevState而不是prevProps来做对比保证了state和props之间的简单关系以及不需要处理第一次渲染时prevProps为空的情况基于第一点将状态变化setState和昂贵操作tabChange区分开更加便于 render 和 commit 阶段操作或者说优化 componentWillUpdate 与 componentWillReceiveProps 类似许多开发者也会在 componentWillUpdate 中根据 props 的变化去触发一些回调 。 但不论是 componentWilReceiveProps 还 是 componentWilUpdate都有可能在一次更新中被调用多次也就是说写在这里的回调函数也有可能会被调用多次这显然是不可取的。与 componentDidMount 类 似 componentDidUpdate 也不存在这样的问题一次更新中 componentDidUpdate 只会被调用一次所以将原先写在 componentWillUpdate 中 的 回 调 迁 移 至 componentDidUpdate 就可以解决这个问题。 另外一种情况则是需要获取DOM元素状态但是由于在fber中render可打断可能在wilMount中获取到的元素状态很可能与实际需要的不同这个通常可以使用第二个新增的生命函数的解决 getSnapshotBeforeUpdate(prevProps, prevState) getSnapshotBeforeUpdate(prevProps, prevState) 返回的值作为componentDidUpdate的第三个参数。与willMount不同的是getSnapshotBeforeUpdate会在最终确定的render执行之前执行也就是能保证其获取到的元素状态与didUpdate中获取到的元素状态相同。官方参考代码 class ScrollingList extends React.Component {constructor(props) {super(props);this.listRef React.createRef();}getSnapshotBeforeUpdate(prevProps, prevState) {// 我们是否在 list 中添加新的 items // 捕获滚动位置以便我们稍后调整滚动位置。if (prevProps.list.length this.props.list.length) {const list this.listRef.current;return list.scrollHeight - list.scrollTop;}return null;}componentDidUpdate(prevProps, prevState, snapshot) {// 如果我们 snapshot 有值说明我们刚刚添加了新的 items// 调整滚动位置使得这些新 items 不会将旧的 items 推出视图。//这里的 snapshot 是 getSnapshotBeforeUpdate 的返回值if (snapshot ! null) {const list this.listRef.current;list.scrollTop list.scrollHeight - snapshot;}}render() {return (div ref{this.listRef}{/* ...contents... */}/div);} } 十一、React 16.X 中 props 改变后在哪个生命周期中处理 在getDerivedStateFromProps中进行处理。 这个生命周期函数是为了替代componentWillReceiveProps存在的所以在需要使用componentWillReceiveProps 时就可以考虑使用 getDerivedStateFromProps 来进行替代。 两者的参数是不相同的而 getDerivedStateFromProps 是一个静态函数也就是这个函数不能通过this访问到class的属性也并不推荐直接访问属性。而是应该通过参数提供的nextProps以及prevState来进行判断根据新传入的props来映射到state。 需要注意的是如果props传入的内容不需要影响到你的state那么就需要返回一个null这个返回值是必须的所以尽量将其写到函数的末尾 static getDerivedStateFromProps(nextProps, prevState) {const {type} nextProps;// 当传入的type发生变化的时候更新stateif (type ! prevState.type) {return {type,};}// 否则对于state不进行任何操作return null; } 十二、React组件命名推荐的方式是哪个 通过引用而不是使用来命名组件displayName。 使用displayName命名组件 export default React.createClass({displayName: TodoApp,// ... }) React推荐的方法 export default class TodoApp extends React.Component {// ... } 十三、react 实现一个全局的 dialog import React, { Component } from react; import { is, fromJS } from immutable; import ReactDOM from react-dom; import ReactCSSTransitionGroup from react-addons-css-transition-group; import ./dialog.css;let defaultState {alertStatus:false,alertTip:提示,closeDialog:function(){},childs: }class Dialog extends Component{state {...defaultState};// css动画组件设置为目标组件FirstChild props {const childrenArray React.Children.toArray(props.children);return childrenArray[0] || null;}//打开弹窗open (options){options options || {};options.alertStatus true;var props options.props || {};var childs this.renderChildren(props,options.childrens) || ;console.log(childs);this.setState({...defaultState,...options,childs})}//关闭弹窗close(){this.state.closeDialog();this.setState({...defaultState})}renderChildren(props,childrens) {//遍历所有子组件var childs [];childrens childrens || [];var ps {...props,  //给子组件绑定props_close:this.close  //给子组件也绑定一个关闭弹窗的事件   };childrens.forEach((currentItem,index) {childs.push(React.createElement(currentItem,{...ps,key:index}));})return childs;}shouldComponentUpdate(nextProps, nextState){return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))}render(){return (ReactCSSTransitionGroupcomponent{this.FirstChild}transitionNamehidetransitionEnterTimeout{300}transitionLeaveTimeout{300}div classNamedialog-con style{this.state.alertStatus? {display:block}:{display:none}}{this.state.childs}/div/ReactCSSTransitionGroup);} } let div document.createElement(div); let props { }; document.body.appendChild(div); let Box ReactD 子类 //子类jsx import React, { Component } from react; class Child extends Component {constructor(props){super(props);this.state {date: new Date()};}showValue(){this.props.showValue this.props.showValue()}render() {return (div classNameChilddiv classNamecontentChildbutton onClick{this.showValue}调用父的方法/button/div/div);} } export default Child; css .dialog-con{position: fixed;top: 0;left: 0;width: 100%;height: 100%;background: rgba(0, 0, 0, 0.3); } 十四、在React中页面重新加载时怎样保留数据 这个问题就设计到了数据持久化主要的实现方式有以下几种 Redux将页面的数据存储在redux中在重新加载页面时获取Redux中的数据data.js使用webpack构建的项目可以建一个文件data.js将数据保存data.js中跳转页面后获取sessionStorge在进入选择地址页面之前componentWillUnMount的时候将数据存储到sessionStorage中每次进入页面判断sessionStorage中有没有存储的那个值有则读取渲染数据没有则说明数据是初始化的状态。返回或进入除了选择地址以外的页面清掉存储的sessionStorage保证下次进入是初始化的数据history APIHistory API 的 pushState 函数可以给历史记录关联一个任意的可序列化 state所以可以在路由 push 的时候将当前页面的一些信息存到 state 中下次返回到这个页面的时候就能从 state 里面取出离开前的数据重新渲染。react-router 直接可以支持。这个方法适合一些需要临时存储的场景。 十五、React必须使用JSX吗 React 并不强制要求使用 JSX。当不想在构建环境中配置有关 JSX 编译时不在 React 中使用 JSX 会更加方便。 每个 JSX 元素只是调用 React.createElement(component, props, ...children) 的语法糖。因此使用 JSX 可以完成的任何事情都可以通过纯 JavaScript 完成。 例如用 JSX 编写的代码 class Hello extends React.Component {render() {return divHello {this.props.toWhat}/div;} }ReactDOM.render(Hello toWhatWorld /,document.getElementById(root) ); 可以编写为不使用 JSX 的代码 class Hello extends React.Component {render() {return React.createElement(div, null, Hello ${this.props.toWhat});} }ReactDOM.render(React.createElement(Hello, {toWhat: World}, null),document.getElementById(root) ); 十六、在React中怎么使用async/await async/await是ES7标准中的新特性。如果是使用React官方的脚手架创建的项目就可以直接使用。如果是在自己搭建的webpack配置的项目中使用可能会遇到 regeneratorRuntime is not defined 的异常错误。那么我们就需要引入babel并在babel中配置使用async/await。可以利用babel的 transform-async-to-module-method 插件来转换其成为浏览器支持的语法虽然没有性能的提升但对于代码编写体验要更好。 十七、如何配置 React-Router 实现路由切换 1使用 Route 组件 路由匹配是通过比较 Route 的 path 属性和当前地址的 pathname 来实现的。当一个 Route 匹配成功时它将渲染其内容当它不匹配时就会渲染 null。没有路径的 Route 将始终被匹配。 // when location { pathname: /about } Route path/about component{About}/ // renders About/ Route path/contact component{Contact}/ // renders null Route component{Always}/ // renders Always/ 2结合使用 Switch 组件和 Route 组件 Switch 用于将 Route 分组。 SwitchRoute exact path/ component{Home} /Route path/about component{About} /Route path/contact component{Contact} / /Switch Switch 不是分组 Route 所必须的但他通常很有用。 一个 Switch 会遍历其所有的子 Route元素并仅渲染与当前地址匹配的第一个元素。 3使用 Link、 NavLink、Redirect 组件 Link 组件来在你的应用程序中创建链接。无论你在何处渲染一个 Link 都会在应用程序的 HTML 中渲染锚a。 NavLink 是一种特殊类型的 Link 当它的 to属性与当前地址匹配时可以将其定义为活跃的。 // location { pathname: /react } NavLink to/react activeClassNamehurrayReact /NavLink // a href/react classNamehurrayReact/a 当我们想强制导航时可以渲染一个Redirect当一个Redirect渲染时它将使用它的to属性进行定向。 十八、react-router 里的 Link 标签和 a 标签的区别 从最终渲染的 DOM 来看这两者都是链接都是标签区别是∶ Link是react-router 里实现路由跳转的链接一般配合Route 使用react-router接管了其默认的链接跳转行为区别于传统的页面跳转Link 的“跳转”行为只会触发相匹配的Route对应的页面内容更新而不会刷新整个页面。 Link做了3件事情: 有onclick那就执行onclickclick的时候阻止a标签默认事件根据跳转href(即是to)用history (web前端路由两种方式之一history hash)跳转此时只是链接变了并没有刷新页面而a标签就是普通的超链接了用于从当前页面跳转到href指向的另一 个页面(非锚点情况)。 a标签默认事件禁掉之后做了什么才实现了跳转? let domArr document.getElementsByTagName(a) [...domArr].forEach(item{item.addEventListener(click,function () {location.href this.href}) }) 十九、React-Router如何获取URL的参数和历史对象 1获取URL的参数 get传值 路由配置还是普通的配置如admin传参方式如admin?id1111。通过this.props.location.search获取url获取到一个字符串?id1111 可以用urlqsquerystring浏览器提供的api URLSearchParams对象或者自己封装的方法去解析出id的值。 动态路由传值 路由需要配置成动态路由如path/admin/:id传参方式如admin/111。通过this.props.match.params.id 取得url中的动态路由id部分的值除此之外还可以通过useParamsHooks来获取 通过query或state传值 传参方式如在Link组件的to属性中可以传递对象 {pathname:/admin,query:111,state:111};。通过this.props.location.state或this.props.location.query来获取即可传递的参数可以是对象、数组等但是存在缺点就是只要刷新页面参数就会丢失。 2获取历史对象 如果React 16.8 时可以使用 React Router中提供的Hooks import { useHistory } from react-router-dom; let history useHistory(); 使用this.props.history获取历史对象 let history this.props.history; 二十、Redux 中间件是什么接受几个参数柯里化函数两端的参数具体是什么 Redux 的中间件提供的是位于 action 被发起之后到达 reducer 之前的扩展点换而言之原本 view -→ action - reducer - store 的数据流加上中间件后变成了 view - action - middleware - reducer - store 在这一环节可以做一些副作用的操作如异步请求、打印日志等。 applyMiddleware源码 export default function applyMiddleware(...middlewares) {return createStore (...args) {// 利用传入的createStore和reducer和创建一个storeconst store createStore(...args)let dispatch () {throw new Error()}const middlewareAPI {getState: store.getState,dispatch: (...args) dispatch(...args)}// 让每个 middleware 带着 middlewareAPI 这个参数分别执行一遍const chain middlewares.map(middleware middleware(middlewareAPI))// 接着 compose 将 chain 中的所有匿名函数组装成一个新的函数即新的 dispatchdispatch compose(...chain)(store.dispatch)return {...store,dispatch}} } 从applyMiddleware中可以看出 redux中间件接受一个对象作为参数对象的参数上有两个字段 dispatch 和 getState分别代表着 Redux Store 上的两个同名函数。柯里化函数两端一个是 middewares一个是store.dispatch。 二十一、Redux 状态管理器和变量挂载到 window 中有什么区别 两者都是存储数据以供后期使用。但是Redux状态更改可回溯——Time travel数据多了的时候可以很清晰的知道改动在哪里发生完整的提供了一套状态管理模式。 随着 JavaScript 单页应用开发日趋复杂JavaScript 需要管理比任何时候都要多的 state 状态。 这些 state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据也包括 UI状态如激活的路由被选中的标签是否显示加载动效或者分页器等等。 管理不断变化的 state 非常困难。如果一个 model 的变化会引起另一个 model 变化那么当 view 变化时就可能引起对应 model 以及另一个model 的变化依次地可能会引起另一个 view 的变化。直至你搞不清楚到底发生了什么。state 在什么时候由于什么原因如何变化已然不受控制。 当系统变得错综复杂的时候想重现问题或者添加新功能就会变得举步维艰。 如果这还不够糟糕考虑一些来自前端开发领域的新需求如更新调优、服务端渲染、路由跳转前请求数据等等。前端开发者正在经受前所未有的复杂性难道就这么放弃了吗?当然不是。 这里的复杂性很大程度上来自于我们总是将两个难以理清的概念混淆在一起变化和异步。 可以称它们为曼妥思和可乐。如果把二者分开能做的很好但混到一起就变得一团糟。一些库如 React 视图在视图层禁止异步和直接操作 DOM来解决这个问题。美中不足的是React 依旧把处理 state 中数据的问题留给了你。Redux就是为了帮你解决这个问题。 二十二、mobox 和 redux 有什么区别 1共同点 为了解决状态管理混乱无法有效同步的问题统一维护管理应用状态;某一状态只有一个可信数据来源通常命名为store指状态容器;操作更新状态方式统一并且可控通常以action方式提供更新状态的途径;支持将store与React组件连接如react-reduxmobx- react; 2区别 Redux更多的是遵循Flux模式的一种实现是一个 JavaScript库它关注点主要是以下几方面 Action∶ 一个JavaScript对象描述动作相关信息主要包含type属性和payload属性∶ type∶ action 类型;payload∶ 负载数据; Reducer∶ 定义应用状态如何响应不同动作action如何更新状态;Store∶ 管理action和reducer及其关系的对象主要提供以下功能∶ 维护应用状态并支持访问状态(getState());支持监听action的分发更新状态(dispatch(action));支持订阅store的变更(subscribe(listener)); 异步流∶ 由于Redux所有对store状态的变更都应该通过action触发异步任务通常都是业务或获取数据任务也不例外而为了不将业务或数据相关的任务混入React组件中就需要使用其他框架配合管理异步任务流程如redux-thunkredux-saga等; Mobx是一个透明函数响应式编程的状态管理库它使得状态管理简单可伸缩 Action∶定义改变状态的动作函数包括如何变更状态;Store∶ 集中管理模块状态State和动作(action)Derivation衍生∶ 从应用状态中派生而出且没有任何其他影响的数据 对比总结 redux将数据保存在单一的store中mobx将数据保存在分散的多个store中redux使用plain object保存数据需要手动处理变化后的操作;mobx适用observable保存数据数据变化后自动处理响应的操作redux使用不可变状态这意味着状态是只读的不能直接去修改它而是应该返回一个新的状态同时使用纯函数;mobx中的状态是可变的可以直接对其进行修改mobx相对来说比较简单在其中有很多的抽象mobx更多的使用面向对象的编程思维;redux会比较复杂因为其中的函数式编程思想掌握起来不是那么容易同时需要借助一系列的中间件来处理异步和副作用mobx中有更多的抽象和封装调试会比较困难同时结果也难以预测;而redux提供能够进行时间回溯的开发工具同时其纯函数以及更少的抽象让调试变得更加的容易 二十三、React Hook 的使用限制有哪些 React Hooks 的限制主要有两条 不要在循环、条件或嵌套函数中调用 Hook。在 React 的函数组件中调用 Hook。 那为什么会有这样的限制呢Hooks 的设计初衷是为了改进 React 组件的开发模式。在旧有的开发模式下遇到了三个问题。 组件之间难以复用状态逻辑。过去常见的解决方案是高阶组件、render props 及状态管理框架。复杂的组件变得难以理解。生命周期函数与业务逻辑耦合太深导致关联部分难以拆分。人和机器都很容易混淆类。常见的有 this 的问题但在 React 团队中还有类难以优化的问题希望在编译优化层面做出一些改进。 这三个问题在一定程度上阻碍了 React 的后续发展所以为了解决这三个问题Hooks 基于函数组件 开始设计。然而第三个问题决定了 Hooks 只支持函数组件。 那为什么不要在循环、条件或嵌套函数中调用 Hook 呢因为 Hooks 的设计是基于数组实现。在调用时按顺序加入数组中如果使用循环、条件或嵌套函数很有可能导致数组取值错位执行错误的 Hook。当然实质上 React 的源码里不是数组是链表。 这些限制会在编码上造成一定程度的心智负担新手可能会写错为了避免这样的情况可以引入 ESLint 的 Hooks 检查插件进行预防。 二十四、React Hooks在平时开发中需要注意的问题和原因 1不要在循环条件或嵌套函数中调用Hook必须始终在 React函数的顶层使用Hook 这是因为React需要利用调用顺序来正确更新相应的状态以及调用相应的钩子函数。一旦在循环或条件分支语句中调用Hook就容易导致调用顺序的不一致性从而产生难以预料到的后果。 2使用useState时候使用pushpopsplice等直接更改数组对象的坑 使用push直接更改数组无法获取到新值应该采用析构方式但是在class里面不会有这个问题。代码示例 function Indicatorfilter() {let [num,setNums] useState([0,1,2,3])const test () {// 这里坑是直接采用push去更新num// setNums(num)是无法更新num的// 必须使用num [...num ,1]num.push(1)// num [...num ,1]setNums(num)} return (div classNamefilterdiv onClick{test}测试/divdiv{num.map((item,index) (div key{index}{item}/div))}/div/div) }class Indicatorfilter extends React.Componentany,any{constructor(props:any){super(props)this.state {nums:[1,2,3]}this.test this.test.bind(this)}test(){// class采用同样的方式是没有问题的this.state.nums.push(1)this.setState({nums: this.state.nums})}render(){let {nums} this.statereturn(divdiv onClick{this.test}测试/divdiv{nums.map((item:any,index:number) (div key{index}{item}/div))}/div/div)} } 3useState设置状态的时候只有第一次生效后期需要更新状态必须通过useEffect TableDeail是一个公共组件在调用它的父组件里面我们通过set改变columns的值以为传递给TableDeail 的 columns是最新的值所以tabColumn每次也是最新的值但是实际tabColumn是最开始的值不会随着columns的更新而更新 const TableDeail ({columns, }:TableData) {const [tabColumn, setTabColumn] useState(columns) }// 正确的做法是通过useEffect改变这个值 const TableDeail ({columns, }:TableData) {const [tabColumn, setTabColumn] useState(columns)useEffect(() {setTabColumn(columns)},[columns]) } 4善用useCallback 父组件传递给子组件事件句柄时如果我们没有任何参数变动可能会选用useMemo。但是每一次父组件渲染子组件即使没变化也会跟着渲染一次。 5不要滥用useContext 可以使用基于 useContext 封装的状态管理工具。 二十五、React Hooks 和生命周期的关系 函数组件的本质是函数没有 state 的概念的因此不存在生命周期一说仅仅是一个render 函数而已。但是引入 Hooks 之后就变得不同了它能让组件在不使用 class 的情况下拥有 state所以就有了生命周期的概念所谓的生命周期其实就是 useState、 useEffect() 和 useLayoutEffect() 。 即Hooks 组件使用了Hooks的函数组件有生命周期而函数组件未使用Hooks的函数组件是没有生命周期的。 下面是具体的 class 与 Hooks 的生命周期对应关系 constructor函数组件不需要构造函数可以通过调用 useState来初始化 state。如果计算的代价比较昂贵也可以传一个函数给 useState。 const [num, UpdateNum] useState(0) getDerivedStateFromProps一般情况下我们不需要使用它可以在渲染过程中更新 state以达到实现 getDerivedStateFromProps 的目的。 function ScrollView({row}) {let [isScrollingDown, setIsScrollingDown] useState(false);let [prevRow, setPrevRow] useState(null);if (row ! prevRow) {// Row 自上次渲染以来发生过改变。更新 isScrollingDown。setIsScrollingDown(prevRow ! null row prevRow);setPrevRow(row);}return Scrolling down: ${isScrollingDown}; } React 会立即退出第一次渲染并用更新后的 state 重新运行组件以避免耗费太多性能。 shouldComponentUpdate可以用 React.memo 包裹一个组件来对它的 props 进行浅比较 const Button React.memo((props) {// 具体的组件 }); 注意React.memo等效于PureComponent它只浅比较 props。这里也可以使用 useMemo 优化每一个节点。 render这是函数组件体本身。componentDidMount, componentDidUpdate useLayoutEffect 与它们两的调用阶段是一样的。但是我们推荐你一开始先用 useEffect只有当它出问题的时候再尝试使用 useLayoutEffect。useEffect 可以表达所有这些的组合。 // componentDidMount useEffect((){// 需要在 componentDidMount 执行的内容 }, []) useEffect(() {// 在 componentDidMount以及 count 更改时 componentDidUpdate 执行的内容document.title You clicked ${count} times;return () {// 需要在 count 更改时 componentDidUpdate先于 document.title ... 执行遵守先清理后更新// 以及 componentWillUnmount 执行的内容       } // 当函数中 Cleanup 函数会按照在代码中定义的顺序先后执行与函数本身的特性无关 }, [count]); // 仅在 count 更改时更新 请记得 React 会等待浏览器完成画面渲染之后才会延迟调用 因此会使得额外操作很方便 componentWillUnmount相当于 useEffect 里面返回的 cleanup 函数 // componentDidMount/componentWillUnmount useEffect((){// 需要在 componentDidMount 执行的内容return function cleanup() {// 需要在 componentWillUnmount 执行的内容     } }, []) componentDidCatch and getDerivedStateFromError目前还没有这些方法的 Hook 等价写法。 class 组件Hooks 组件constructoruseStategetDerivedStateFromPropsuseState 里面 update 函数shouldComponentUpdateuseMemorender函数本身 componentDidMountuseEffectcomponentDidUpdateuseEffectcomponentWillUnmountuseEffect 里面返回的函数componentDidCatch无getDerivedStateFromError无 二十六、为什么React并不推荐优先考虑使用Context Context目前还处于实验阶段可能会在后面的发行版本中有很大的变化事实上这种情况已经发生了所以为了避免给今后升级带来大的影响和麻烦不建议在app中使用context。尽管不建议在app中使用context但是独有组件而言由于影响范围小于app如果可以做到高内聚不破坏组件树之间的依赖关系可以考虑使用context对于组件之间的数据通信或者状态管理有效使用props或者state解决然后再考虑使用第三方的成熟库进行解决以上的方法都不是最佳的方案的时候在考虑context。context的更新需要通过setState()触发但是这并不是很可靠的Context支持跨组件的访问但是如果中间的子组件通过一些方法不影响更新比如 shouldComponentUpdate() 返回false 那么不能保证Context的更新一定可以使用Context的子组件因此Context的可靠性需要关注 二十七、React中refs的作用是什么有哪些应用场景 Refs 提供了一种方式用于访问在 render 方法中创建的 React 元素或 DOM 节点。Refs 应该谨慎使用如下场景使用 Refs 比较适合 处理焦点、文本选择或者媒体的控制触发必要的动画集成第三方 DOM 库 Refs 是使用 React.createRef() 方法创建的他通过 ref 属性附加到 React 元素上。要在整个组件中使用 Refs需要将 ref 在构造函数中分配给其实例属性 class MyComponent extends React.Component {constructor(props) {super(props)this.myRef React.createRef()}render() {return div ref{this.myRef} /} } 由于函数组件没有实例因此不能在函数组件上直接使用 ref function MyFunctionalComponent() {return input /; } class Parent extends React.Component {constructor(props) {super(props);this.textInput React.createRef();}render() {// 这将不会工作return (MyFunctionalComponent ref{this.textInput} /);} } 但可以通过闭合的帮助在函数组件内部进行使用 Refs function CustomTextInput(props) {// 这里必须声明 textInput这样 ref 回调才可以引用它let textInput null;function handleClick() {textInput.focus();}return (divinputtypetextref{(input) { textInput input; }} /inputtypebuttonvalueFocus the text inputonClick{handleClick}//div);  } 注意 不应该过度的使用 Refs。ref 的返回值取决于节点的类型。 当 ref 属性被用于一个普通的 HTML 元素时React.createRef() 将接收底层 DOM 元素作为他的 current 属性以创建 ref。当 ref 属性被用于一个自定义的类组件时ref 对象将接收该组件已挂载的实例作为他的 current。当在父组件中需要访问子组件中的 ref 时可使用传递 Refs 或回调 Refs。 二十八、Redux中的connect有什么作用 connect负责连接React和Redux 1获取state connect 通过 context获取 Provider 中的 store通过 store.getState() 获取整个store tree 上所有state 2包装原组件 将state和action通过props的方式传入到原组件内部 wrapWithConnect 返回—个 ReactComponent 对 象 ConnectConnect 重 新 render 外部传入的原组件 WrappedComponent 并把 connect 中传入的 mapStateToPropsmapDispatchToProps与组件上原有的 props合并后通过属性的方式传给WrappedComponent 3监听store tree变化 connect缓存了store tree中state的状态通过当前state状态 和变更前 state 状态进行比较从而确定是否调用 this.setState() 方法触发Connect及其子组件的重新渲染

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/913127.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何建CMS网站企业标识设计公司

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 常见的两种创建线程…

最好加盟网站建设大连建设学院网站

SeaTunnel 是使用的mvnw命令,可以先执行一下install-plugin.sh然后终止 理论上应该可以直接执行mvnw,他就会去安装下载maven,目录就是下面的目录 然后去服务器目录修改 setting.xml文件,设置镜像源即可 /root/.m2/wrapper/dists/apache-maven-3.8.4-bin/52ccbt68d252mdldqsfsn…

移动端性能监控探索:鸿蒙 NEXT 探针架构与技术实现

在鸿蒙 NEXT 的新时代,阿里云 ARMS RUM SDK 作为一款性能体验监控工具,可以作为辅助 APP 运维强有力的助手。作者:杨兰馨(楠瑆) 背景介绍 2024 年 10 月 22 日,华为在原生鸿蒙之夜正式发布 HarmonyOS NEXT(版本…

哲讯科技:以数智之力,铸就企业SAP ERP实施新典范

哲讯科技:以数智之力,铸就企业SAP ERP实施新典范在当今瞬息万变的商业环境中,企业数字化转型已不是选择题,而是生存题。SAP ERP作为全球领先的企业资源规划系统,以其高度的集成性、前瞻的管理思想和强大的功能,成…

Shell 脚本编程:函数 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

PR曲线绘制

PR曲线绘制 https://blog.csdn.net/xiang_gina/article/details/149962713作者:太一吾鱼水 宣言:在此记录自己学习过程中的心得体会,同时积累经验,不断提高自己! 声明:博客写的比较乱,主要是自己看的。…

5台电脑怎么同步文件最安全高效?别再只知道用局域网共享了!

还在为多台电脑文件同步烦恼,手动传输效率低?本文提供最佳解决方案,教你告别U盘。详解如何使用坚果云实现文件无感、实时同步,并借助其历史版本与云桥模式功能,安全且节省空间地管理多设备文件,是高效办公的必备…

建设信用网站的目的门户网站建设总结

windows下的TortoiseSVN是资源管理器的一个插件,以覆盖图标表示文件状态,几乎所以命令都有图形界面支持,比较好用,这里就不多说。主要说说linux下svn的使用,因为linux下大部分的操作都是通过命令行来进行,所…

wordpress付费插件网站网络优化工程师证

2008/02/28 17:32i当ListView绑定数据源后,这个效果让我无从下手, 这个问题一直困扰着我,后来我在CSDN上发贴求助,问题终于得以解决,这是一位大大给的回复: 以下各节提供了三种方法,用于创建各行的 Background 颜色具有交替效果的 ListView。该示例还论述用于在添加…

自己建网站做那个模块好建设网站的费用如何账务处理

🍁🍁🍁图像分割实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 unet医学细胞分割实战1 unet医学细胞分割实战2 unet医学细胞分割实战3 unet医学细胞分割实战4 unet…

专业开发网站多少钱做游戏类型的网站的好处

在我之前的文章 “Elasticsearch:使用 ELSER 进行语义搜索”,我们展示了如何使用 ELESR v1 来进行语义搜索。在使用 ELSER 之前,我们必须注意的是: 重要:虽然 ELSER V2 已正式发布,但 ELSER V1 仍处于 [预览…

什么是html5网站佛山新网站建设服务

【题目描述】 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 示例 1&am…

建站公司转型做什么业务wordpress吧

flashplayer的cpu渲染 bitmapData占用的内存分两块,一块是原始数据区,另一块是解压后的内存区10秒内如果没有使用这个bitmapdata,解压后的内存区会被释放,当10秒后重新使用,这个bitmapdata会再次解压,所以就…

有什么做礼品的卖家网站网站当地备案

概念:分包就是把一个完整的小程序项目,按照需求划分为不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。 分包的优点:可以优化小程序首次启动的下载时间,在多团队共同开发时可以更好的解耦…

汕头网站建设只需要800网上申请注册公司网址

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值&a…

呼伦贝尔网站建设厦门网站建设报价

动态内存管理 1. 为什么存在动态内存管理2. 动态内存函数的介绍2.1 malloc函数和free函数2.2 calloc函数2.3 realloc函数 3. 常见的动态内存错误3.1 对NULL指针的解引用操作3.2 对动态开辟空间的越界访问3.3 对非动态开辟内存使用free函数3.4 使用free释放动态开辟内存的一部分…

关于CompatibilityHID例程的使用

CompatibilityHID例程主要演示HID和串口之间的数据传输 1、首先注意工程要根据MCU不同型号进行相应的配置,具体可参考下链接: EVT-CH32x系列芯片EVT工程使用注意说明2、例程演示需要用到相应的工具,下载链接如下:H…

【CVCVCV】GAN代码解析

【CVCVCV】GAN代码解析Posted on 2025-09-23 16:06 SaTsuki26681534 阅读(0) 评论(0) 收藏 举报0 通过读GAN的代码了解一下常规深度学习模型的整体工程结构 1

实用指南:通过ssh远程linux 盒子

实用指南:通过ssh远程linux 盒子2025-09-23 16:07 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !impor…

海外推广是什么工作seo网站代码

main.m // 点语法-编译器特性,编译器遇到点语法会自动展开成相应的 //语法 //为了让其他语言的程序员能快速入手OC加入了点语法 //点语法的本质还是方法调用,不是访问成员变量 //(区别java,java的点语法是访问成员变量 //OC里面就…