什么是Vue3

MVVM是Model-View-ViewModel的缩写,它是一种前端架构模式。Vue就是一种使用MVVM架构的前端框架。

在MVVM架构中,Model表示数据模型,View表示用户界面,ViewModel是Model和View之间的中介者。ViewModel通过双向数据绑定将Model和View连接起来,当Model发生变化时,ViewModel会自动更新View,反之亦然。

与其他前端JavaScript框架相比,Vue的最大优势就是其轻量级和简单易用。Vue的核心库只关注视图层,不涉及其他方面,因此体积较小、易于上手,同时也具有很好的性能表现。

Vue 3相比于Vue 2,有一些全新的理念和改进,包括:

  1. 更快的渲染速度和更小的包大小:Vue 3引入了新的响应式系统和静态渲染器,可以在运行时实现更高效的代码生成,从而提高了渲染速度,并减小了包大小。
  2. Composition API:Vue 3引入了Composition API,它使得在组件中使用逻辑复用和代码组合变得更加容易。使用Composition API可以更好地组织和管理组件内部的代码逻辑。
  3. Teleport和Suspense组件:Vue 3引入了Teleport和Suspense组件,它们可以帮助开发者更方便地处理异步渲染和组件的跨层级挂载等问题。
  4. 更好的TypeScript支持:Vue 3对TypeScript的支持得到了大幅度的提升,包括更好的类型推导和更丰富的类型定义。

总之,Vue是一个功能强大、易于学习和使用的前端框架,而Vue 3则在性能和开发体验等方面进行了进一步的提升。

明确Vue2和Vue3的区别

  • vue3使用createApp函数来创建应用实例,而vue2使用new Vue语法。createApp函数可以让多个应用实例在同一个页面上共存,每个实例都有自己的配置和全局资源1。
  • vue3支持多个根元素在同一个模板中,而vue2只允许一个根元素2
  • vue3提供了一个新的API叫做Composition API,它可以让开发者更灵活地组织和复用代码逻辑,而不需要依赖于选项对象123。
  • vue3引入了Proxy作为响应式系统的底层实现,替代了vue2中的Object.defineProperty。这样可以提高性能,减少内存占用,支持更多的数据类型,以及解决一些vue2中存在的问题124。
  • vue3提供了一个新的函数叫做watchEffect,它可以自动追踪依赖并重新执行副作用函数,而不需要像vue2中的watch属性那样指定依赖项3。
  • vue3优化了虚拟DOM的渲染过程,引入了静态标记、片段、模板编译优化等技术,使得渲染速度更快,打包体积更小14。
  • vue3增加了对TypeScript的支持,使得开发者可以利用静态类型检查来编写更健壮和可维护的代码14。
  • vue3提供了一些新的内置组件和指令,例如Suspense、Teleport、v-model等14。
  • vue3改进了自定义指令和过渡动画的API,使得开发者可以更方便地控制指令和动画的生命周期钩子14。
  • vue3提供了一些新的工具和插件来辅助开发和调试,例如Vite、Vue Devtools、Vue Test Utils等14。
  • vue3保持了对vue2大部分语法和特性的兼容性,并提供了迁移构建版本来帮助开发者平滑地从vue2迁移到vue31

Vue3的技术选型

  • Vue(选项式2.0,组合式3.0更好)

    • 选项式 API 还是 组合式 API✔️

    • HTML 还是 单文件组件✔️

  • 语法(要用到ts的一些特性,但主要的还是js语法)

    • javascript 还是 typescript✔️
  • 构建工具(vite更轻量,构建速度更快)

    • @vue/cli 还是 vite✔️
  • 路由

    • vue-router✔️
  • 共享存储(pinia更好用)

    • vuex 还是 pinia✔️
  • 视图组件(都是组件库,一个饿了么,一个啊里)

    • ElementUI 还是 Antdv✔️

体验Vue的语法变迁

这是学完之后补充的笔记,一览从学习接触Vue到工作开发使用Vue的方式的变迁~

(1)Vue2选项式API

所谓的选项卡,Vue2老项目使用的技术,总体感觉就是不宜扩展,灵活性差于Vue3

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Calculator</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <input type="number" v-model="num1">
        <select v-model="operator">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>
        <input type="number" v-model="num2">
        <button @click="calculate">Calculate</button>
        <!-- <span>=</span> -->
        <span>{{ result }}</span>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                num1: 0,
                num2: 0,
                operator: '+',
                result: 0
            },
            watch: {
                num1: function() {
                    this.calculate();
                },
                num2: function() {
                    this.calculate();
                },
                operator: function() {
                    this.calculate();
                }
            },
            methods: {
                calculate: function() {
                    switch(this.operator) {
                        case '+':
                            // 果然还是ts好...
                            this.result = Number(this.num1)  + Number(this.num2);
                            break;
                        case '-':
                            this.result = this.num1 - this.num2;
                            break;
                        case '*':
                            this.result = this.num1 * this.num2;
                            break;
                        case '/':
                            this.result = this.num1 / this.num2;
                            break;
                    }
                }
            }
        })
    </script>
