Vue学习之路 https://vuejs.org/guide/introduction.html
1. 基础认知
1.1. 认识Vue
https://cn.vuejs.org/index.html
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
全称是Vue.js或者Vuejs;
什么是渐进式框架呢?
表示可以在项目中一点点来引入和使用Vue,而不一定需要全部使用Vue来开发整个项目;
1.2. 前端框架
目前前端最流行的三大框架:Vue,React,Angular
- Angular:入门门槛较高,并且国内市场占率较低,不否认本身非常优秀
- React:在国内外市场占有率非常高,必须学习的一个框架
- Vue:国内占有率最高
1.3. Vue3
- 在2020年的9月19日,万众期待的Vue3终于发布了正式版,命名为“One Piece”
- 它也带来了很多新的特性:更好的性能、更小的包体积、更好的TypeScript集成、更优秀的API设计
- 在vue3刚刚发布时,很多人也是跃跃欲试,想要尝试vue3的各种新特性
- 但是事实上在刚刚发布的时候使用vue3来写demo练习是没有问题的,真正在实际业务项目中使用vue3还需要一个相对的过程
- 包括vue3的进一步稳定、包括社区更多vue3相关的插件、组件库的支持和完善
- 那么需要学习vue3吗?
- 答案是肯定的
- 首先vue3在经过一系列的更新和维护后,已经是趋于稳定,并且在之前尤雨溪也宣布在2021年第二季度会将vue3作为Vue CLI的默认版本
- 目前社区也经过一定时间的沉淀,更加的完善了,包括AntDesignVue、Element-Plus都提供了对Vue3的支持,所以很多公司目前新的项目都已经在使用Vue3来进行开发了
- 并且在面试的时候,几乎都会问到各种各样Vue3、Vite2工具相关的问题
1.4. Vue3带来的变化(源码)
源码通过monorepo的形式来管理源代码:
- Mono:单个
- Repo:repository仓库
- 主要是将许多项目的代码存储在同一个repository中;
- 这样做的目的是多个包本身相互独立,可以有自己的功能逻辑、单元测试等,同时又在同一个仓库下方便管理;
- 而且模块划分的更加清晰,可维护性、可扩展性更强;
源码使用TypeScript来进行重写:
- 在Vue2.x的时候,Vue使用Flow来进行类型检测;
- 在Vue3.x的时候,Vue的源码全部使用TypeScript来进行重构,并且Vue本身对TypeScript支持也更好了;
1.5. Vue3带来的变化(性能)
- 使用Proxy进行数据劫持
- 在Vue2.x的时候,Vue2是使用Object.defineProperty来劫持数据的getter和setter方法的;
- 这种方式一致存在一个缺陷就是当给对象添加或者删除属性时,是无法劫持和监听的;
- 所以在Vue2.x的时候,不得不提供一些特殊的API,比如
$set
或$delete
,事实上都是一些hack方法,也增加了 开发者学习新的API的成本; - 而在Vue3.x开始,Vue使用Proxy来实现数据的劫持;
- 删除了一些不必要的API
- 移除了实例上的
$on
,$off
和$once
; - 移除了一些特性:如filter、内联模板等;
- 移除了实例上的
- 包括编译方面的优化
- 生成Block Tree、Slot编译优化、diff算法优化;
1.6. Vue3带来的变化(新的API)
由Options API 到 Composition API:
- 在Vue2.x的时候,会通过Options API来描述组件对象;
- Options API包括data、props、methods、computed、生命周期等等这些选项;
- 存在比较大的问题是多个逻辑可能是在不同的地方:
- 比如created中会使用某一个method来修改data的数据,代码的内聚性非常差;
- Composition API可以将 相关联的代码 放到同一处 进行处理,而不需要在多个Options之间寻找;
Hooks函数增加代码的复用性:
- 在Vue2.x的时候,通常通过mixins在多个组件之间共享逻辑;
- 但是有一个很大的缺陷就是 mixins也是由一大堆的Options组成的,并且多个mixins会存在命名冲突的问题;
- 在Vue3.x中,我们可以通过Hook函数,来将一部分独立的逻辑抽取出去,并且它们还可以做到是响应式的;
2. 使用Vue
Vue的本质,就是一个JavaScript的库:
- 就把它理解成一个已经封装好的库;
- 在项目中可以引入并且使用它即可
那么安装和使用Vue这个JavaScript库有哪些方式呢?
- 方式一:在页面中通过CDN的方式来引入;
- 方式二:下载Vue的JavaScript文件,并且自己手动引入;
- 方式三:通过npm包管理工具安装使用它(webpack再讲);
- 方式四:直接通过Vue CLI创建项目,并且使用它;
2.1. 方式一:CDN引入
什么是CDN呢?
CDN称之为内容分发网络(Content Delivery Network或Content Distribution Network,缩写:CDN)
它是指通过
相互连接的网络系统
,利用最靠近
每个用户的服务器;最近的边缘节点(服务器)中查找资源,如果没有,查找父节点,如果没有,查找源站。
源站将资源传输给父节点,父节点传输给最近边缘节点
更快、更可靠地将
音乐、图片、视频、应用程序及其他文件
发送给用户;来提供
高性能、可扩展性及低成本的
网络内容传递给用户;
常用的CDN服务器可以大致分为两种:
- 自己的CDN服务器:需要购买自己的CDN服务器,目前阿里、腾讯、亚马逊、Google等都可以购买CDN服务器;
- 开源的CDN服务器:国际上使用比较多的是unpkg、 JSDelivr、cdnjs;
Vue的CDN引入:
1
<script src="https://unpkg.com/vue@next"></script>
Hello Vue案例的实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<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="https://unpkg.com/vue@next"></script>
<script>
const why = {
template: '<h1>Hello Vue</h1>'
}
const app = Vue.createApp(why);
app.mount("#app");
</script>
</body>
</html>
2.2. 方式二:下载和引入
下载Vue的源码,可以直接打开CDN的链接:
- 打开链接,复制其中所有的代码;
- 创建一个新的文件,比如vue.js,将代码复制到其中;
通过script标签,引入刚才的文件
案例实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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="./vue.js"></script>
<script>
Vue.createApp({
template: '<h1>Hello Vue.js</h1>'
}).mount('#app');
</script>
</body>
</html>
2.3. 计数器案例
实现一个计数器的案例:
- 点击+1,那么内容会显示数字+1;
- 点击-1,那么内容会显示数字-1;
选择很多种方式来实现:
- 对比原生和Vue的实现方式的不同
2.3.1. 原生js
1 |
|
2.3.2. Vue.js
1 |
|
2.3.3. 声明式和命令式
原生开发和Vue开发的模式和特点,是完全不同的,这里其实涉及到两种不同的编程范式:
- 命令式编程和声明式编程;
- 命令式编程关注的是 “how to do”,声明式编程关注的是 “what to do”,由框架(机器)完成 “how”的过程;
在原生的实现过程中,如何操作的呢?
- 每完成一个操作,都需要通过JavaScript编写一条代码,来给浏览器一个指令;
- 这样的编写代码的过程,称之为命令式编程;
- 在早期的原生JavaScript和jQuery开发的过程中,我们都是通过这种命令式的方式在编写代码的;
在Vue的实现过程中,如何操作的呢?
- 在createApp传入的对象中声明需要的内容,模板template、数据data、方法methods;
- 这样的编写代码的过程,称之为是声明式编程;
- 目前Vue、React、Angular的编程模式,都称之为声明式编程;
2.4. MVVM模型
MVC和MVVM都是一种软件的体系结构
MVC是Model – View –Controller的简称,是在前期被使用非常框架的架构模式,比如iOS、前端;
MVVM是Model-View-ViewModel的简称,是目前非常流行的架构模式;
通常情况下,也经常称Vue是一个MVVM的框架
- Vue官方其实有说明,Vue虽然并没有完全遵守MVVM的模型,但是整个设计是受到它的启发的
3. templeate属性
在使用createApp的时候,传入了一个对象
template属性:表示的是Vue需要帮忙渲染的模板信息:
- 目前看到它里面有很多的HTML标签,这些标签会替换掉挂载到的元素(比如id为app的div)innerHTML;
- 模板中有一些奇怪的语法,比如 @click,这些都是模板特有的语法;
但是这个模板的写法有点过于别扭了,并且IDE很有可能没有任何提示,阻碍编程的效率
Vue提供了两种方式:
1. 方式一:使用script标签,并且标记它的类型为 x-template;
2. 方式二:使用任意标签(通常使用template标签,因为不会被浏览器渲染),设置id;- https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/template
- template元素是一种用于保存客户端内容的机制,该内容再加载页面时不会被呈现,但随后可以在运行时使用JavaScript实例化;
3.1. template写法
在createApp的对象中,传入的template以 # 开头:
如果字符串是以 # 开始,那么它将被用作 querySelector,并且使用匹配元素的 innerHTML 作为模板字符串;
3.1.1. 使用script标签
1 |
|
3.1.2. 使用template标签
1 |
|
4. data属性
data属性是传入一个函数,并且该函数需要返回一个对象:
在Vue2.x的时候,也可以传入一个对象(虽然官方推荐是一个函数);
在Vue3.x的时候,必须传入一个函数,否则就会直接在浏览器中报错;
data中返回的对象会被Vue的响应式系统劫持,之后对该对象的修改或者访问都会在劫持中被处理:
- 所以在template中通过 访问counter,可以从对象中获取到数据;
- 所以修改counter的值时,template中的 也会发生改变;
5. methods属性
- methods属性是一个对象,通常会在这个对象中定义很多的方法:
- 这些方法可以被绑定到 template 模板中;
- 在该方法中,可以使用this关键字来直接访问到data中返回的对象的属性;
5.1. 为什么不能使用箭头函数?
- 官方文档有这么一段描述:
- 注意,不应该使用箭头函数来定义 method 函数 (例如
plus: () => this.a++
)。理由是箭头函数绑定了父级作用域的上下文,所以this
将不会按照期望指向 Vue 实例,this.a
将是 undefined
- 注意,不应该使用箭头函数来定义 method 函数 (例如
- 在methods中要使用data返回对象中的数据:
- 那么这个this是必须有值的,并且应该可以通过this获取到data返回对象中的数据。
- 这个this能不能是window呢?
- 不可以是window,因为window中无法获取到data返回对象中的数据;
- 但是如果使用箭头函数,那么这个this就会是window了;
- 为什么是window呢?
- 箭头函数中不绑定this,这个this就是window;
- 这里涉及到箭头函数使用this的查找规则,它会在自己的上层作用于中来查找this;
- 最终刚好找到的是script作用于中的this,所以就是window;
- this到底是如何查找和绑定的呢?
- 详细的讲解了this的绑定规则 https://mp.weixin.qq.com/s/hYm0JgBI25grNG_2sCRlTA;
5.2. this到底指向的是什么?
事实上Vue的源码当中就是对methods中的所有函数进行了遍历,并且通过bind绑定了this:
/packages/runtime-core/src/componentOptions.ts
1 | instance: ComponentInternalInstance |
6. 其他属性
- 比如props、computed、watch、emits、setup等等;
- 也包括很多的生命周期函数;
7. 查看Vue的源码
如果想要学习Vue的源码,比如看createApp的实现过程,应该怎么办呢?
第一步:在GitHub上搜索 vue-next,下载源代码;
- 这里推荐通过 git clone 的方式下载;
git clone https://github.com/vuejs/core
第二步:安装Vue源码项目相关的依赖;
执行
npm install pnpm -g
执行
pnpm install
第三步:对项目执行打包操作
- 执行
pnpm dev
(执行前修改脚本)
- 执行
第四步:通过 packages/vue/dist/vue.global.js 调试代码
在
./package.json
中修改代码1
2
3"scripts": {
"dev": "node scripts/dev.js --sourcemap"
}在
packages/vue/dist/
中新建index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<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>
<template id = "vue">
<h1>hello template</h1>
</template>
<script src="./vue.global.js"></script>
<script>
debugger;
Vue.createApp({
template: '#vue'
}).mount("#app");
</script>
</body>
</html>在chrome中打开 index.html,调试代码,得到源码所在位置
/packages/runtime-dom/src/index.ts
8. VSCode代码片段
在VSCode中生成一个代码片段,方便快速生成
具体的步骤如下:
第一步,复制自己需要生成代码片段的代码;
第二步,https://snippet-generator.app/ 在该网站中生成代码片段;
第三步,在VSCode中配置代码片段;
【code】—> 【首选项】—> 【配置用户代码片段】—> 【html.json】添加
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40{
"create vue app": {
"prefix": "vueapp",
"body": [
"<!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>",
" <template id = \"vue\">",
" ",
" </template>",
" <script src=\"https://unpkg.com/vue@next\"></script>",
" <script>",
" Vue.createApp({",
" template: '#vue',",
" data: function(){",
" return {",
" ",
" }",
" },",
" watch: {",
" ",
" },",
" methods: {",
"",
" }",
" }).mount(\"#app\");",
" </script>",
"</body>",
"</html>"
],
"description": "create vue app"
}
}