前端面试(React框架二)

简介: 本文对比了React中class与createClass的用法,探讨Vue与React在数据更新、模板语法及优化机制上的差异,解析高阶组件(HOC)的复用逻辑、React事件机制中的合成事件与事件代理,并深入讲解Redux状态管理流程及其纯函数reducer的设计原理。同时介绍虚拟DOM(VDOM)的结构、Diff算法的同层比对与key值作用,说明其如何提升渲染性能,适用于Vue和React的核心更新机制。

17. class和createClass的比较

一个调用React.createClass并传入一个对象,另一个则是使用class继承React.Component

var InputControlES5 = React.createClass({
propTypes: {
  initialValue: React.PropTypes.string
},
defaultProps: {
  initialValue: ''
}, // Set up initial state
getInitialState: function() {
  return {
    text: this.props.initialValue || 'placeholder'
  };
},
handleChange: function(event) {
  this.setState({
    text: event.target.value
  });
},
render: function() {
  return (
    <div>
      Type something:
      <input onChange={this.handleChange}
        value={this.state.text} />
      </div>
    );
  }
});
Copy

18. 谈一下Vue 和 React区别?

  1. 改变数据方式不同,Vue 修改状态相比来说要简单许多,React 需要使用 setState 来改变状态,并且使用这个 API 也有一些坑点。
  2. Vue 的底层使用了依赖追踪,页面更新渲染已经是最优的了,但是 React 还是需要用户手动去优化这方面的问题。
  3. React 需要使用 JSX,Vue 使用了模板语法

19. 高阶组件 HOC (higher order component)

高阶组件是一个以组件为参数并返回一个新组件的函数。

  1. HOC 允许你重用代码、逻辑和引导抽象。
  2. 最常见的可能是 Redux 的 connect 函数。
  3. 除了简单分享工具库和简单的组合,HOC 最好的方式是共享 React 组件之间的行为。
  4. 如果你发现你在不同的地方写了大量代码来做同一件事时,就应该考虑将代码重构为可重用的 HOC。
function add(a, b) {
    return a + b
}
Copy

现在如果我想给这个 add 函数添加一个输出结果的功能,那么你可能会考虑我直接使用 console.log 不就实现了么。说的没错,但是如果我们想做的更加优雅并且容易复用和扩展,我们可以这样去做:

function withLog (fn) {
    function wrapper(a, b) {
        const result = fn(a, b)
        console.log(result)
        return result
    }
    return wrapper
}
const withLogAdd = withLog(add)
withLogAdd(1, 2)
Copy

这个做法在函数式编程里称之为高阶函数,大家都知道 React 的思想中是存在函数式编程的,高阶组件和高阶函数就是同一个东西。我们实现一个函数,传入一个组件,然后在函数内部再实现一个函数去扩展传入的组件,最后返回一个新的组件,这就是高阶组件的概念,作用就是为了更好的复用代码。

20. 谈一下React的事件机制

React 其实自己实现了一套事件机制,首先我们考虑一下以下代码

const Test = ({ list, handleClick }) => ({
    list.map((item, index) => (
        <span onClick={handleClick} key={index}>{index}</span>
    ))
})
Copy
  1. 事实当然不是,JSX 上写的事件并没有绑定在对应的真实 DOM 上,而是通过事件代理的方式,将所有的事件都统一绑定在了document。这样的方式不仅减少了内存消耗,还能在组件挂载销毁时统一订阅和移除事件。
  2. 另外冒泡到 document 上的事件也不是原生浏览器事件,而是React自己实现的合成事件(SyntheticEvent)。因此我们如果不想要事件冒泡的话,调用 event.stopPropagation 是无效的,而应该调用 event.preventDefault。
  3. 那么实现合成事件的目的好处有两点,分别是:
  • 合成事件首先抹平了浏览器之间的兼容问题,另外这是一个跨浏览器原生事件包装器,赋予了跨浏览器开发的能力
  • 对于原生浏览器事件来说,浏览器会给监听器创建一个事件对象。如果你有很多的事件监听,那么就需要分配很多的事件对象,造成高额的内存分配问题。但是对于合成事件来说,有一个事件池专门来管理它们的创建和销毁,当事件需要被使用时,就会从池子中复用对象,事件回调结束后,就会销毁事件对象上的属性,从而便于下次复用事件对象。

