redux与mobx的区别?

两者对⽐:

  • redux将数据保存在单⼀的store中,mobx将数据保存在分散的多个store中
  • redux使⽤plain object保存数据,需要⼿动处理变化后的操作;mobx适⽤observable保存数据,数据变化后⾃动处理响应的操作
  • redux使⽤不可变状态,这意味着状态是只读的,不能直接去修改它,⽽是应该返回⼀个新的状态,同时使⽤纯函数;mobx中的状态是可变的,可以直接对其进⾏修改

mobx相对来说⽐较简单,在其中有很多的抽象,mobx更多的使⽤⾯向对象的编程思维;redux会⽐较复杂,因为其中的函数式编程思想掌握起来不是那么容易,同时需要借助⼀系列的中间件来处理异步和副作⽤

  • mobx中有更多的抽象和封装,调试会⽐较困难,同时结果也难以预测;⽽redux提供能够进⾏时间回溯的开发⼯具,同时其纯函数以及更少的抽象,让调试变得更加的容易

场景辨析:

  • 基于以上区别,我们可以简单得分析⼀下两者的不同使⽤场景。
  • mobx更适合数据不复杂的应⽤:mobx难以调试,很多状态⽆法回溯,⾯对复杂度⾼的应⽤时,往往⼒不从⼼。
  • redux适合有回溯需求的应⽤:⽐如⼀个画板应⽤、⼀个表格应⽤,很多时候需要撤销、重做等操作,由于redux不可变的特性,天然⽀持这些操作。
  • mobx适合短平快的项⽬:mobx上⼿简单,样板代码少,可以很⼤程度上提⾼开发效率。
  • 当然mobx和redux也并不⼀定是⾮此即彼的关系,你也可以在项⽬中⽤redux作为全局状态管理,⽤mobx作为组件局部状态管理器来⽤。

什么是 prop drilling,如何避免?

在构建 React 应用程序时,在多层嵌套组件来使用另一个嵌套组件提供的数据。最简单的方法是将一个 prop 从每个组件一层层的传递下去,从源组件传递到深层嵌套组件,这叫做prop drilling
prop drilling的主要缺点是原本不需要数据的组件变得不必要地复杂,并且难以维护。
为了避免prop drilling,一种常用的方法是使用React Context。通过定义提供数据的Provider组件,并允许嵌套的组件通过Consumer组件或useContext Hook 使用上下文数据。

这段代码有什么问题吗?

这段代码有什么问题:

this.setState((prevState, props) => {
  return {
    streak: prevState.streak + props.count,
  };
});

答案:
没有什么问题。这种方式很少被使用,咱们可以将一个函数传递给setState,该函数接收上一个 state 的值和当前的props,并返回一个新的状态,如果咱们需要根据以前的状态重新设置状态,推荐使用这种方式。

diff算法是怎么运作

每一种节点类型有自己的属性,也就是prop,每次进行diff的时候,react会先比较该节点类型,假如节点类型不一样,那么react会直接删除该节点,然后直接创建新的节点插入到其中,假如节点类型一样,那么会比较prop是否有更新,假如有prop不一样,那么react会判定该节点有更新,那么重渲染该节点,然后在对其子节点进行比较,一层一层往下,直到没有子节点

React 的生命周期方法有哪些?

  • componentWillMount:在渲染之前执行,用于根组件中的 App 级配置。
  • componentDidMount:在第一次渲染之后执行,可以在这里做AJAX请求,DOM 的操作或状态更新以及设置事件监听器。
  • componentWillReceiveProps:在初始化render的时候不会执行,它会在组件接受到新的状态(Props)时被触发,一般用于父组件状态更新时子组件的重新渲染
  • shouldComponentUpdate:确定是否更新组件。默认情况下,它返回true。如果确定在 stateprops 更新后组件不需要在重新渲染,则可以返回false,这是一个提高性能的方法。
  • componentWillUpdate:在shouldComponentUpdate返回 true 确定要更新组件之前件之前执行。
  • componentDidUpdate:它主要用于更新DOM以响应propsstate更改。
  • componentWillUnmount:它用于取消任何的网络请求,或删除与组件关联的所有事件监听器。

使用 React Hooks 好处是啥?

