Vue3+TypeScript(coderwhy)学习笔记(一)邂逅Vue3

1,140 阅读5分钟

前言

Snipaste_2022-07-09_15-42-09.png

  • 本笔记基于coderwhy大神新课程-vue3+ts所作,原版课程地址指路—深入Vue3+TypeScript技术栈,请大家尽量支持正版哈
  • 本笔记集视频、课件、代码而成,较为详细,建议收藏关注,持续更新中

Vue3带来的变化

1.源码

源码通过monorepo的形式来管理源代码:

  • pMono:单个
  • pRepo:repository仓库
  • 主要是将许多项目的代码存储在同一个repository中;
  • 这样做的目的是多个包本身相互独立,可以有自己的功能逻辑、单元测试等,同时又在同一个仓库下方便管理;
  • 而且模块划分的更加清晰,可维护性、可扩展性更强;

源码使用TypeScript来进行重写:

  • 在Vue2.x的时候,Vue使用Flow来进行类型检测;
  • 在Vue3.x的时候,Vue的源码全部使用TypeScript来进行重构,并且Vue本身对TypeScript支持也更好了;

2.性能

使用Proxy进行数据劫持

  • 在Vue2.x的时候,Vue2是使用Object.defineProperty来劫持数据的gettersetter方法的;这种方式一致存在一个缺陷就是当给对象添加或者删除属性时,是无法劫持和监听的,所以在Vue2.x的时候,不得不提供一些特殊的API,比如$set$delete,事实上都是一些hack方法,也增加了开发者学习新的API的成本,而在Vue3.x开始,Vue使用Proxy来实现数据的劫持

删除了一些不必要的API:

  • 移除了实例上的$on, $off$once

移除了一些特性:

  • 如filter、内联模板等;

编译方面的优化:

  • 生成Block Tree、Slot编译优化、diff算法优化

3.新API

Options API 到 Composition API:

  • 在Vue2.x的时候,我们会通过Options API来描述组件对象;Options API包括datapropsmethodscomputed生命周期等等这些选项;存在比较大的问题是多个逻辑可能是在不同的地方: 比如created中会使用某一个method来修改data的数据,代码的内聚性非常差;
  • Composition API可以将相关联的代码放到同一处进行处理,而不需要在多个Options之间寻找;

Hooks函数增加代码的复用性:

  • 在Vue2.x的时候,我们通常通过mixins在多个组件之间共享逻辑;但是有一个很大的缺陷就是mixins也是由一大堆的Options组成的,并且多个mixins会存在命名冲突的问题;在Vue3.x中,我们可以通过Hook函数,来将一部分独立的逻辑抽取出去,并且它们还可以做到是响应式的;

Hello Vue的实现

 <body>
  <div id="app"></div>
  <script src="https://unpkg.com/vue@next"></script>
  <script>
    // Vue相关的代码
    const app = Vue.createApp({
      template: '<h2>Hello Vue3</h2>'
    });
    // 将app挂载到id为app的div上
    app.mount("#app");
  </script>
</body>

createApp对象参数

在使用createApp的时候,我们传入了一个对象,我们解析一下传入的属性分别代表什么含义

template属性

template表示的是Vue需要帮助我们渲染的模板信息:
目前我们看到它里面有很多的HTML标签,这些标签会替换掉我们挂载到的元素(比如id为app的div)的innerHTML;模板中有一些奇怪的语法,比如{{}},比如 @click,这些都是模板特有的语法,会在后面讲到;但是这个模板的写法有点过于别扭了,并且编辑器可能没有任何提示,阻碍我们变成的效率。

方式一:使用script标签,并且标记它的类型为 x-template

<script type="x-template" id="my-app">
    <div>
      <h2>{{counter}}</h2>
      <button @click='increment'>+1</button>
      <button @click='decrement'>-1</button>
    </div>
</script>

方式二:使用任意标签(通常使用template标签,因为不会被浏览器渲染),设置id,template元素是一种用于保存客户端内容的机制,该内容在加载页面时不会被呈现,但随后可以在运行时使用JavaScript实例化;

<template id="my-app">
    <div>
      <h2>{{counter}}</h2>
      <button @click='increment'>+1</button>
      <button @click='decrement'>-1</button>
    </div>
</template>

这个时候,在createApp的对象中,我们需要传入的template以#开头:如果字符串是以#开始,那么它将被用作querySelector,并且使用匹配元素的innerHTML作为模板字符串;

data属性

data属性是传入一个函数,并且该函数需要返回一个对象:
在Vue2.x的时候,也可以传入一个对象(虽然官方推荐是一个函数);
在Vue3.x的时候,必须传入一个函数,否则就会直接在浏览器中报错;
data中返回的对象会被Vue的响应式系统劫持,之后对该对象的修改或者访问都会在劫持中被处理: 所以我们在template中通过{{counter}}访问counter,可以从对象中获取到数据;我们修改counter的值时,template中的 {{counter}}也会发生改变;
具体这种响应式的原理,后面会有专门的篇幅来讲解。

methods属性

methods属性是一个对象,通常我们会在这个对象中定义很多的方法:
这些方法可以被绑定到 template 模板中;
在该方法中,我们可以使用this关键字来直接访问到data中返回的对象的属性;

其他属性

当然,这里还可以定义很多其他的属性,会在后续进行讲解:props、computed、watch、emits、setup等等,也包括很多的生命周期函数;

如何学习Vue3源码

如果想要学习Vue的源码,比如看createApp的实现过程,应该怎么办呢?
第一步:在GitHub上搜索 vue-next,下载源代码,推荐通过 git clone 的方式下载;
第二步:安装Vue源码项目相关的依赖,执行 yarn install;
第三步:对项目执行打包操作,执行yarn dev(执行前修改脚本) f821c88eef3b4e8985eb809d202dfd9a.png
第四步:通过 packages/vue/dist/vue.global.js 调试代码,packages/vue/examples下新建why文件夹,里面新建demo.html文件,内容如下,打上了debugger

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app"></div>
  <script src="../../dist/vue.global.js"></script>
  <script>
    debugger;
    Vue.createApp({
      template: `<h2>你好啊</h2>`
    }).mount("#app");
  </script>
</body>
</html>

刷新浏览器发现,现在是在vue.global.js里面调试的,是一整个代码,有没有办法跳到某个具体的源代码里面? 1.png 使用--sourcemap(代码映射,可以把某个函数映射到具体哪个打包文件里面)

2.png 重新运行打包

3.png