</body>
</html>

(2)Vue3组合式API

自由且灵活

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Calculator</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="app">
        <input type="number" v-model="state.num1">
        <select v-model="state.operator">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>
        <input type="number" v-model="state.num2">
        <!-- <button @click="calculate">Calculate</button> -->
        <span>={{ result }}</span>
    </div>
    <script>
        const { reactive, computed } = Vue;

        const App = {
            setup() {
                const state = reactive({
                    num1: 0,
                    num2: 0,
                    operator: '+',
                });

                const result = computed(() => {
                    switch (state.operator) {
                        case '+':
                            return Number(state.num1) + Number(state.num2);
                        case '-':
                            return state.num1 - state.num2;
                        case '*':
                            return state.num1 * state.num2;
                        case '/':
                            return state.num1 / state.num2;
                    }
                });

                // const calculate = () => state.result = result.value;


                return { state, result };
            },
        };

        Vue.createApp(App).mount('#app');
    </script>
</body>

</html>

(3)Vue3的script setup语法糖

加入了语法糖可以不用考虑那么多繁文琐节了(当然了由于这是html所以还有一些局限性,如果是单文件组件甚至不需要去编写setup函数和手动导出方法和变量了)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Calculator</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="app">
        <input type="number" v-model="state.num1">
        <select v-model="state.operator">
            <option value="+">+</option>
            <option value="-">-</option>
            <option value="*">*</option>
            <option value="/">/</option>
        </select>
        <input type="number" v-model="state.num2">
        <!-- <button @click="calculate">Calculate</button> -->
        <span>={{ result }}</span>
    </div>

    <script setup>
        import { reactive, computed, createApp } from 'vue';

        const state = reactive({
            num1: 0,
            num2: 0,
            operator: '+',
        });

        const result = computed(() => {
            switch (state.operator) {
                case '+':
                    return Number(state.num1) + Number(state.num2);
                case '-':
                    return state.num1 - state.num2;
                case '*':
                    return state.num1 * state.num2;
                case '/':
                    return state.num1 / state.num2;
            }
        });

        // const calculate = () => state.result = result.value;

        createApp({
            setup() {
                return { state, result };
            },
        }).mount('#app');
    </script>
</body>

</html>

使用了 <script setup>,代码中不再需要使用 Vue.createApp,而是需要使用 createApp 函数来创建 Vue 应用。同时,Vue 对象的引入也可以通过 import 的方式进行。

<script>标签默认情况下不支持使用ES模块的import语法,因为浏览器不支持直接加载ES模块。如果你想在<script>标签中使用import语法,你需要使用一些工具,比如Webpack或者Rollup,来将你的代码打包成浏览器可以执行的形式。当然,现代浏览器也开始支持<script type="module">标签,你可以在这个标签中使用import语法,但是它的兼容性还不太好,不建议在生产环境中使用。如果你想在浏览器中使用import语法,可以尝试使用CDN提供的库,比如ES6模块标准的库@std/esm。

(4)工程化Vue3语法糖的开发应用

只是一个例子,和前面的代码案例无关了。在工程级的项目开发中都会使用这种模式,编写单个的组件完成独立的功能模块,然后在Vue的根组件中挂载。

每个组件都由模板template、脚本script和style样式三部分组成(当然了这是单文件组件,除此之外还有纯粹的函数式组件)

<!--通用页眉组件-->
<template>
  <footer>
    <div class="center">
      <span>Copyright&nbsp;©{{ startYear }}-{{ currentYear }}&nbsp;{{ author }}&nbsp;</span>
      <span v-if="icpNumber" class="icp-number">
        <a href="http://beian.miit.gov.cn" target="_blank">{{ icpNumber }}</a>
      </span>
    </div>
  </footer>
</template>
<script lang="ts" setup>

interface PageFooterProps {
  startYear: number;
  author: string;
  icpNumber?: string;
}

const props = defineProps<PageFooterProps>();

const currentYear = new Date().getFullYear();
</script>
<style lang="less" scoped>
footer {
  background-color: #f3f4f5;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 10px;

  .center {
    text-align: center;
    color: #4e77ab;
    a {
      text-decoration: none;
      color: #4979ff;
    }
  }
}
</style>