首先,Hooks 通常支持提取和重用跨多个组件通用的有状态逻辑,而无需承担高阶组件或渲染 props 的负担。Hooks 可以轻松地操作函数组件的状态,而不需要将它们转换为类组件。
Hooks 在类中不起作用,通过使用它们,咱们可以完全避免使用生命周期方法,例如 componentDidMountcomponentDidUpdatecomponentWillUnmount。相反,使用像useEffect这样的内置钩子。

参考 前端进阶面试题详细解答

什么情况下使用异步组件

  • 提高页面加载速度,使用reloadable把各个页面分别单独打包,按需加载

Dva工作原理

集成redux+redux-saga

工作原理

改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State

React 中 refs 干嘛用的?

Refs 提供了一种访问在render方法中创建的 DOM 节点或者 React 元素的方法。在典型的数据流中,props 是父子组件交互的唯一方式,想要修改子组件,需要使用新的pros重新渲染它。凡事有例外,某些情况下咱们需要在典型数据流外,强制修改子代,这个时候可以使用 Refs
咱们可以在组件添加一个 ref 属性来使用,该属性的值是一个回调函数,接收作为其第一个参数的底层 DOM 元素或组件的挂载实例。

class UnControlledForm extends Component {
  handleSubmit = () => {
    console.log("Input Value: ", this.input.value);
  };
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="text" ref={(input) => (this.input = input)} />
        <button type="submit">Submit</button>
      </form>
    );
  }
}

请注意,input 元素有一个ref属性,它的值是一个函数。该函数接收输入的实际 DOM 元素,然后将其放在实例上,这样就可以在 handleSubmit 函数内部访问它。
经常被误解的只有在类组件中才能使用 refs,但是refs也可以通过利用 JS 中的闭包与函数组件一起使用。

function CustomForm({ handleSubmit }) {
  let inputElement;
  return (
    <form onSubmit={() => handleSubmit(inputElement.value)}>
      <input type="text" ref={(input) => (inputElement = input)} />
      <button type="submit">Submit</button>
    </form>
  );
}

为什么类方法需要绑定到类实例?

在 JS 中,this 值会根据当前上下文变化。在 React 类组件方法中,开发人员通常希望 this 引用组件的当前实例,因此有必要将这些方法绑定到实例。通常这是在构造函数中完成的:

class SubmitButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isFormSubmitted: false,
    };
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  handleSubmit() {
    this.setState({
      isFormSubmitted: true,
    });
  }
  render() {
    return <button onClick={this.handleSubmit}>Submit</button>;
  }
}

描述 Flux 与 MVC?

