关于 Vue3 这些知识,你可能还不知道!

开发 前端
Vue 是目前前沿开发中最热门的框架之一,到2019年每周的下载率翻了一番。2020 年初 Vue3的发布还会增加它的受欢迎程度。

[[348895]]

本文已经作者 Matt Maribojoc 授权翻译!

Vue 是目前前沿开发中最热门的框架之一,到2019年每周的下载率翻了一番。2020 年初 Vue3的发布还会增加它的受欢迎程度。

Vue3 为开发人员提供了更多的控制,它使我们能够精确地控制项目中发生的事情,从编写定制的编译和渲染方法到直 Vue reactivity API。

Vue3 使用 Proxy 来监听数据的变化

响应性是 VueJS 的核心,数据必须具有依赖性,可以观察并进行更新以响应任何更改,Vue2 使用 Object.defineProperty 创建 getter 和 setter 来实现响应式。

使用Object.defineProperty有两个主要问题,在官方文档中都提到过:Vue 不能检测数组和对象的变化。

对于对象

Vue 无法检测 property 的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。

对于数组

Vue 不能检测以下数组的变动:

  1. 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength

举个例子:

var vm = new Vue({ 
  data: { 
    items: ['a''b''c'
  } 
}) 
vm.items[1] = 'x' // 不是响应性的 
vm.items.length = 2 // 不是响应性的 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

为什么使用 Proxy ?

Vue3 的解决方案是使用基于Proxy的观察者模式来解决 Vue2 响应上的一些限制。

新旧系统之间的主要区别在于,在Vue2中,Object.defineProperty会修改原始数据,而Proxy则不会,Proxy 虚拟化目标数据并设置不同的处理程序(称为target),这些处理程序通过getters和setter拦截数据。

Vue3 意味着我们无需使用vm.$set来让数据动态的响应,同时也解决 vue2 操作数组无法响应的问题。

正如尤雨溪大哥所总结的那样,基于代理可以支持:

  • 检测属性 添加/删除
  • 检测数组 index/length 的变化
  • 支持Map,Set, WeakMap 和WeakSet

Composition API

这是到目前为止 Vue3 最大的一个变化,它有助于代码的组织和重用性。

目前,在Vue中我们使用是Options API。Options API按属性组织代码:data,computed,methods等。

这是一个非常直观的方式,但维护一些复杂组件变得非常困难。单个功能的代码通常在相隔数百行的多个地方抛出。

可维护性和可读性成为主要问题。

接着,我们快速了解一下Composition API的工作原理。

import { reactive, computed } from 'vue' 
 
export default { 
  setup() { 
    let state = reactive({ 
      input: ''
      groceries: [], 
      groceriesLeft: computed(() => { groceries.length }) 
    }) 
 
    function addGrocery() { 
      state.groceries.push(state.input) 
   state.input = '' 
    } 
 
    function deleteGrocery(index) { 
   state.groceries.splice(index, 1); 
  } 
  return {  
   state,  
   addGrocery,  
   deleteGrocery  
  } 
  } 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

我们来分析一下,上面的过程 ??

import { reactive, computed } from 'vue' 
  • 1.

Vue Composition API公开了Vue中的许多核心功能,比如reactive和组件方法,所以,我们需要导入它们。

export default { 
   setup() { 
  • 1.
  • 2.

setup()方法的引入是 Vue3 中最大的变化之一。从本质上讲,它使我们能够确定传递回模板的内容,无论返回什么,都可以在模板中访问。

我们可以在 setup 里面设置reactive 数据,生命周期,计算属性,定义的方法并返回我们想要的任何东西。

let state = reactive({ 
  input: ''
  groceries: [], 
  groceriesLeft: computed(() => { groceries.length }) 
}) 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

通过以反应式方法包装所有这些数据,所有数据在内部都将变为反应式。此状态模式来自Composition API文档。

reactive() 函数接收一个对象作为参数,并返回一个代理对象,所有数据在内部都将变为响应式的。

需要注意的一点是我们声明groceriesLeft变量的方式。它是一个计算的属性,并在setup()方法中定义,不再单独拎出来声明。

function addGrocery() { 
  state.groceries.push(state.input) 
  state.input = '' 

 
function deleteGrocery(index) { 
  state.groceries.splice(index, 1) 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

函数声明倒是没啥变化,区别一点是由于所有响应数据都存储在state 对象中,因此我们必须使用状态对象进行访问,但这不是Vue3特有的。

return {  
  state,  
  addGrocery,  
  deleteGrocery  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

最后,我们想从setup()方法返回这些函数,这样声明的数据和方法就可在模板内部访问。

初次引入此方法时,Vue 社区中存在许多反对,因为开发者不希望被迫编写这种新的方式。但是,这个也可选的,就是说我们仍然可以使用 vue2 方式来做。

现在可以在Vue中使用 Suspense

Suspense是React的一个功能,现已在Vue3中引入。Suspense 让组件“等待”某个异步操作,直到该异步操作结束即可渲染。

当我们想要异步加载setup()方法中的内容时,这很有用。简而言之,只需知道 setup 方法可以像其他方法一样被设置为异步的。

如果我们要在等待组件获取数据并解析时显示“正在拼了命的加载…”之类的内容,则只需三个步骤即可实现Suspense。

  • 将异步组件包装在标记中
  • 在我们的 Async 组件的旁边添加一个兄弟姐妹,标签为。
  • 将两个组件都包装在组件中

使用插槽,Suspense 将渲染后备内容,直到默认内容准备就绪。然后,它将自动切换以显示我们的异步组件。

<Suspense>  
  <template #default>  
    <article-info/>  
  </template>  
  <template #fallback>  
    <div>正在拼了命的加载…</div>  
  </template>  
</Suspense>  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

Fragment

在Vue 3中,我们可以期待的另一个令人兴奋的补充是Fragment。你可能会问,什么是碎片?如果你创建一个Vue组件,那么它只能有一个根节点。这意味着不能创建这样的组件

<template> 
  <div>Hello</div> 
  <div>World</div> 
</template> 
  • 1.
  • 2.
  • 3.
  • 4.

原因是代表任何Vue组件的Vue实例需要绑定到一个单一的DOM元素中。唯一可以创建一个具有多个DOM节点的组件的方法就是创建一个没有底层Vue实例的功能组件。

结果发现React社区也遇到了同样的问题。他们想出的解决方案是一个名为 Fragment 的虚拟元素。它看起来差不多是这样的:

class Columns extends React.Component { 
  render() { 
    return ( 
      <React.Fragment> 
        <td>Hello</td> 
        <td>World</td> 
      </React.Fragment> 
    ); 
  } 

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

尽管Fragment看起来像一个普通的DOM元素,但它是虚拟的,根本不会在DOM树中呈现。这样我们可以将组件功能绑定到一个单一的元素中,而不需要创建一个多余的DOM节点。

目前你可以在Vue 2中使用vue-fragments库来使用Fragments,而在Vue 3中,你将会在开箱即用!

Portals

Portals是一种特殊的组件,目的是在当前组件之外渲染某些内容。这也是React中原生实现的功能之一。下面是 React 文档中关于portals的说法。

Portals 提供了一种第一流的方式,可以将子节点渲染到父组件的DOM层次结构之外的DOM节点中。

这是一种非常好的处理modals、弹出窗口和一般要出现在页面顶部的组件的方式。通过使用portals,你可以确保没有任何一个主组件的CSS规则会影响到你想要显示的组件,并且免除了你用z-index做讨厌的黑客的麻烦。

下面是Portal-Vue文档中的示例屏幕截图和代码。

对于每一个Portals,我们需要指定它的目标目的地,在那里,Portals内容将被渲染。

<template> 
  <div> 
    <div> 
      <p> 
        The content below this paragraph is 
        rendered in the right/bottom (red) container by PortalVue 
      </p> 
      <Portal to="right-basic"
        <p class="red"
          This is content from the left/top container (green). 
          The cool part is, it works across components, 
          so you can send your content anywhere! 
        </p> 
      </Portal> 
    </div> 
    <PortalTarget name="right-basic"></PortalTarget> 
  </div> 
</template> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

Vue3 优化了渲染

内部测试表明,Vue3中的模板样式比Vue2快约120%。

有两个关键的优化提高Vue3渲染速度:

  1. Block Tree 优化
  2. 提升静态节点树

我们进一步详细介绍一下。

Block Tree 优化

使用虚拟DOM有一个瓶颈,因为每个组件都必须跟踪其依赖关系。监听这些依赖关系速度会变慢很多,因为它递归地检查整个元素树。

Vue团队注意到的一件事是,在组件中,节点的大部分结构都是静态的。而且,如果某个节实际上是动态的(由于v-if或v-for指令),则其中的许多内容都是静态的。

使用此想法,Vue3将模板分为静态部分与动态部分。现在,渲染器知道哪些节点是动态的,它不会浪费时间检查静态节点的变化。

这大大减少了需要被动监视的元素数量。

结合所有这些节点可创建一个Block Tree或一个基于指令(v-if,v-for)分为节点块的模板。

在 Block Tree 中,每个节点具有:

  • 完全静态的节点结构
  • 不需要监听的静态内容
  • 可以存储在数组中的动态节点

这消除了对每个元素进行递归检查的需要,从而大大改善了运行时间。

静态树提升(Static Tree Hoisting)

使用静态树提升,这意味着 Vue 3 的编译器将能够检测到什么是静态的,然后将其提升,从而降低了渲染成本。它将能够跳过 patching 整棵树。

这大大减少了虚拟DOM的工作,并节省了大型项目开销,主要是垃圾收集。

支持 Typescript

另一个变化是Vue代码库将使用Typescript重写,这个对于前端来说,又得去学习 TS 才能更好的上手 Vue3。

所以 Vue 也提供了两种选择给我:如果你想要Typescript,那就用。如果不想,那就用 Vue2 的方式。

Typescript 规范了 JS 变量中类型信息。多长远来看,这有助于我们对项目的维护。

超轻量级

目前,VueJS已经很小(20kb gzip压缩)。但是,Vue 团队面临一个问题:新特性增加了每个用户的捆绑包大小,不管他们是否使用它。

为了解决这个问题,Vue3 更加彻底的模块化。这样做增加需要开发的导入模块数量,但可确保我们项目中引入未使用的库。

由于 tree shaking ,Vue 3 的估计大小大约压缩了10 kb。当然,许多库都需要被导入。

准备好了吗

如果你是 Vue 的使用者,那么很明显,Vue3 中的更新将使它变得更加实用且功能强大。

从渲染优化到帮助开发人员编写更具可读性/可维护性的代码,Vue3改善Vue2遇到的许多痛点。

Vue3 已经正式发布了,你准备好了吗,快来上手学习吧!

作者:Matt Maribojoc 译者:前端小智 来源:medium

原文:https://medium.com/swlh/what-you-need-to-know-about-vue3-in-2020-b36a2feb5dad

本文转载自微信公众号「大迁世界」,可以通过以下二维码关注。转载本文请联系大迁世界公众号。

 

 

责任编辑:武晓燕 来源: 大迁世界
相关推荐

2015-07-13 08:49:54

2022-05-05 12:02:45

SCSS函数开发

2020-03-05 11:10:18

Left join数据库MySQL

2018-09-02 15:43:56

Python代码编程语言

2020-12-14 07:51:16

JS 技巧虚值

2019-11-20 10:25:06

sudoLinux

2017-10-16 13:30:28

windows 10技巧输入法

2020-06-03 08:53:40

CSS伪类 JS

2021-10-22 09:41:26

桥接模式设计

2022-02-23 14:18:02

macOSMac时间机器

2018-05-10 11:50:13

Docker容器冷知识

2021-06-01 07:40:59

Vue3更新技巧

2021-03-18 14:02:56

iOS苹果细节

2016-07-22 17:55:07

云计算

2023-11-06 11:32:46

CSS选择器作用域

2022-12-07 08:16:50

Vue 3技巧数组

2021-10-19 14:49:49

CSS前端

2015-05-14 15:59:33

DockerLinux容器管理工具

2025-02-27 08:33:13

2012-11-23 10:57:44

Shell
点赞
收藏

51CTO技术栈公众号