likes
comments
collection
share

💡简单认识一下Vue | 框架设计的基本概念

作者站长头像
站长
· 阅读数 15

前言

我们需要同步并明确一些词汇的概念,比如:声明式、命令式、运行时、编译时.。这些词汇在框架设计中被经常涉及到。

为什么需要框架?🧰

首先我们知道在目前的前端开发中,有两种编程范式,命令式编程声明式编程,简单来讲,命令式编程是指我们在学习JS原生开发时所使用的编程方式,而声明式编程则是我们在使用Vue时进行的编程方式。Vue作为一个流行框架,它所使用的编程方式必然是在某些方面优于原生开发的,并且它的优点能够让企业去坚定的选择它,下面我们来看看究竟是怎么个事儿。

命令式

命令式是:关注过程 的一种编程范式,他描述了完成一个功能的 详细逻辑与步骤例子:为指定的div的子元素div的子元素p标签,展示变量msg💡简单认识一下Vue | 框架设计的基本概念

声明式

声明式是:**关注结果 **的一种编程范式,他 并不关心完成一个功能的 详细逻辑与步骤。(注意:这并不意味着声明式不需要过程!声明式只是把过程进行了隐藏而已!)例子:(与上述相同例子)💡简单认识一下Vue | 框架设计的基本概念“当我们看到 声明式 时,心情是非常舒爽的!原来这就是**框架带来的好处!”

命令式 VS 声明式

从视觉上还不够,我们要理论分析,通常情况下,我们评价一个编程范式通常会从两个方面入手:

  1. 性能
  2. 可维护性

性能⚡

div.innerText="hello world"//耗时为:1
<div>{{msg}</div> <!--耗时为:1+n-->

那么:已知修改text最简单的方式是innerText,浏览器是无法直接解析{{}}这种插值语法的,所以说无论声明式的代码是如何实现的文本切换,那么它的耗时一定是 >1 的,我们把它比作 1+n (对比的性能消耗)

所以,由以上举例可知:命令式的性能>声明式的性能 !!

可维护性🔧

可维护性代表的维度非常多,但是通常情况下,所谓的可维护性指的是:对代码可以方便的阅读、修改、删除、增加。在之前的例子中,我们可以清楚的认识到 声明式 的代码更利于阅读,所以更加利于维护。

所以,由以上举例可知:命令式的可维护性<声明式的可维护性 !!

企业应用为何使用框架开发?

无论什么类型的企业,也无论它们在开发什么类型的项目,那么最关注的点无非就是两个:

  1. 项目成本 (开发周期)
  2. 开发体验

项目成本💰

开发周期越长,所付出的人员成本就会越高,从而导致项目成本变得越高。

通过我们前面的分析可知,声明式的开发范式在可维护性上是大于命令式的。而可维护性从一定程度上就决定了,它会使项目的:**开发周期变短、升级变得更容易 **从而大量节约开发成本。

开发体验🌈

决定开发者开发体验的核心要素,主要是在开发时和阅读时的难度,这个被叫做:心智负担。根据我们之前所说,声明式开发难度明显低于命令式,对于开发体验而言,声明式的心智负担更低,也就是开发体验更好

框架是怎样设计的?🚀

我们之前提到过 命令式的性能>声明式的性能 ,难道就对性能不管不顾了吗!?太不负责了!!Vue 作者 尤雨溪 在一次演讲中说道:“框架的设计过程其实是一个不断取舍的过程”

我们知道对于 Vue 而言,当我们使用它的是通过声明式的方式进行使用,但是对于Vue内部而言,是通过命令式来进行的实现。对于开发者而言,不需要关注实现过程,只需要关注最终的结果即可

所以我们可以理解为:Vue 封装了命令式的逻辑,而对外暴露出了声明式的接口。

Vue 所需要做的就是:封装命令式逻辑,同时尽可能的减少性能的损耗!它需要在性能可维护性之间,找到一个平衡。从而找到一个可维护性更好,性能相对更优的一个点。

什么是运行时?

场景:渲染出下面这个dom元素💡简单认识一下Vue | 框架设计的基本概念使用Vue的Api尝试一下,可以看到关键在于render

// render.html
<head>
	<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.js"></script>
</head>
<body>
  <div id="app"></div>
</body>
<script>
  const { render, h } = Vue
  const vnode = h(
    'div',
    {
    	class: 'test'
    },
    'hello render'
  )
  const container = document.querySelector('#app')
  render(vnode, container)
</script>

浏览器中渲染:💡简单认识一下Vue | 框架设计的基本概念那么render是怎么实现的呢?我们自己简单模拟一下

const vnode = {
  type: 'div',
  props: {
    class: 'test'
  },
  children: 'hello render'
}
function render(vnode) {
  const ele = document.createElement(vnode.type)
  ele.className = vnode.props.class
  ele.innerText = vnode.children
  document.body.appendChild(ele)
}
render(vnode)

浏览器中同样渲染出:💡简单认识一下Vue | 框架设计的基本概念

没错,我们刚刚就编写了一个小小的 “框架”,就是 运行时 的代码框架。

“每次这么写个这么复杂的vnode,太麻烦了,能不能直接写 HTML标签结构的方式 来进行渲染”“可以的,但是那就不是 运行时 的代码可以解决的了!”

总结:运行时可以利用 rendervnode 渲染成真实的 dom节点

什么是编译时?

上面我们提到了,能不能直接写 HTML标签结构的方式 来进行渲染,要想实现这一点,我们需要来学习一下 编译时(编译器) 。其实 Vue 是 编译时+运行时 的一个框架,我们来看看一段代码:

<head>
  <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.js"></script>
</head>
<body>
  <div id="app"></div>
</body>
<script>
  const { compile, createApp } = Vue
  const html = `
  <div class="test">hello compiler</div>
`
  const renderFn = compile(html) //compile即编译时(编译器)
  
  const app = createApp({
    render: renderFn
  })
  app.mount('#app')
</script>

对于编译器而言,它的主要作用就是:把template中的html编译成render函数。然后再利用运行时通过render挂载对应的DOM。

那么最后,我们做一个总结:编译时可以把 html的节点,编译成render函数

为什么要编译时+运行时?

我们要明确一点:dom 操作比 js 操作更耗时,即更耗性能 !

  1. 针对于 纯运行时而言:因为不存在编译器,所以我们只能够提供一个复杂的JS对象(vnode)。
  2. 针对于 纯编译时而言:因为缺少运行时,所以它只能把分析差异的操作,放到 编译时进行,难以处理动态数据,同样因为省略了运行时,所以速度可能会更快。但是这种方式这将损失灵活性。
  3. 运行时+编译时:比如 vue或 react都是通过这种方式来进行构建的,使其可以在保持灵活性的基础上,尽量的进行性能的优化,从而达到一种平衡。