传统的 MVC 模式在分离数据(Model)、UI(View和逻辑(Controller)方面工作得很好,但是 MVC 架构经常遇到两个主要问题:
数据流不够清晰:跨视图发生的级联更新常常会导致混乱的事件网络,难于调试。
缺乏数据完整性:模型数据可以在任何地方发生突变,从而在整个UI中产生不可预测的结果。
使用 Flux 模式的复杂用户界面不再遭受级联更新,任何给定的React 组件都能够根据 store 提供的数据重建其状态。Flux 模式还通过限制对共享数据的直接访问来加强数据完整性。

state 和 props 共同点和区别

共同点

  • state 和props的改变都会触发render函数(界面会发生改变)

不同点

  • props 是readonly(只读),但是state是可读可写
  • props 来自父组件,state是组件内部的数据对象

如何有条件地向 React 组件添加属性?

对于某些属性,React 非常聪明,如果传递给它的值是虚值,可以省略该属性。例如:

var InputComponent = React.createClass({
  render: function () {
    var required = true;
    var disabled = false;
    return <input type="text" disabled={disabled} required={required} />;
  },
});

渲染结果:

<input type="text" required>

另一种可能的方法是:

var condition = true;
var component = <div value="foo" {...(condition && { disabled: true })} />;

redux异步中间件之间的优劣?

redux-thunk优点:

  • 体积⼩:redux-thunk的实现⽅式很简单,只有不到20⾏代码;
  • 使⽤简单:redux-thunk没有引⼊像redux-saga或者redux-observable额外的范式,上⼿简单。

redux-thunk缺陷:

  • 样板代码过多:与redux本身⼀样,通常⼀个请求需要⼤量的代码,⽽且很多都是重复性质的;
  • 耦合严重:异步操作与redux的action偶合在⼀起,不⽅便管理;
  • 功能孱弱:有⼀些实际开发中常⽤的功能需要⾃⼰进⾏封装。

redux-saga优点:

  • 异步解耦:异步操作被被转移到单独saga.js中,不再是掺杂在action.js或component.js中;
  • action摆脱thunk function: dispatch的参数依然是⼀个纯粹的 action (FSA),⽽不是充满 “⿊魔法” thunk function;
  • 异常处理:受益于 generator function 的saga实现,代码异常/请求失败都可以直接通过try/catch语法直接捕获处理;
  • 功能强⼤:redux-saga提供了⼤量的Saga辅助函数和Effect创建器供开发者使⽤,开发者⽆须封装或者简单封装即可使⽤;
  • 灵活:redux-saga可以将多个Saga可以串⾏/并⾏组合起来,形成⼀个⾮常实⽤的异步flow;
  • 易测试,提供了各种case的测试⽅案,包括mock task,分⽀覆盖等等。

redux-saga缺陷:

  • 额外的学习成本:redux-saga不仅在使⽤难以理解的generator function,⽽且有数⼗个API,学习成本远超reduxthunk,最重要的是你的额外学习成本是只服务于这个库的,与redux-observable不同,redux-observable虽然也有额外学习成本但是背后是rxjs和⼀整套思想;
  • 体积庞⼤:体积略⼤,代码近2000⾏,min版25KB左右;
  • 功能过剩:实际上并发控制等功能很难⽤到,但是我们依然需要引⼊这些代码;
  • ts⽀持不友好:yield⽆法返回TS类型。

redux-observable优点:

  • 功能最强:由于背靠rxjs这个强⼤的响应式编程的库,借助rxjs的操作符,你可以⼏乎做任何你能想到的异步处理;
  • 背靠rxjs:由于有rxjs的加持,如果你已经学习了rxjs,redux-observable的学习成本并不⾼,⽽且随着rxjs的升级reduxobservable也会变得更强⼤。

redux-observable缺陷:

  • 学习成本奇⾼:如果你不会rxjs,则需要额外学习两个复杂的库;
  • 社区⼀般:redux-observable的下载量只有redux-saga的1/5,社区也不够活跃,在复杂异步流中间件这个层⾯reduxsaga仍处于领导地位。

react的全家桶有哪些

  • react:核心
  • redux:相当于数据,主要存储数据状态

    react-redux可以完成数据订阅

    redux-thunk可以实现异步的action

    redux-logger是redux的日志中间件

    react-router 专门为react提供路由解决方案,它利用HTML5 的history API,来操作浏览器的 session history (会话历史)

  • react-router:提供核心的路由组件与函数

    react-router-config:用来配置静态路由(还在开发中)

    react-router-native:

    react-router-dom:

  • axios:是基于promise的用于浏览器和服务端进行数据交互的技术
  • antd:Ant Degisn是个很好的React UI库

React 性能优化

  • shouldCompoentUpdate
  • pureComponent 自带shouldCompoentUpdate的浅比较优化
  • 结合Immutable.js达到最优

如何告诉 React 它应该编译生产环境版

通常情况下我们会使用 WebpackDefinePlugin 方法来将 NODE_ENV 变量值设置为 production。编译版本中 React会忽略 propType 验证以及其他的告警信息,同时还会降低代码库的大小,React 使用了 Uglify 插件来移除生产环境下不必要的注释等信息

React- Router有几种形式?

有以下几种形式。
HashRouter,通过散列实现,路由要带#。
BrowerRouter,利用HTML5中 history API实现,需要服务器端支持,兼容性不是很好。

react-router4的核心

  • 路由变成了组件
  • 分散到各个页面,不需要配置 比如<link> <route></route>

简述flux 思想

Flux 的最大特点,就是数据的"单向流动"。
  • 用户访问 View
  • View发出用户的 Action
  • Dispatcher 收到Action,要求 Store 进行相应的更新
  • Store 更新后,发出一个"change"事件
  • View 收到"change"事件后,更新页面

紧张的大葱
35 声望3 粉丝