Skip to content

概述

https://cn.vuejs.org/

https://cn.vuejs.org/guide/introduction.html

https://github.com/vuejs/core

https://github.com/vuejs/vue-cli

更好的 Typescript 支持

为什么要有 vue3

vue2 遇到的难题

  • 随着功能的增长,复杂组件的代码变得难以维护
  • Vue2 对于 typescript 的支持非常有限

使用 vue cli 配置开发环境

https://cli.vuejs.org/

1
2
3
4
5
6
7
➜  Desktop node -v
v14.12.0

npm install -g @vue/cli

➜  Desktop vue --version
@vue/cli 4.5.9
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
➜  Desktop vue create vue3-basic

Vue CLI v4.5.9
? Please pick a preset: Manually select features

按空格选中 typescript

? Check the features needed for your project: Choose Vue version, Babel, TS, Linter
? Choose a version of Vue.js that you want to start the project with 3.x (Preview)
? Use class-style component syntax? No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? No
? Pick a linter / formatter config: Basic
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
? Save this as a preset for future projects? No
使用 npm 安装
1
2
$ cd vue3-basic
$ npm run serve

项目文件结构

入口文件: src/main.ts

插件推荐

ESLint
Vutur

简单计数器

修改src/App.vue:

 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
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <h1>{{ count }}</h1>
    <button @click="increase">👍+1</button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'App',
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increase() {
      this.count++
    }
  }
});
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

配置文件

https://cli.vuejs.org/zh/config/#%E5%85%A8%E5%B1%80-cli-%E9%85%8D%E7%BD%AE

认识 MVC 和 MVVM 模式

MVVM(Model-View-ViewModel,模型 - 视图 - 视图模型) 模式

传统的 MVC 模式包括以下三部分:

  • 视图(View): 用户界面
  • 控制器(Controller): 业务逻辑
  • 模型(Model): 数据存储

Model 代表数据存储,主要用于实现数据的持久化;
View 代表用户界面(UI),主要用于实现页面的显示;
Controller 代表业务逻辑,串联起 View 和 Model,主要用来实现业务的逻辑代码

在 MVC 模式中,用户的交互行为在 View 中触发,由 View 通知 Controller 去进行对应的逻辑处理,处理完成之后通知 Model 改变状态,
Model 完成状态改变后,找到对应的 View 去更新用户界面的显示内容,至此完成对用户交互行为的反馈。

由此可见,整个流程由 View 发起,最终在 View 中做出改变,这是一个单向的过程。
当年流行的 backbone.js 就是 MVC 的典型代表

流行的 MVVM 模式

MVVM 是把 MVC 中的 Controller 去除了,相当于变薄了,取而代之的是 ViewModal。
所谓 ViewModel,是一个同步的 View 和 Model 的对象,在前端 MVVM 中,ViewModel 最典型的作用是操作 DOM,特点是双向数据绑定(Data-Binding) .

在双向数据绑定中,开发者无须关注如何找到 DOM 节点和如何修改 DOM 节点,因为每一个在 View 中需要操作的 DOM 都会有一个在 Model 中对应的对象,
通过改变这个对象,DOM 就会自动改变;
反之,当 DOM 改变时,对应的 Model 中的对象也会改变。
ViewModel 将 View 和 Model 关联起来,因此开发者只需关注业务逻辑,不需要手动操作 DOM,这就是 ViewModel 带来的优势,
如下图所示

MVVM 让开发者更加专注于页面视图,从视图出发来编写业务逻辑,这也符合正常的开发流程,而 Vue.js 就是一个典型的从视图(View)出发的前端 MVVM 框架
从 Vue 的英文发音类似 View 就可以参透其中的奥秘

Vue 3 新特性概览

更易于维护

(1) 从 Flow 迁移到 TypeScript

(2) 源代码目录结构遵循 Monorepo

Monorepo 是一种管理代码的方式,它的核心观点是所有的项目在一个代码仓库中,但是代码分割到一个个小的模块中,而不是都放在 src 这个目录下。
这样的分割,使得每个开发者大部分时间只是工作在少数的几个文件夹内,并且也只会编译自己负责的模块,不会导致一个 IDE 打不开太大的项目之类的事情,这样很多事情就简单了很多。

我们可以看一下 Vue.js 在采用 Monorepo 前后的源码结构对比,如下图所示:

Vite

伴随着 Vue 3,Vue 团队也推出了自己的开发构建工具 Vite,可以在一定程度上取代 Vue Cli 和 webpack-dev-server 的功能。
基于此,Vite 主要有以下特性:

  • 快速的冷启动
  • 即时的模块热更新
  • 真正的按需编译

Vite 在开发环境下基于浏览器原生 ES 6 Modules 开发,在生产环境下基于 Rollup 打包

组合式 API

在 Vue 2.x 中,组件的主要逻辑是通过一些配置项来编写,包括一些内置的生命周期方法或者组件方法,例如下面的代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
export default {
  name: 'test',
  components: {},
  props: {},
  data () {
    return {}
  },
  created() {},
  mounted() {},
  watch: {},
  methods: {}
}

上面的代码中,这些基于配置的组件写法称为 Options API(配置式 API),
Vue3 的一大核心新特性是引入了 Composition API(组合式 API),这使得组件的大部分内容都可以通过 setup() 方法进行配置。
将上述代码改造成组合式 API,代码如下:

 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
import { onMounted, reactive, watch } from 'vue'
export default {
  props: {
    name: String,
  },
  name: 'test',
  components: {},
  setup (props, ctx) {
    console.log(props.name)
    console.log('created')
    const data = reactive({
      a: 1
    })
    watch(
      () => data.a,
      (val, oldVal) => {
        console.log(val)
      }
    )
    onMounted(() => {

    })
    const myMethod = (obj) => {

    }

    return {
      data,
      myMethod
    }
  }
}

上面的代码采用了 ES6 的语法,并且使用了 Vue3 的 Composition API 中的 setup 方法