对 React 和 Vue 的了解,它们的异同
相似之处:
- 都将注意力集中放弃在外围库,而将其余性能如路由和全局状态治理交给相干的库
- 都有本人的构建工具,能让你失去一个依据最佳实际设置的我的项目模板。
- 都应用了Virtual DOM(虚构DOM)进步重绘性能
- 都有props的概念,容许组件间的数据传递
- 都激励组件化利用,将利用分拆成一个个性能明确的模块,进步复用性
不同之处:
1)数据流
Vue默认反对数据双向绑定,而React始终提倡单向数据流
2)虚构DOM
Vue2.x开始引入"Virtual DOM",打消了和React在这方面的差别,然而在具体的细节还是有各自的特点。
- Vue声称能够更快地计算出Virtual DOM的差别,这是因为它在渲染过程中,会跟踪每一个组件的依赖关系,不须要从新渲染整个组件树。
- 对于React而言,每当利用的状态被扭转时,全副子组件都会从新渲染。当然,这能够通过 PureComponent/shouldComponentUpdate这个生命周期办法来进行管制,但Vue将此视为默认的优化。
3)组件化
React与Vue最大的不同是模板的编写。
- Vue激励写近似惯例HTML的模板。写起来很靠近规范 HTML元素,只是多了一些属性。
- React举荐你所有的模板通用JavaScript的语法扩大——JSX书写。
具体来讲:React中render函数是反对闭包个性的,所以咱们import的组件在render中能够间接调用。然而在Vue中,因为模板中应用的数据都必须挂在 this 上进行一次直达,所以 import 完组件之后,还须要在 components 中再申明下。
4)监听数据变动的实现原理不同
- Vue 通过 getter/setter 以及一些函数的劫持,能准确晓得数据变动,不须要特地的优化就能达到很好的性能
- React 默认是通过比拟援用的形式进行的,如果不优化(PureComponent/shouldComponentUpdate)可能导致大量不必要的vDOM的从新渲染。这是因为 Vue 应用的是可变数据,而React更强调数据的不可变。
5)高阶组件
react能够通过高阶组件(Higher Order Components-- HOC)来扩大,而vue须要通过mixins来扩大。
起因高阶组件就是高阶函数,而React的组件自身就是纯正的函数,所以高阶函数对React来说大海捞针。相同Vue.js应用HTML模板创立视图组件,这时模板无奈无效的编译,因而Vue不采纳HOC来实现。
6)构建工具
两者都有本人的构建工具
- React ==> Create React APP
- Vue ==> vue-cli
7)跨平台
- React ==> React Native
- Vue ==> Weex
生命周期调用办法的程序是什么?
React生命周期分为三大周期,11个阶段,生命周期办法调用程序别离如下。
(1)在创立期的五大阶段,调用办法的程序如下。
- getDetaultProps:定义默认属性数据。
- getInitialState:初始化默认状态数据。
- component WillMount:组件行将被构建。
- render:渲染组件。
- componentDidMount:组件构建实现
(2)在存在期的五大阶段,调用办法的程序如下。
- componentWillReceiveProps:组件行将接管新的属性数据。
- shouldComponentUpdate:判断组件是否应该更新。
- componnent WillUpdate:组件行将更新。
- render:渲染组件。
- componentDidUpdate:组件更新实现。
(3)在销毁期的一个阶段,调用办法 componentWillUnmount,示意组件行将被销毀。
React 如何辨别 Class组件 和 Function组件
个别的形式是借助 typeof 和 Function.prototype.toString 来判断以后是不是 class,如下:
function isClass(func) { return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func));}
然而这个形式有它的局限性,因为如果用了 babel 等转换工具,将 class 写法全副转为 function 写法,下面的判断就会生效。
React 辨别 Class组件 和 Function组件的形式很奇妙,因为所有的类组件都要继承 React.Component,所以只有判断原型链上是否有 React.Component 就能够了:
AComponent.prototype instanceof React.Component
React的Fiber工作原理,解决了什么问题
- React Fiber 是一种基于浏览器的单线程调度算法。
React Fiber 用相似 requestIdleCallback 的机制来做异步 diff。然而之前数据结构不反对这样的实现异步 diff,于是 React 实现了一个相似链表的数据结构,将原来的 递归diff 变成了当初的 遍历diff,这样就能做到异步可更新了
refs的作用是什么,你在什么样的业务场景下应用refs
- 操作DOM,为什么操作DOM?
场景
- 图片渲染好后,操作图片宽高。比方做个放大镜性能
constructor 为什么不先渲染?
由ES6的继承规定得悉,不论子类写不写constructor,在new实例的过程都会给补上constructor。
所以:constructor钩子函数并不是不可短少的,子组件能够在一些状况略去。比方不本人的state,从props中获取的状况
参考 前端进阶面试题具体解答
调用 setState 之后产生了什么
在代码中调用 setState 函数之后,React 会将传入的参数与之前的状态进行合并,而后触发所谓的和谐过程(Reconciliation)。通过和谐过程,React 会以绝对高效的形式依据新的状态构建 React 元素树并且着手从新渲染整个 UI 界面。在 React 失去元素树之后,React 会计算出新的树和老的树之间的差别,而后依据差别对界面进行最小化从新渲染。通过 diff 算法,React 可能准确制导哪些地位产生了扭转以及应该如何扭转,这就保障了按需更新,而不是全副从新渲染。
- 在 setState 的时候,React 会为以后节点创立一个 updateQueue 的更新列队。
- 而后会触发 reconciliation 过程,在这个过程中,会应用名为 Fiber 的调度算法,开始生成新的 Fiber 树, Fiber 算法的最大特点是能够做到异步可中断的执行。
- 而后 React Scheduler 会依据优先级高下,先执行优先级高的节点,具体是执行 doWork 办法。
- 在 doWork 办法中,React 会执行一遍 updateQueue 中的办法,以取得新的节点。而后比照新旧节点,为老节点打上 更新、插入、替换 等 Tag。
- 以后节点 doWork 实现后,会执行 performUnitOfWork 办法取得新节点,而后再反复下面的过程。
- 当所有节点都 doWork 实现后,会触发 commitRoot 办法,React 进入 commit 阶段。
- 在 commit 阶段中,React 会依据后面为各个节点打的 Tag,一次性更新整个 dom 元素
简述react事件机制
当用户在为onClick增加函数时,React并没有将Click工夫绑定在DOM下面
而是在document处监听所有反对的事件,当事件产生并冒泡至document处时,React将事件内容封装交给中间层SyntheticEvent(负责所有事件合成)
所以当事件触发的时候,对应用对立的散发函数dispatchEvent将指定函数执行。React在本人的合成事件中重写了 stopPropagation办法,将 isPropagationStopped设置为 true,而后在遍历每一级事件的过程中依据此遍历判断是否继续执行。这就是 React本人实现的冒泡机制
redux 有什么毛病
- 一个组件所须要的数据,必须由父组件传过来,而不能像 flux 中间接从 store 取
- 当一个组件相干数据更新时,即便父组件不须要用到这个组件,父组件还是会从新 render,可能会有效率影响,或者须要写简单的
shouldComponentUpdate
进行判断
高阶组件的利用场景
权限管制
利用高阶组件的 条件渲染 个性能够对页面进行权限管制,权限管制个别分为两个维度:页面级别 和 页面元素级别
// HOC.js function withAdminAuth(WrappedComponent) { return class extends React.Component { state = { isAdmin: false, } async componentWillMount() { const currentRole = await getCurrentUserRole(); this.setState({ isAdmin: currentRole === 'Admin', }); } render() { if (this.state.isAdmin) { return <WrappedComponent {...this.props} />; } else { return (<div>您没有权限查看该页面,请分割管理员!</div>); } } }; }// 应用// pages/page-a.js class PageA extends React.Component { constructor(props) { super(props); // something here... } componentWillMount() { // fetching data } render() { // render page with data } } export default withAdminAuth(PageA);
可能你曾经发现了,高阶组件其实就是装璜器模式在 React 中的实现:通过给函数传入一个组件(函数或类)后在函数外部对该组件(函数或类)进行性能的加强(不批改传入参数的前提下),最初返回这个组件(函数或类),即容许向一个现有的组件增加新的性能,同时又不去批改该组件,属于 包装模式(Wrapper Pattern) 的一种。
什么是装璜者模式:在不扭转对象本身的前提下在程序运行期间动静的给对象增加一些额定的属性或行为
能够进步代码的复用性和灵活性。
再对高阶组件进行一个小小的总结:
- 高阶组件 不是组件,是 一个把某个组件转换成另一个组件的 函数
- 高阶组件的次要作用是 代码复用
- 高阶组件是 装璜器模式在 React 中的实现
封装组件的准则
封装准则
1、繁多准则:负责繁多的页面渲染
2、多重职责:负责多重职责,获取数据,复用逻辑,页面渲染等
3、明确承受参数:必选,非必选,参数尽量设置以_结尾,防止变量反复
4、可扩大:需要变动可能及时调整,不影响之前代码
5、代码逻辑清晰
6、封装的组件必须具备高性能,低耦合的个性
7、组件具备繁多职责:封装业务组件或者根底组件,如果不能给这个组件起一个有意义的名字,证实这个组件承当的职责可能不够繁多,须要持续抽组件,直到它能够是一个独立的组件即可
React key 是干嘛用的 为什么要加?key 次要是解决哪一类问题的
Keys 是 React 用于追踪哪些列表中元素被批改、被增加或者被移除的辅助标识。在开发过程中,咱们须要保障某个元素的 key 在其同级元素中具备唯一性。
在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是早先创立的还是被挪动而来的元素,从而缩小不必要的元素重渲染此外,React 还须要借助 Key 值来判断元素与本地状态的关联关系。
注意事项:
- key值肯定要和具体的元素—一对应;
- 尽量不要用数组的index去作为key;
- 不要在render的时候用随机数或者其余操作给元素加上不稳固的key,这样造成的性能开销比不加key的状况下更蹩脚。
React 中 keys 的作用是什么?
Keys
是React
用于追踪哪些列表中元素被批改、被增加或者被移除的辅助标识
- 在开发过程中,咱们须要保障某个元素的
key
在其同级元素中具备唯一性。在React Diff
算法中React
会借助元素的Key
值来判断该元素是早先创立的还是被挪动而来的元素,从而缩小不必要的元素重渲染。此外,React 还须要借助Key
值来判断元素与本地状态的关联关系,因而咱们绝不可漠视转换函数中Key
的重要性
我当初有一个button,要用react在下面绑定点击事件,要怎么做?
class Demo { render() { return <button onClick={(e) => { alert('我点击了按钮') }}> 按钮 </button> }}
你感觉你这样设置点击事件会有什么问题吗?
因为onClick
应用的是匿名函数,所有每次重渲染的时候,会把该onClick
当做一个新的prop
来解决,会将外部缓存的onClick
事件进行从新赋值,所以绝对间接应用函数来说,可能有一点的性能降落
批改
class Demo { onClick = (e) => { alert('我点击了按钮') } render() { return <button onClick={this.onClick}> 按钮 </button> }
类组件(Class component)和函数式组件(Functional component)之间有何不同
- 类组件不仅容许你应用更多额定的性能,如组件本身的状态和生命周期钩子,也能使组件间接拜访
store
并维持状态 - 当组件仅是接管
props
,并将组件本身渲染到页面时,该组件就是一个 '无状态组件(stateless component)',能够应用一个纯函数来创立这样的组件。这种组件也被称为哑组件(dumb components)或展现组件
什么起因会促使你脱离 create-react-app 的依赖
当你想去配置 webpack 或 babel presets。
对虚构 DOM 的了解?虚构 DOM 次要做了什么?虚构 DOM 自身是什么?
从实质上来说,Virtual Dom是一个JavaScript对象,通过对象的形式来示意DOM构造。将页面的状态形象为JS对象的模式,配合不同的渲染工具,使跨平台渲染成为可能。通过事务处理机制,将屡次DOM批改的后果一次性的更新到页面上,从而无效的缩小页面渲染的次数,缩小批改DOM的重绘重排次数,进步渲染性能。
虚构DOM是对DOM的形象,这个对象是更加轻量级的对DOM的形容。它设计的最后目标,就是更好的跨平台,比方node.js就没有DOM,如果想实现SSR,那么一个形式就是借助虚构dom,因为虚构dom自身是js对象。 在代码渲染到页面之前,vue或者react会把代码转换成一个对象(虚构DOM)。以对象的模式来形容实在dom构造,最终渲染到页面。在每次数据发生变化前,虚构dom都会缓存一份,变动之时,当初的虚构dom会与缓存的虚构dom进行比拟。在vue或者react外部封装了diff算法,通过这个算法来进行比拟,渲染时批改扭转的变动,原先没有产生扭转的通过原先的数据进行渲染。
另外古代前端框架的一个根本要求就是毋庸手动操作DOM,一方面是因为手动操作DOM无奈保障程序性能,多人合作的我的项目中如果review不严格,可能会有开发者写出性能较低的代码,另一方面更重要的是省略手动DOM操作能够大大提高开发效率。
为什么要用 Virtual DOM:
(1)保障性能上限,在不进行手动优化的状况下,提供过得去的性能
上面比照一下批改DOM时实在DOM操作和Virtual DOM的过程,来看一下它们重排重绘的性能耗费∶
- 实在DOM∶ 生成HTML字符串+ 重建所有的DOM元素
- Virtual DOM∶ 生成vNode+ DOMDiff+必要的DOM更新
Virtual DOM的更新DOM的筹备工作消耗更多的工夫,也就是JS层面,相比于更多的DOM操作它的生产是极其便宜的。尤雨溪在社区论坛中说道∶ 框架给你的保障是,你不须要手动优化的状况下,我仍然能够给你提供过得去的性能。 (2)跨平台 Virtual DOM实质上是JavaScript的对象,它能够很不便的跨平台操作,比方服务端渲染、uniapp等。
这段代码有什么问题?
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=" 前端技术业余学习平台"></App>,ickt )
在页面中失常输入“有课前端网-前端技术业余学习平台”。然而这种写法很少应用,并不是罕用的写法。React容许对 setState办法传递一个函数,它接管到先前的状态和属性数据并返回一个须要批改的状态对象,正如咱们在下面所做的那样。它岂但没有问题,而且如果依据以前的状态( state)以及属性来批改以后状态,举荐应用这种写法。
何为 reducer
一个 reducer 是一个纯函数,该函数以先前的 state 和一个 action 作为参数,并返回下一个 state。
(组件的)状态(state)和属性(props)之间有何不同
State
是一种数据结构,用于组件挂载时所需数据的默认值。State
可能会随着工夫的推移而产生渐变,但少数时候是作为用户事件行为的后果。
Props
(properties 的简写)则是组件的配置。props
由父组件传递给子组件,并且就子组件而言,props
是不可变的(immutable)。组件不能扭转本身的 props,然而能够把其子组件的 props 放在一起(对立治理)。Props 也不仅仅是数据--回调函数也能够通过 props 传递。
redux是如何更新值得
用户发动操作之后,dispatch发送action ,依据type,触发对于的reducer,reducer 就是一个纯函数,接管旧的 state 和 action,返回新的 state。通过 subscribe(listener)监听器,派发更新。