React与Vue的模板

  最早接触的前端框架是Angular1.x的版本,但是真正应用到实际项目中的前端框架还是只有Vue。因为部分原因,现在终于要开始拿起React来看了。之前一直没有学习React而是选择了Vue的原因只是在于不喜欢React的JSX语法,而Vue的模板与JS代码分离的写法更加符合我的审美。

React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合,比如,在 UI 中需要绑定处理事件、在某些时刻状态发生变化时需要通知到 UI,以及需要在 UI 中展示准备好的数据。
React 并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式,而是通过将二者共同存放在称之为“组件”的松散耦合单元之中,来实现关注点分离。我们将在后面章节中深入学习组件。如果你还没有适应在 JS 中使用标记语言,这个会议讨论应该可以说服你。
React 不强制要求使用 JSX,但是大多数人发现,在 JavaScript 代码中将 JSX 和 UI 放在一起时,会在视觉上有辅助作用。它还可以使 React 显示更多有用的错误和警告消息。

其实模板这个东西很早之前就有过接触,最早接触模板这个东西还是在写ThinkPHP这个框架的时候,MVC模式的前后端耦合是我最早在大型项目中的尝试,再到后来写Laravel框架,发现模板在复用和构建组件上面确实很好用。在ES6的字符串模板出来之前,其实我非常排斥在JS代码中写HTML代码,因为需要不断的使用+做字符串拼接,一个是麻烦一个是代码写出来也非常不好看。但是,最近重新看了一下JSX的语法,发现其与Vue的写法其实非常相像。
  在Vue文件中,一个组件一般分成3个部分:<template><script><style>,其中script<style>都是局部的,除非引入全局标志,而在JSX中,一切都是JS代码,HTML部分单独用JSX语法编写,作为Js中的一个变量传入React的渲染函数中去。

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);

ReactDOM.render(
  element,
  document.getElementById('root')
);

如上面的element就是一个JSX语法编写的表示HTML内容的JS对象,在这其中一般写法如同平常的HTML语法一样,但是和ES6中的字符串模板类似的,以花括号的形式引入JS变量渲染到模板中。这个非常像PHP中的PHP代码和HTML代码的混写形式:

// test.php
<h1 class="top">
    Hello, <?php echo formatName(user) ?>
</h1>

这样看来,其实模板语言其实是相似的。

模板渲染

  众所周知,操作DOM是一个非常消耗计算资源的操作,repaint还好,如果reflow的话资源消耗是比较大的,这也是在前端面试中经常会被问到的关于页面渲染优化的问题。常见的做法是将经常变动且可能导致reflow的DOM节点脱离文档流,不让它影响整个文档的变化;或者是尽量使用repaint的动画,如使用transform变化;或者是说将很多DOM操作合并,先将目标DOM复制,在内存中全部操作完成后,再一次性渲染出来。不论采取什么方法,目标只有一个减少浏览器对于DOM节点的重新渲染。
  在Vue中,框架使用了Virtual DOM的方法,在内存中构建虚拟DOM,然后将其渲染出来。或者说:在Vue的底层实现上,Vue将模板编译成虚拟DOM渲染函数。结合Vue自带的响应系统,在状态改变时,Vue能够智能地计算出重新渲染组件的最小代价并应到DOM操作上。
  React中也是用了类似的方法。React元素是不可变对象。一旦被创建,你就无法更改它的子元素或者属性。一个元素就像电影的单帧:它代表了某个特定时刻的 UI。根据我们已有的知识,更新 UI 唯一的方式是创建一个全新的元素,并将其传入 ReactDOM.render()。
  React DOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态。

Virtual DOM 作用是什么

  虚拟DOM的最终目标是将虚拟节点渲染到视图上。但是如果直接使用虚拟节点覆盖旧节点的话,会有很多不必要的DOM操作。例如,一个ul标签下很多个li标签,其中只有一个li有变化,这种情况下如果使用新的ul去替代旧的ul,因为这些不必要的DOM操作而造成了性能上的浪费。
  为了避免不必要的DOM操作,虚拟DOM在虚拟节点映射到视图的过程中,将虚拟节点与上一次渲染视图所使用的旧虚拟节点(oldVnode)做对比,找出真正需要更新的节点来进行DOM操作,从而避免操作其他无需改动的DOM。
  
其实虚拟DOM在Vue.js主要做了两件事:
- 提供与真实DOM节点所对应的虚拟节点vnode
- 将虚拟节点vnode和旧虚拟节点oldVnode进行对比,然后更新视图

Diff算法

初步理解Virtual DOM和diff算法

最后修改日期:2020年5月1日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。