2019前端面试题-框架、架构篇

yarn和npm的区别

yarn的优点:

  • 速度快
    • 并行安装
    • 离线模式
  • 安装版本统一
  • 更简洁的输出
  • 多注册来源处理
  • 更好的语义化

zhuanlan.zhihu.com/p/27449990

yarn.lock

yarn.lock 会记录你安装的所有大大小小的软件包的具体版本号。只要你不删除 yarn.lock 文件,再次运行 yarn install 时,会根据其中记录的版本号获取所有依赖包。你可以把 yarn.lock 提交到版本库里,这样其他同事签出代码并运行 yarn install 时,可以保证大家安装的依赖都是完全一致的。

Virtual DOM 真的比操作原生 DOM 快吗?谈谈你的想法

虚拟 DOM 就是用来模拟 DOM 的一个对象,这个对象拥有一些重要属性,并且更新 UI 主要就是通过对比(DIFF)旧的虚拟 DOM 树 和新的虚拟 DOM 树的区别完成的。

  • innerHTML vs. Virtual DOM 的重绘性能消耗:

innerHTML: render html string O(template size) + 重新创建所有 DOM 元素 O(DOM size)

Virtual DOM: render Virtual DOM + diff O(template size) + 必要的 DOM 更新 O(DOM change)

Virtual DOM render + diff 显然比渲染 html 字符串要慢,但是!它依然是纯 js 层面的计算,比起后面的 DOM 操作来说,依然便宜了太多。可以看到,innerHTML 的总计算量不管是 js 计算还是 DOM 操作都是和整个界面的大小相关,但 Virtual DOM 的计算量里面,只有 js 计算和界面大小相关,DOM 操作是和数据的变动量相关的。前面说了,和 DOM 操作比起来,js 计算是极其便宜的。这才是为什么要有 Virtual DOM:它保证了 1)不管你的数据变化多少,每次重绘的性能都可以接受;2) 你依然可以用类似 innerHTML 的思路去写你的应用。

Virtual DOM 为了提升小量数据更新时的性能,也需要针对性的优化,比如 shouldComponentUpdate 或是 immutable data

Virtual DOM 真正的价值从来都不是性能,而是它 1) 为函数式的 UI 编程方式打开了大门;2) 可以渲染到 DOM 以外的 backend,比如 ReactNative。

www.zhihu.com/question/31…

使用react的好处

  • 虚拟DOM,提升性能
  • 组件化
  • 单向数据流(数据流更清晰,组件的状态就更可控;)

redux与缺陷

redux设计有以下几个要点:

  • state是单例模式且不可变的,单例模式避免了不同store之间的数据交换的复杂性,而不可变数据提供了十分快捷的撤销重做、“时光旅行”等功能。
  • state只能通过reducer来更新,不可以直接修改。
  • reducer必须是纯函数,形如(state,action) => newState

react-redux主要包含两个部分。

  • Provider组件:可以将store注入到子组件的cotext中,所以一般放在应用的最顶层。
  • connect函数: 返回一个高阶函数,把context中由Provider注入的store取出来然后通过props传递到子组件中,这样子组件就能顺利获取到store了。

缺点

  • 1.样板代码过多:
  • 2.更新效率问题:由于使用不可变数据模式,每次更新state都需要拷贝一份完整的state造成了内存的浪费以及性能的损耗。 (用immutable解决)
  • 3.数据传递效率问题:由于react-redux采用的旧版context API,context的传递存在着效率问题。

react hook

Hook 提供了更直接的 API:props, state,context,refs 以及生命周期

useState 会返回一对值:当前状态和一个让你更新它的函数

const [count, setCount] = useState(0);

useEffect 它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API。

// 相当于 componentDidMount 和 componentDidUpdate:
  useEffect(() => {
    // 使用浏览器的 API 更新页面标题
    document.title = `You clicked ${count} times`;
  });
复制代码

useEffect 可以在组件渲染后实现各种不同的副作用。有些副作用可能需要清除,所以需要返回一个函数:

useEffect(() => {
  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }

  ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
  
  return () => {
    ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
  };
});
复制代码

规则

  • 只在最顶层使用 Hook
  • 只在 React 函数中调用 Hook

react 性能优化

  • 使用生产版本
  • webpack打包
  • showComponentUpdate
  • 使用immutable数据

react的组件生命周期

简版

详细版