21. redux简介

redux 是一个应用数据流框架,主要是解决了组件间状态共享的问题,原理是集中式管理,主要有三个核心方法,action,store,reducer

工作流程是:

  • view用actionCreator创建一个action,里面可能包含一些数据
  • 使用store的dispatch方法将acion传入store
  • store将action与旧的state转发给reducer
  • reducer深拷贝state,并返回一个新的state给store
  • store接收并更新state
  • 使用store.subscribe订阅更新,重新render组件

21.1 reducer为什么是纯函数?

Note

从本质上讲,纯函数的定义如下:不修改函数的输入值,依赖于外部状态(比如数据库,DOM和全局变量),同时对于任何相同的输入有着相同的输出结果。

21.2 原理解析

  1. 阅读源码可以看到,Redux接收一个给定的state(对象),然后通过循环将state的每一部分传递给每个对应的reducer。如果有发生任何改变,reducer将返回一个新的对象。如果不发生任何变化,reducer将返回旧的state。
  2. Redux只通过比较新旧两个对象的存储位置来比较新旧两个对象是否相同(也就是Javascript对象浅比较)。如果你在reducer内部直接修改旧的state对象的属性值,那么新的state和旧的state将都指向同一个对象。因此Redux认为没有任何改变,返回的state将为旧的state。
  3. 深比较在真实的应用当中代价昂贵,因为通常js的对象都很大,同时需要比较的次数很多。
  4. 因此一个有效的解决方法是作出一个规定:无论何时发生变化时,开发者都要创建一个新的对象,然后将新对象传递出去。同时,当没有任何变化发生时,开发者发送回旧的对象。也就是说,新的对象代表新的state。 使用了新的策略之后,你能够比较两个对象通过使用!==比较两个对象的存储位置而不是比较两个对象的所有属性。

22. VDOM是什么?为什么会存在VDOM?

22.1 VDom的产生原因

  1. 非常耗费性能的。而且JS操作DOM是非常复杂,JS操作DOM越多,控制与页面的耦合度就越高,代码越难以维护。
  2. 虚拟DOM,即用JS对象来描述DOM树结构,Diff算法则是找旧VDOM与新的VDOM的最小差异,然后再把差异渲染出来

22.2 VDOM的组成

  • tag 标签名
  • attrs DOM属性键值对
  • childen DOM字节点数组 或 文本内容

如何理解虚拟 DOM?-zhihu

22.3 为什么DOM操作慢? 因为属性太多了

22.4 vdom如何应用,核心API是什么?

  1. 创建虚拟节点
  • h('标签名', {...属性...}, [...子元素...])
  • h('标签名', {...属性...}, '文本内容')
  1. 将VNode添加到一个DOM元素内
  • patch(DOM_obj, vnode);
  1. 用一个新的vnode来和旧的vnode进行比较,得出新旧dom的差异
  2. patch(vnode, newVnode)

23. diff算法

23.1 对比Vdom树差异的算法

React 的 diff 算法

23.2 同层比对

新旧状态的比对时采用同层比对,当发现某节点不一致了直接替换该节点的子树。而不管它的子树是不是真的改动了。

23.3 key值的使用

  1. 在列表循环的时候React会要求每一个列表项有一个独一无二稳定的key值,它的目的是为了当状态改变时新旧状态的每一个列表项能够对应起来,方便比对。
  2. Key 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。
  3. Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系

23.4 合并操作

调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制

23.5 diff算法的流程

  1. tree diff 新旧两棵DOM树,逐层对比的过程,就是 Tree Diff; 当整颗DOM逐层对比完毕,则所有需要被按需更新的元素,必然能够找到;
  2. component diff 在进行Tree Diff的时候,每一层中,组件级别的对比,叫做 Component Diff;
  • 如果对比前后,组件的类型相同,则暂时认为此组件不需要被更新;
  • 如果对比前后,组件类型不同,则需要移除旧组件,创建新组件,并追加到页面上;(重新创建并追加到页面上去)
  1. element diff 在进行组件对比的时候,如果两个组件类型相同,则需要进行 元素级别的对比,这叫做 Element Diff;

24. Vue和React中key的作用?(面试重点)

  1. 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
  2. 同一层级的一组节点,他们可以通过唯一的id进行区分。

