Java面试题(四)
为什么选择使用框架而不是原生?
框架的好处:
1、组件化:其中React 的组件化最为彻底, 甚至可以到函数级别的原子组件,
高度的组件化可以是我们的工程易于维护、易于组合拓展。
2、天然分层:JQuery 时代的代码大部分情况下是面条代码,耦合严重,现代框架不管是MVC、MVP还是MVVM 模式都能帮助我们进行分层,代码解耦更易于读写。
3、生态:现在主流前端框架都自带生态,不管是数据流管理架构还是UI库都有成熟的解决方案。
4、开发效率:现代前端框架都默认自动更新DOM,而非我们手动操作,解放了开发者的手动DOM成本,提高开发效率,从根本上解决了UI与状态同步问题。
虚拟DOM的优劣如何?
优点:
1、保证性能下限:虚拟DOM可以经过diff找出最小差异,然后批量进行patch,这种操作虽然比不上手动优化,但是比起粗暴的DOM操作性能要好很多,因此虚拟DOM可以保证性能下限。
2、无需手动操作DOM:虚拟DOM的diff和patch都是在一次更新中自动进行的,我们无需手动操作DOM,极大提高开发效率。
3、跨平台:虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器渲染、移动端开发等等。
缺点:
无法进行极致优化:在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致化,比如VScode采用直接手动操作DOM的方式进行极端的性能优化。
虚拟DOM实现原理?
1、虚拟DOM本质上是JavaScript对象,是对真实DOM的抽象
2、状态变更时,记录新树和旧树的差异
3、最后把差异更新到真正的DOM中
React最新的生命周期是怎样的?
挂载阶段:
1、constructor:构造函数,最先被执行,通常在构造函数里初始化state对象或者给自定义方法绑定this
2、getDerivedStateFromProps:static getDerivedStateFromProps(nextProps, prevState),这是个静态方法,当接收到新的属性想去修改state,可以使用getDerivedStateFromProps
3、render:render函数是纯函数,只返回需要渲染的东西,不应该包含其它的业务逻辑,可以返回原生的DOM、React组件、Fragment、Portals、字符串和数字、Boolean和null等内容
4、componentDidMount:组件装载之后调用,此时可以获取到DOM节点并操作,比如对canvas,svg的操作,服务器请求,订阅都可以写在这个里面,但是记得在componentWillUnmount中取消订阅
更新阶段:
1、getDerivedStateFromProps:此方法在更新个挂载阶段都可能会调用
2、shouldComponentUpdate:shouldComponentUpdate(nextProps,nextState),有两个参数nextProps和nextState,表示新的属性和变化之后的state,返回一个布尔值,true表示会触发重新渲染,false表示不会触发重新渲染,默认返回true,通常利用此生命周期来优化React程序性能
3、render:更新阶段也会触发此生命周期
4、getSnapshotBeforeUpdate:getSnapshotBeforeUpdate(prevProps,prevState),这个方法在render之后,componentDidUpdate之前调用,有两个参数prevProps和prevState,表示之前的属性和之前的state,这个函数有一个返回值,会作为第三个参数传给componentDidUpdate,如果不想要返回值,可以返回null,此生命周期必须与componentDidUpdate搭配使用
5、componentDidUpdate:componentDidUpdate(prevProps,prevState,snapshot),该方法在getSnapshotBeforeUpdate方法之后被调用,有三个参数prevProps,prevState,snapshot,表示之前的props,之前的state,和snapshot。第三个参数是getSnapshopBeforeUpdate,然后在componentDidUpdate中统一触发回调或更新状态
卸载阶段:
componentWillUnmount:当组件被卸载或者销毁了就会调用,可以在这个函数里去清除一些定时器,取消网络请求,清理无效的DOM元素等垃圾清理工作

React的请求应该放在哪个生命周期中?
React的异步请求有人认为放在componentWillMount中可以提前进行异步请求,避免白屏,此观点有问题
由于JavaScript中异步事件的性质,当启动API调用时,浏览器会在此期间返回执行其他工作。当React渲染一个组件时,它不会等待componentWillMount它完成任何事情,当React继续前进并继续render,没有办法"暂停"渲染以等待数据到达。
而且在componentWillMount请求会有一系列潜在的问题,首先,在服务器渲染时,如果在componentWillMount里获取数据,fetch data会执行两次,一次在服务器端一次在客户端,这造成了多余的请求,其次,在React16进行React Filber 重写后,componentWillMount可能在一次渲染中多次调用
setState到底是异步还是同步?
有时表现出异步,有时表现出同步
1、setState只在合成事件和钩子函数中是"异步"的,在原生事件和setTimeout中都是同步的
2、setState的"异步"并不是说内部有异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形成了所谓的"异步",当然可以通过第二个参数setState(partialState,)
3、setState的批量更新优化也是建立在"异步"(合成事件、钩子函数)之上的,在原生事件和setTimeout中不会批量更新,在"异步"中如果对同一个值进行多次setState,setState的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时setState多个不同的值,在更新时会对其进行合并批量更新
React组件通信如何实现?
React组件间通信方式
1、父组件向子组件通讯:父组件可以向子组件通过传props的方式,向子组件进行通讯
2、子组件向父组件通讯:props + 回调的方式,父组件向子组件传递props进行通讯,此props为作用域为父组件自身的函数,子组件调用该函数,将子组件想要传递的信息,作为参数,传递到父组件的作用域中
3、兄弟组件通信:找到这两个兄弟节点共同的父节点,结合上面两种方式由父节点转发信息进行通信
4、跨层级通信:Context设计目的是为了共享那些对于一个组件树而言是"全局"的数据,例如当前认证的用户、主题或首选语言, 对于跨越多层的全局数据通过Context通信再适合不过
5、发布订阅模式:发布者发布事件,订阅者监听事件并作出反应,我们可以通过引入event模块进行通信
6、全局状态管理工具:借助Redux或者Mobx等全局状态管理工具进行通信,这种工具会维护一个全局状态中心Store,并根据不同的事件产生新的状态
网络编程中InetAddress和InetSocketAddress的区别?
InetAddress类没有构造方法,所以不能直接new出一个对象,可以通过InetAddress类的静态方法获得InetAddress的对象
封装对象:IP及DNS
InetSocketAddress有构造方法,可以用InetSocketAddress.getAddress()创建InetAddress对象
封装对象:Socket地址(IP + 端口)
有不对欢迎指出,侵删

浙公网安备 33010602011771号