郑州做网站hnqfu,赣州做网站找谁,温州做模具的网站,网易企业邮箱收费吗1、当调用 setState的时候#xff0c;发生了什么操作#xff1f; 当调用 setState时#xff0c; React做的第一件事是将传递给setState的对象合并到组件的当前状态#xff0c;这将启动一个称为和解#xff08; reconciliation#xff09;的过程。 和解的最终目标是#…1、当调用 setState的时候发生了什么操作 当调用 setState时 React做的第一件事是将传递给setState的对象合并到组件的当前状态这将启动一个称为和解 reconciliation的过程。 和解的最终目标是根据这个新的状态以最有效的方式更新DOM。 为此 React将构建一个新的 React虚拟DOM树可以将其视为页面DOM元素的对象表示方式。 一旦有了这个DOM树为了弄清DOM是如何响应新的状态而改变的 React会将这个新树与上一个虚拟DOM树比较。 这样做 React会知道发生的确切变化并且通过了解发生的变化后在绝对必要的情况下进行更新DOM即可将因操作DOM而占用的空间最小化。 2、在 React中元素 element和组件 component有什么区别 简单地说在 React中元素虛拟DOM描述了你在屏幕上看到的DOM元素。 换个说法就是在 React中元素是页面中DOM元素的对象表示方式。在 React中组件是一个函数或一个类它可以接受输入并返回一个元素。 注意工作中为了提高开发效率通常使用JSX语法表示 React元素虚拟DOM。在编译的时候把它转化成一个 React. createElement调用方法。 3、在构造函数调用 super 并将 props 作为参数传入的作用 在构造函数里调用super的目的是保证子类组件里有this 在ES6中super()函数就是父类的构造函数。所以在react里定义类组件时调用 super就是在调用React.Component的构造函数。 调用super函数时把props传入的目的是保证this有属性props即在子类组件里能够使用this.props 举例:
传递了props
class MyComponent extends React.Component {constructor(props) {super(props);console.log(this.props); // { name: sudheer,age: 30 }}
}没传递 props
class MyComponent extends React.Component {constructor(props) {super();console.log(this.props); // undefined// 但是 Props 参数仍然可用console.log(props); // Prints { name: sudheer,age: 30 }}render() {// 构造函数外部不受影响console.log(this.props); // { name: sudheer,age: 30 }}
}
4、什么是 React的refs为什么它们很重要
refs允许你直接访问DOM元素或组件实例。为了使用它们可以向组件添加个ref属性。
如果该属性的值是一个回调函数它将接受底层的DOM元素或组件的已挂载实例作为其第一个参数。可以在组件中存储它。
export class App extends Component {showResult ( ) {console. logthis. input. value}render ( ) {return (divinput typetext ref{input this .input input } / button onClick{this. showResult.bindthis}展示结果/ button/div);}
}
如果该属性值是一个字符串 React将会在组件实例化对象的refs属性中存储一个同名属性该属性是对这个DOM元素的引用。可以通过原生的 DOM API操作它。
export class App extends Component {showResult(){console .log ( this.refs.username.value)}render(){return (divinput typetext refusername/ button onClick{this. showResu1t.bind (this)}展示结果/ button/div);}
}
5、React 中的key是什么为什么它们很重要 key可以帮助 React跟踪循环创建列表中的虚拟DOM元素了解哪些元素已更改、添加或删除。 每个绑定key的虚拟DOM元素在兄弟元素之间都是独一无二的。在 React的和解过程中比较新的虛拟DOM树与上一个虛拟DOM树之间的差异并映射到页面中。key使 React处理列表中虛拟DOM时更加高效因为 React可以使用虛拟DOM上的key属性快速了解元素是新的、需要删除的还是修改过的。如果没有keyReact就不知道列表中虚拟DOM元素与页面中的哪个元素相对应。所以在创建列表的时候不要忽略key。 6、React 性能优化在哪个生命周期它优化的原理是什么
react的父级组件的render函数重新渲染会引起子组件的render方法的重新渲染。但是有的时候子组件的接受父组件的数据没有变动。子组件render的执行会影响性能这时就可以使用shouldComponentUpdate来解决这个问题。
使用方法如下
shouldComponentUpdate(nexrProps) {if (this.props.num nexrProps.num) {return false}return true;
}
shouldComponentUpdate提供了两个参数nextProps和nextState表示下一次props和一次state的值当函数返回false时候render()方法不执行组件也就不会渲染返回true时组件照常重渲染。此方法就是拿当前props中值和下一次props中的值进行对比数据相等时返回false反之返回true。
需要注意在进行新旧对比的时候是浅对比也就是说如果比较的数据时引用数据类型只要数据的引用的地址没变即使内容变了也会被判定为true。
面对这个问题可以使用如下方法进行解决 1使用setState改变数据之前先采用ES6中assgin进行拷贝但是assgin只深拷贝的数据的第一层所以说不是最完美的解决办法
const o2 Object.assign({},this.state.obj)o2.student.count 00000;this.setState({obj: o2,})
2使用JSON.parse(JSON.stringfy())进行深拷贝但是遇到数据为undefined和函数时就会错。
const o2 JSON.parse(JSON.stringify(this.state.obj))o2.student.count 00000;this.setState({obj: o2,})
react性能优化是在哪个生命周期函数中
在shouldComponentUpdate 这个方法中这个方法主要用来判断是否需要调用render方法重绘DOM 因为DOM的描绘非常消耗性能如果能够在shouldComponentUpdate方法中能写出更优化的 diff算法极大的提高性能
7、约束性组件 controlled component与非约束性组件 uncontrolled component有什么区别
在 React中组件负责控制和管理自己的状态。
如果将HTML中的表单元素 input、 select、 textarea等添加到组件中当用户与表单发生交互时就涉及表单数据存储问题。根据表单数据的存储位置将组件分成约東性组件和非约東性组件。
约束性组件 controlled component就是由 React控制的组件也就是说表单元素的数据存储在组件内部的状态中表单到底呈现什么由组件决定。
如下所示 username没有存储在DOM元素内而是存储在组件的状态中。每次要更新 username时就要调用 setState更新状态每次要获取 username的值就要获取组件状态值。
class App extends Component {//初始化状态constructor ( props ) {super ( props )this .state {username有课前端网}}//查看结果showResult ( ) {//获取数据就是获取状态值console. log ( this .state. username )}changeUsername (e) {//原生方法获取var value e .target .value//更新前可以进行脏值检测//更新状态this .setState ( {tusername:value} )}//渲染组件render( ) {//返回虚拟DOM return (divp{/*输入框绑定va1ue*/}input typetext onChange{ this.changeUsername .bind (this ) }value { this .state.username }//pp button onClick{this.showResult.bind (this)}查看结果/ button/p/div)}
}
非约束性组件 uncontrolled component就是指表单元素的数据交由元素自身存储并处理而不是通过 React组件。表单如何呈现由表单元素自身决定。
如下所示表单的值并没有存储在组件的状态中而是存储在表单元素中当要修改表单数据时直接输入表单即可。有时也可以获取元素再手动修改它的值。当要获取表单数据时要首先获取表单元素然后通过表单元素获取元素的值。
注意为了方便在组件中获取表单元素通常为元素设置ref属性在组件内部通过refs属性获取对应的DOM元素。
class App extends Component {//查看结果showResult ( ) {//获取值console. logthis. refs. username .value//修改值就是修改元素自身的值this.refs.username.value专业前端学习平台}//渲染组件render ( ) {//返回虚拟DOM return (divp{/*非约束性组件中表单元素通过 defaultvalue定义*/} input typetext ref username defaultvalue有课前端网//pp button onClick{this. showResult.bind ( this ) }查看结果/button/p/div)}
虽然非约東性组件通常更容易实现可以通过refs直接获取DOM元素并获取其值但是 React建议使用约束性组件。主要原因是约東性组件支持即时字段验证允许有条件地禁用/启用按钮强制输入格式等。
8、在哪个生命周期中你会发出Ajax请求为什么
Ajax请求应该写在组件创建期的第五个阶段即 componentDidMount生命周期方法中。原因如下。
在创建期的其他阶段组件尚未渲染完成。而在存在期的5个阶段又不能确保生命周期方法一定会执行如通过 shouldComponentUpdate方法优化更新等。在销毀期组件即将被销毁请求数据变得无意义。因此在这些阶段发岀Ajax请求显然不是最好的选择。
在组件尚未挂载之前Ajax请求将无法执行完毕如果此时发出请求将意味着在组件挂载之前更新状态如执行 setState这通常是不起作用的。
在 componentDidMount方法中执行Ajax即可保证组件已经挂载并且能够正常更新组件。
9、shouldComponentUpdate有什么用为什么它很重要 组件状态数据或者属性数据发生更新的时候组件会进入存在期视图会渲染更新。在生命周期方法 should ComponentUpdate中允许选择退出某些组件和它们的子组件的和解过程。 和解的最终目标是根据新的状态以最有效的方式更新用户界面。如果我们知道用户界面的某一部分不会改变那么没有理由让 React弄清楚它是否应该更新渲染。通过在 shouldComponentUpdate方法中返回 false, React将让当前组件及其所有子组件保持与当前组件状态相同。 10、如何用 React构建 build生产模式 通常使用 Webpack的 DefinePlugin方法将 NODE ENV设置为 production。这将剥离 propType验证和额外的警告。除此之外还可以减少代码因为 React使用 Uglify的dead-code来消除开发代码和注释这将大大减少包占用的空间。 可以通过配置package.json中的script中的mode为production
11、为什么要使用 React. Children. map props. children( ))而不是props. children. map ( ( ) )
因为不能保证 props. children将是一个数组。
以下面的代码为例。
Parenth1有课前端网/h1
/Parent
在父组件内部如果尝试使用 props.children. map映射子对象则会抛出错误因为props. children是一个对象而不是一个数组。
如果有多个子元素 React会使 props.children成为一个数组如下所示。
Parenth1有课前端网/h1h2前端技术学习平台/h2
/Parent
不建议使用如下方式在这个案例中会抛出错误。
class Parent extends Component {render ( ) {return (div { this .props.children.map (obj obj ) }/div) }
}
建议使用如下方式避免在上一个案例中抛出错误。
class Parent extends Component {render ( ) {return (div { React.Children.map ( this .props.children, obj obj) }/div)}
}
12、在使用 React Router时如何获取当前页面的路由或浏览器中地址栏中的地址 在当前组件的 props中包含 location属性对象包含当前页面路由地址信息在 match中存储当前路由的参数等数据信息。可以直接通过 this .props使用它们。 react18中可以使用useLocation获取地址相关信息 13、createElement和 cloneElement有什么区别 createElement是JSX被转载得到的在 React中用来创建 React元素即虚拟DOM的内容。cloneElement用于复制元素并传递新的 props。 14、React- Router有几种形式
有以下几种形式。 HashRouter通过散列实现路由要带#不够美观。BrowerRouter利用HTML5中 history API实现需要服务器端支持兼容性不是很好。 15、React的事件和普通的HTML事件有什么不同
区别
对于事件名称命名方式原生事件为全小写react 事件采用小驼峰对于事件函数处理语法原生事件为字符串react 事件为函数react 事件不能采用 return false 的方式来阻止浏览器的默认行为而必须要地明确地调用preventDefault()来阻止默认行为。
合成事件是 react 模拟原生 DOM 事件所有能力的一个事件对象其优点如下
兼容所有浏览器更好的跨平台将事件统一存放在一个数组避免频繁的新增与删除垃圾回收。方便 react 统一管理和事务机制。
事件的执行顺序为原生事件先执行合成事件后执行合成事件会冒泡绑定到 document 上所以尽量避免原生事件与合成事件混用如果原生事件阻止冒泡可能会导致合成事件不执行因为需要冒泡到document 上合成事件才会执行。
16、 17、React中D算法的原理是什么
原理如下。
1节点之间的比较。
节点包括两种类型一种是 React组件另一种是HTML的DOM。
如果节点类型不同按以下方式比较 如果 HTML DOM不同直接使用新的替换旧的。如果组件类型不同也直接使用新的替换旧的。 如果 HTML DOM类型相同按以下方式比较。 在 React里样式并不是一个纯粹的字符串而是一个对象这样在样式发生改变时只需要改变替换变化以后的样式。修改完当前节点之后递归处理该节点的子节点。 如果组件类型相同按以下方式比较 如果组件类型相同使用 React机制处理。一般使用新的 props替换旧的 props并在之后调用组件的 componentWillReceiveProps方法之前组件的 render方法会被调用。 节点的比较机制开始递归作用于它的子节点。 2两个列表之间的比较。 一个节点列表中的一个节点发生改变 React无法很妤地处理这个问题。循环新旧两个列表并找出不同这是 React唯一的处理方法。 但是有一个办法可以把这个算法的复杂度降低。那就是在生成一个节点列表时给每个节点上添加一个key。这个key只需要在这一个节点列表中唯一不需要全局唯一。 3取舍 需要注意的是上面的启发式算法基于两点假设。 类型相近的节点总是生成同样的树而类型不同的节点也总是生成不同的树 可以为多次 render都表现稳定的节点设置key。 上面的节点之间的比较算法基本上就是基于这两个假设而实现的。要提高 React应用的效率需要按照这两点假设来开发。
18、概述一下 React中的事件处理逻辑。 为了解决跨浏览器兼容性问题 React会将浏览器原生事件 Browser Native Event封装为合成事件 Synthetic Event并传入设置的事件处理程序中。 这里的合成事件提供了与原生事件相同的接口不过它们屏蔽了底层浏览器的细节差异保证了行为的一致性。另外 React并没有直接将事件附着到子元素上而是以单一事件监听器的方式将所有的事件发送到顶层进行处理基于事件委托原理。 这样 React在更新DOM时就不需要考虑如何处理附着在DOM上的事件监听器最终达到优化性能的目的。 19、传入 setstate函数的第二个参数的作用是什么
第二个参数是一个函数该函数会在 setState函数调用完成并且组件开始重渲染时调用可以用该函数来监听渲染是否完成。
this .setstate ({ username有课前端网
}, ( ) console.log ( re-rendered success. ) )
20、React和vue.js的相似性和差异性是什么
相似性如下 都是用于创建UI的 JavaScript库。都是快速和轻量级的代码库这里指 React核心库。都有基于组件的架构。都使用虚拟DOM。都可以放在单独的HTML文件中或者放在 Webpack设置的一个更复杂的模块中。都有独立但常用的路由器和状态管理库。 区别 react严格上只能算是MVC的view层,vue则是MVVM模式组件定义方式不同。React使用JSX语法而Vue可以使用模板或JSX。 虚拟DOM实现不同。React使用虚拟DOM进行DOM的渲染和更新而Vue也使用虚拟DOM但它更注重数据绑定和响应式系统。 数据绑定不同。Vue实现了数据的双向绑定而React则提倡单向数据流。社区和生态系统不同。React拥有更大的社区和更多的第三方库支持而Vue也在社区和生态系统方面有着显著的发展。性能不同。在某些情况下Vue可能提供更快的渲染速度因为其在虚拟DOM和编译器方面做了一些优化。 状态管理方式不同。Vue使用Vuex进行状态管理而React则使用Redux或Context。设计理念不同。React被设计为可以自底向上逐层应用而Vue则被设计为可以自顶向下逐层应用 21、生命周期调用方法的顺序是什么
React生命周期分为三大周期11个阶段生命周期方法调用顺序分别如下。
1在创建期的五大阶段调用方法的顺序如下。 getDetaultProps定义默认属性数据。 getInitialState初始化默认状态数据。 componentWillMount组件即将被构建。 render渲染组件。 componentDidMount组件构建完成 2在存在期的五大阶段调用方法的顺序如下。 componentWillReceiveProps组件即将接收新的属性数据。 shouldComponentUpdate判断组件是否应该更新。 componnentWillUpdate组件即将更新。 render渲染组件。 componentDidUpdate组件更新完成。 3在销毁期的一个阶段调用方法 componentWillUnmount表示组件即将被销毀。
22、使用状态要注意哪些事情
要注意以下几点。 不要直接更新状态 状态更新可能是异步的 状态更新要合并。 数据从上向下流动 23、说说 React组件开发中关于作用域的常见问题。
在 EMAScript5语法规范中关于作用域的常见问题如下。
1在map等方法的回调函数中要绑定作用域this通过bind方法。
2父组件传递给子组件方法的作用域是父组件实例化对象无法改变。
3组件事件回调函数方法的作用域是组件实例化对象绑定父组件提供的方法就是父组件实例化对象无法改变。
在 EMAScript6语法规范中关于作用域的常见问题如下。
1当使用箭头函数作为map等方法的回调函数时箭头函数的作用域是当前组件的实例化对象即箭头函数的作用域是定义时的作用域无须绑定作用域。
2事件回调函数要绑定组件作用域。
3父组件传递方法要绑定父组件作用域。
总之在 EMAScript6语法规范中组件方法的作用域是可以改变的。
24、在 Redux中使用 Action要注意哪些问题 在Redux中使用 Action的时候 Action文件里尽量保持 Action文件的纯净传入什么数据就返回什么数据最好把请求的数据和 Action方法分离开以保持 Action的纯净。 25、在 Reducer文件里对于返回的结果要注意哪些问题
在 Reducer文件里对于返回的结果必须要使用 Object.assign()来复制一份新的 state否则页面不会跟着数据刷新。
return Object. assign ( { } state, {type:action .type,shouldNotPaint : true
}) 26、React中的setState是同步执行还是异步执行如果是异步的怎么拿到执行后的state
setState是异步的。
如果要拿到修改后的状态需要使用回调函数的方式如下
//改变状态后想做一些事情
this.setState({属性名:属性值
}, () {//一般是用于在setState之后做一些操作//this.state 修改之后的state
})
为什么不能直接用以下办法更新state
this.state.msg “hello”;
因为这样不会引起组件的重新渲染所以数据修改后没法 呈现在页面上。
而调用setState()函数会引起组件的重新渲染这样更新的数据就会呈现在页面上
27、
28、Redux内部原理 内部怎么实现dispstch一个函数的 以redux-thunk中间件作为例子下面就是thunkMiddleware函数的代码 // 部分转为ES5代码运行middleware函数会返回一个新的函数如下
return ({ dispatch, getState }) {// next实际就是传入的dispatchreturn function (next) {return function (action) {// redux-thunk核心if (typeof action function) { return action(dispatch, getState, extraArgument);}return next(action);};};
}redux-thunk库内部源码非常的简单允许action是一个函数同时支持参数传递否则调用方法不变 redux创建Store通过combineReducers函数合并reducer函数返回一个新的函数combination这个函数负责循环遍历运行reducer函数返回全部state。将这个新函数作为参数传入createStore函数函数内部通过dispatch初始化运行传入的combinationstate生成返回store对象redux中间件applyMiddleware函数中间件的主要目的就是修改dispatch函数返回经过中间件处理的新的dispatch函数redux使用实际就是再次调用循环遍历调用reducer函数更新state
29、如果创建了类似于下面的 Icketang元素那么该如何实现 Icketang类 Icketang username雨夜清荷{user user Info user{user} /Loading /}
/Icketang
import React, { Component } fromr reactexport class Icketang extends Component {
//请实现你的代码
}
在上面的案例中一个组件接受一个函数作为它的子组件。Icketang组件的子组件是一个函数而不是一个常用的组件。这意味着在实现 Icketang组件时需要将props. children作为一个函数来处理。
具体实现如下。
import React, { Component } from react
class Icketang extends Component {constructor ( props ){super ( props ) this .state {user : props.user }}componentDidMount( ) {//模拟异步获取数据操作更新状态setTimeout ( ( ) this .setstate ({user有课前端网})2000}render ( ) {return this.props.children ( this .state.user )}
}
class Loading extends Component {render ( ) {return pLoading./p}
}
class Info extends Component { render ( ) {return hl { this .props.user }/h1}
}
调用 Icketang组件并传递给user属性数据把 props.children作为一个函数来处理。这种模式的好处是我们已经将父组件与子组件分离了父组件管理状态。父组件的使用者可以决定父组件以何种形式渲染子组件。
为了演示这一点在渲染 Icketang组件时分别传递和不传递user属性数据来观察渲染结果。
import {render} from react-dom;render (Icketang{ user user Info user {user} / Loading / }/Icketang , ickt
上述代码没有为 Icketang组件传递user属性数据因此将首先渲染 Loading组件当父组件的user状态数据发生改变时我们发现Info组件可以成功地渲染出来。
render Icketang user雨夜清荷
{ user user Info user {user} / Loading /}
/Icketang ickt)
上述代码为 Icketang组件传递了user属性数据因此将直接渲染Info组件当父组件的user状态数据发生改变时我们发现Info组件产生了更新在整个过程中 Loading组件都未渲染。
30、 这段代码有什么问题
class App extends Component {constructor ( props ) {super ( props )this .state {username有课前端网 msg }}render ( ) {return (div { this .state. msg }/div);}componentDidMount ( ) {this .setState ( ( oldState, props ) {return {msg:oldState .username - props.intro }} )}
render ( App intro 前端技术专业学习平台/Appickt )
在页面中正常输出“有课前端网-前端技术专业学习平台”。但是这种写法很少使用并不是常用的写法。React允许对 setState方法传递一个函数它接收到先前的状态和属性数据并返回一个需要修改的状态对象正如我们在上面所做的那样。它不但没有问题而且如果根据以前的状态 state以及属性来修改当前状态推荐使用这种写法。
31、请说岀 React从 EMAScript5编程规范到 EMAScript6编程规范过程中的几点改变。
主要改变如下。
1创建组件的方法不同。 EMAScript5版本中定义组件用 React.createClass。EMAScript6版本中定义组件要定义组件类并继承 Component类。 2定义默认属性的方法不同。 EMAScript5版本中用 getDefaultProps定义默认属性。EMAScript6版本中为组件定义 defaultProps静态属性来定义默认属性。 3定义初始化状态的方法不同。 EMAScript5版本中用 getInitialState定义初始化状态。EMAScript6版本中在构造函数中通过this. state定义初始化状态。 注意构造函数的第一个参数是属性数据一定要用 super继承。 4定义属性约束的方法不同。 EMAScript5版本中用 propTypes定义属性的约束。 EMAScript6版本中为组件定义 propsTypes静态属性来对属性进行约束。 5使用混合对象、混合类的方法不同。 EMAScript5版本中通过mixins继承混合对象的方法。 EMAScript6版本中定义混合类让混合类继承 Component类然后让组件类继承混合类实现对混合类方法的继承。 6绑定事件的方法不同。 EMAScript5版本中绑定的事件回调函数作用域是组件实例化对象。 EMAScript6版本中绑定的事件回调函数作用域是null。 7父组件传递方法的作用域不同。 EMAScript5版本中作用域是父组件。 EMAScript6版本中变成了null。 8组件方法作用域的修改方法不同。 EMAScript5版本中无法改变作用域。 EMAScript6版本中作用域是可以改变的。