基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从O(n^3)降到了O(n)。

  1. 当页面的数据发生变化时,Diff算法只会比较同一层级的节点:
  2. 如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。
  3. 如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。
  4. 当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。

Note

所以一句话,key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。

目录
相关文章
|
14天前
|
安全 编译器 PHP
PHP 8.x:让老将焕发新活力
PHP 8.x:让老将焕发新活力
155 76
|
14天前
|
机器学习/深度学习 人工智能 缓存
CALM自编码器:用连续向量替代离散token,生成效率提升4倍
近年来语言模型效率优化多聚焦参数规模与注意力机制,却忽视了自回归生成本身的高成本。CALM提出新思路:在token之上构建潜在空间,通过变分自编码器将多个token压缩为一个连续向量,实现“一次前向传播生成多个token”。该方法大幅减少计算次数,提升推理速度与吞吐量,同时引入无似然训练与BrierLM评估体系,突破传统语言建模范式,为高效大模型提供新路径。
90 7
CALM自编码器:用连续向量替代离散token,生成效率提升4倍
|
14天前
|
人工智能 监控 Cloud Native
云原生AI赋能文旅数智化转型:玄晶引擎AI数字员工落地长白山康养项目全解析
本文以长白山大健康企业为例,介绍其通过玄晶引擎云原生AI数字员工实现“养生+文旅”模式智能化升级的实践。涵盖技术架构、运营适配、营销创新与落地经验,展现AI在内容生产、客服转化、B端获客等环节的全链路赋能,助力企业收益率提升47%、团队扩张35%,为文旅产业数智化转型提供可复用范本。
106 12
|
15天前
|
存储 人工智能 运维
AI重构知识管理:如何破解技术团队的6大效率困局
通过AI全链路赋能,实现技术文档智能生成、语义检索、隐性知识沉淀与企业级安全管控,破解研发中API文档低效、故障排查慢、知识复用难等痛点,提升文档效率300%、故障修复提速80%,助力团队从“被动管理”迈向“智能协同”,重构高效能研发新范式。
95 12
|
15天前
|
人工智能 缓存 监控
Coze AI 智能体工作流:配置与实战完整指南
本文详细介绍了如何利用Coze平台的工作流功能构建智能AI助手。通过解析核心组件并演示“个性化旅行规划师”的完整配置案例,文章展示了如何设计并行处理、集成外部工具并优化性能。重点探讨了工作流的模块化设计、版本控制及成本优化等进阶技巧,旨在帮助用户将AI从简单工具转变为能处理复杂任务、甚至具备自学习能力的业务伙伴。
|
18天前
|
Linux C语言 C++
C语言Qt编程基础(零基础入门Qt C语言开发指南)
本文介绍如何在C语言中借助C++封装调用Qt实现GUI开发。通过创建C兼容接口,结合Qt库与C主程序,初学者可快速入门C语言Qt编程,掌握跨语言混合开发技巧,为深入学习Qt打下基础。(238字)
|
24天前
|
敏捷开发 测试技术 持续交付
微服务技术栈
单元测试是保障代码质量的基石。它快速、稳定,能精准定位问题,提升代码可维护性与团队协作效率。通过“测试金字塔”模型,单元测试作为底层支撑,占比应达80%。相比端到端测试,它显著降低维护成本,助力持续交付。写单测不是踩刹车,而是为软件研发提速。
72 9
|
14天前
|
人工智能 自然语言处理 运维
2025 AI客服选型全景评测:从技术适配到价值赋能
伴随大语言模型与AI Agent技术的深度渗透,2025年智能客服行业完成了从“标准化问答工具”到“全场景智能服务中枢”的关键性跨越。这一转型不仅重构了客户服务的交互模式,更推动客服体系成为企业链接用户、优化运营的核心基础设施,其价值从单纯的成本节约延伸至业务增长赋能。
|
17天前
|
人工智能 搜索推荐 算法
AI热点选品:当推荐系统遇上“热点”,我们需要一场变革
针对传统推荐系统滞后于外部热点的问题,我们构建了“热点AI选品”自动化系统。通过小时级感知、LLM驱动的热点理解与需求推理、多模态素材召回、三级机审过滤及话题聚合技术,实现从热点捕捉到商品分发的端到端闭环,显著提升信息流的新鲜感与用户参与度。
131 12
AI热点选品:当推荐系统遇上“热点”,我们需要一场变革