挂载

当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:

constructor()

static getDerivedStateFromProps()

render()

componentDidMount()

更新

当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:

static getDerivedStateFromProps()

shouldComponentUpdate()

render()

getSnapshotBeforeUpdate()

componentDidUpdate()

如果 shouldComponentUpdate() 返回 false,则不会调用 render()。

卸载

componentWillUnmount()

错误处理

当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:

static getDerivedStateFromError() componentDidCatch()

getDerivedStateFormProps

取代componentWillReceiveProps()。这个钩子是从props去取到state的值。

getSnapshotBeforeUpdate(prevProps,prevState)

getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。

此用法并不常见,但它可能出现在 UI 处理中,如需要以特殊方式处理滚动位置的聊天线程等。

应返回 snapshot 的值(或 null)。

constructor()

  • state值初始化
  • super(props)否则会报错
  • 为事件绑定实例

react diff

React 通过制定大胆的 diff 策略,将 O(n3) 复杂度的问题转换成 O(n) 复杂度的问题;

  • DOM 节点跨层级的移动操作特别少
  • 相同类的组件生成相似的树形结构,不同类的组件生成不同的树形结构
  • 同一层级的一组子节点,可以用唯一id区分 tree diff component diff element diff

React 通过分层求异的策略,对 tree diff 进行算法优化;

React 通过相同类生成相似树形结构,不同类生成不同树形结构的策略,对 component diff 进行算法优化;

React 通过设置唯一 key的策略,对 element diff 进行算法优化;

建议,在开发组件时,保持稳定的 DOM 结构会有助于性能的提升;

建议,在开发过程中,尽量减少类似将最后一个节点移动到列表首部的操作,当节点数量过大或更新操作过于频繁时,在一定程度上会影响 React 的渲染性能。 zhuanlan.zhihu.com/p/2034637

用webpack实现按需加载

在AntDesign出品的babel-plugin-import 安装以上插件后,在.babelrc

react和Vue的区别

  • react是单向数据流,vue是双向数据流
  • 在 React 应用中,当某个组件的状态发生变化时,它会以该组件为根,重新渲染整个组件子树。在 Vue 应用中,组件的依赖是在渲染过程中自动追踪的,所以系统能精确知晓哪个组件确实需要被重渲染。

服务端渲染,就next.js

服务端渲染:渲染过程在服务器端完成,最终的渲染结果 HTML 页面通过 HTTP 协议发送给客户端。对于客户端而言,只是看到了最终的 HTML 页面,看不到数据,也看不到模板。

  • 优点
    • 是容易 SEO,首屏加载快,因为客户端接收到的是完整的 HTML 页面 -缺点
    • 耗费后端资源。费流量,即使局部页面的变化也需要重新发送整个页

客户端渲染:服务器端把模板和数据发送给客户端,渲染过程在客户端完成。

  • 优点
    • 节省后端资源,局部刷新页面,多端渲染,前后端分离
  • 缺点
    • 首屏性能差,白屏,无法(或很难)进行 SEO

服务端渲染的优点就是客户端渲染的缺点,服务端渲染的缺点同时也是客户端渲染的优点,反之亦然

Next.js 做的是同构渲染。同一套代码既可以在服务器端渲染,也可以在客户端渲染。Exciting当我们首次访问时,换言之当我们访问首屏页面时,Next.js 使用服务器端渲染,为我们返回已经渲染完成的最终 HTML 页面。这样就同时解决了首屏白屏问题以及 SEO 问题。此后当我们再进行交互时,则使用客户端渲染。HTML、CSS、JS 等资源都不需要再重新请求,只需要通过 ajax/websocket 等途径获取数据,在客户端完成渲染过程。

context

Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。Context提供了一个无需为每层组件手动添加props,就能在组件树间进行数据传递的方法。

  • provider,props的生产者
  • consumers, 消费prover提供的value
const ThemeContext = React.createContext('light');  //创建context,设置默认值
复制代码

react-router 里的 标签和 标签有什么区别

的“跳转”行为只会触发相匹配的 对应的页面内容更新,而不会刷新整个页面。 而 标签就是普通的超链接了,用于从当前页面跳转到 href 指向的另一个页面(非锚点情况)。

转载于:https://juejin.im/post/5cee29b7f265da1b8b2b40ca

你可能感兴趣的:(2019前端面试题-框架、架构篇)