• 六十九、Vue3


    一 Vue3的变化

    1. 性能的提升
      打包大小减少41%

      初次渲染快55%, 更新渲染快133%

      内存减少54%

    2. 源码的升级
      使用Proxy代替defineProperty实现响应式

      重写虚拟DOM的实现和Tree-Shaking

    3. 拥抱TypeScript
      Vue3可以更好的支持TypeScript

    4. 新的特性
      Composition API(组合API)

      setup配置
      ref与reactive
      watch与watchEffect
      provide与inject
      新的内置组件

      Fragment
      Teleport
      Suspense
      其他改变

      新的生命周期钩子
      data 选项应始终被声明为一个函数
      移除keyCode支持作为 v-on 的修饰符

    5. 组合式API和配置项API
      使用传统OptionsAPI中,新增或者修改一个需求,就需要分别在data,methods,computed里修改 。

      组件中的template标签可以没有根标签

    二 创建Vue3项目的两种方式

    2.1 vue-cl创建

    vue-cli创建和之前创建vue2一样,选择vue版本时选择3.x即可。

    2.2 vite创建

    创建的项目将使用基于 Vite 的构建设置,并允许我们使用 Vue 的单文件组件 (SFC)。

    1. 在终端输入以下命令

      npm init vue@latest
      
      • 1

      在这里插入图片描述

    2. cd到项目文件夹,执行npm install,然后执行npm run dev
      npm run dev

    3. 项目启动成功,访问网址。
      在这里插入图片描述

    4. 也可在vscode中打开项目文件夹
      在这里插入图片描述

    三 常用API

    3.1 setup

    1. setup为Vue3.0中一个新的配置项,值为一个函数

    2. setup是所有Composition API(组合API)编写的位置

    3. 组件中所用到的:数据、方法等等,均要配置在setup中

    4. setup函数的返回值:返回一个对象,对象中的属性、方法, 在模板中均可以直接使用

      注意:

      尽量不要与Vue2.x配置混用

      Vue2.x配置(data、methos、computed…)中可以访问到setup中的属性、方法。
      但在setup中不能访问到Vue2.x配置(data、methos、computed…)。
      如果有重名, setup优先。

    <template>
      {{ name }}
      <br>
      {{ age }}
      <br>
      <button @click="ageAdd">点击年龄+1</button>
    </template>
    
    <script>
    export default {
      name: 'App',
      created(){
        console.log(this)
      },
      setup() {
        let name = 'xuxiaoxu'
        let age = 18
        console.log(this)
        let ageAdd = () => {
          age++
          console.log(age)
        }
    
        return {
          name, age,ageAdd
        }
      }
    }
    </script>
    
    • 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

    在这里插入图片描述
    注意:

    1. setup函数中没有了this,在setup函数外是有this的,但是不是Vc实例了,而变成了Proxy实例。
      在这里插入图片描述
    2. 所有的变量和方法都在setup函数中写。
    3. 定义了变量,变量可以渲染,但是没有响应式,值变了,但是渲染的值没有跟着改变。
    4. setup必须要有返回值,返回的值才能在模板中使用。

    3.2 ref和reactive

    • 作用: 定义一个响应式的数据

    • 语法: const 变量= ref(值)

      创建一个包含响应式数据的引用对象(reference对象,简称ref对象)。
      JS中操作数据: 变量.value
      模板中读取数据: 不需要.value,直接:

      {{变量}}

    <template>
      {{ name }}
      <br>
      {{ age }}
      <br>
      <button @click="ageAdd">点击年龄+1</button>
    </template>
    
    <script>
    import { ref } from 'vue'
    
    export default {
      name: 'App',
      setup() {
        let name = ref('xuxiaoxu')
        let age = ref(18)
        console.log(name)
        console.log(age)
        let ageAdd = () => {
          age.value++
          console.log(age.value)
        }
    
        return {
          name, age,ageAdd
        }
      }
    }
    </script>
    
    • 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

    在这里插入图片描述

    • 接收的数据可以是:基本类型、也可以是对象类型。

      基本类型的数据:响应式依然是靠Object.defineProperty()的get与set完成的

      对象类型的数据:内部 求助 了Vue3.0中的一个新函数—— reactive函数

    <template>
      {{ info.name }}
      <br>
      {{ info.age }}
      <br>
      <button @click="info.ageAdd">点击年龄+1</button>
    </template>
    
    <script>
    import { reactive } from 'vue'
    export default {
      name: 'App',
      setup() {
        let info = reactive({
          name: 'xuxiaoxu',
          age: 18
        })
        info.ageAdd = () => {
          info.age += 1
          console.log(info.age)
        }
        console.log(info)
    
        return {
          info
        }
      }
    }
    </script>
    
    • 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

    在这里插入图片描述
    对象在渲染时直接对象点key就可以获取到value,也可以直接给对象添加方法。

    3.3 计算和监听属性

    computed函数使用

    <template>
      <p>姓:<input type="text" v-model="info.firstName">p>
      <p>名:<input type="text" v-model="info.lastName">p>
      <p>全名:<input type="text" v-model="info.fullName">p>
    template>
    
    <script>
    import { computed, reactive } from 'vue'
    export default {
      name: 'App',
      setup() {
        const info = reactive({
          firstName: '',
          lastName: ''
        })
        info.fullName = computed({
          get() {
            return info.firstName + '_' + info.lastName
          },
          // 修改属性会执行set函数,并将修改后的值传入
          set(val) {
            console.log(val)
            let strArray = val.split('_')
            info.firstName = strArray[0]
            info.lastName = strArray[1]
          }
        })
    
        return {
          info
        }
      }
    }
    script>
    
    • 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

    在这里插入图片描述
    watch函数

    <template>
      <p><input type="text" v-model="name">{{ name }}p>
    template>
    
    <script>
    import { watch, ref, watchEffect } from 'vue'
    export default {
      name: 'App',
      setup() {
        const name = ref('xuxiaoxu')
        watch(name, (value, oldvalue) => {
          console.log(value)
          console.log(oldvalue)
        })
    
        watchEffect(()=>{
          // 只有当watchEffect里使用的变量值改变才会执行该函数
          let a = name.value
          console.log('执行了')
        })
    
        return {
          name
        }
      }
    }
    script>
    
    • 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

    在这里插入图片描述

    3.4 生命周期

    在这里插入图片描述

    1. beforeCreate:在组件实例初始化完成之后立即调用。组合式 API 中的 setup() 钩子会在所有选项式 API 钩子之前调用,beforeCreate() 也不例外。
    2. created:在组件实例处理完所有与状态相关的选项后调用。当这个钩子被调用时,以下内容已经设置完成:响应式数据、计算属性、方法和侦听器。然而,此时挂载阶段还未开始,因此 $el 属性仍不可用。
    3. beforeMount:在组件被挂载之前调用。当这个钩子被调用时,组件已经完成了其响应式状态的设置,但还没有创建 DOM 节点。它即将首次执行 DOM 渲染过程。这个钩子在服务端渲染时不会被调用。
    4. mounted:在组件被挂载之后调用。这个钩子在服务端渲染时不会被调用。
    5. beforeUpdate:在组件即将因为一个响应式状态变更而更新其 DOM 树之前调用。
    6. updated:在组件因为一个响应式状态变更而更新其 DOM 树之后调用。
    7. beforeUnmount:在一个组件实例被卸载之前调用。当这个钩子被调用时,组件实例依然还保有全部的功能。
    8. 在一个组件实例被卸载之后调用。可以在这个钩子中手动清理一些副作用,例如计时器、DOM 事件监听器或者与服务器的连接。
    <template>
      <h1>生命周期h1>
      <hr>
      <button @click="handleClick">点我消失button>
      <Child v-if="show">Child>
    
    
    template>
    
    <script>
    import Child from "./components/Child.vue";
    import { ref } from 'vue'
    
    export default {
      name: 'App',
      components: { Child },
      setup() {
        let show = ref(true)
        const handleClick = () => {
          show.value = !show.value
        }
        return {
          show, handleClick
        }
    
      }
    }
    script>
    
    • 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
    <template>
        <h1>我是Child组件h1>
      template>
      
      <script>
      import {onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted} from 'vue'
      
      export default {
        name: 'Child',
        setup() {
          console.log('组合式api的beforeCreate')
          console.log('组合式api的created')
          onBeforeMount(() => {
            console.log('组合式api的onBeforeMount')
          })
          onMounted(() => {
            console.log('组合式api的onMounted')
          })
          onBeforeUpdate(() => {
            console.log('组合式api的onMounted')
          })
          onBeforeUnmount(() => {
            console.log('组合式api的onBeforeUnmount')
          })
          onUnmounted(() => {
            console.log('组合式api的onUnmounted')
          })
    
          return{}
      
        }
      }
      script>
    
    • 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

    在这里插入图片描述

    3.5 自定义hook函数

    在 Vue 应用的概念中,“组合式函数”(Composables) 是一个利用 Vue 的组合式 API 来封装和复用有状态逻辑的函数。

    相比之下,有状态逻辑负责管理会随时间而变化的状态。一个简单的例子是跟踪当前鼠标在页面中的位置。在实际应用中,也可能是像触摸手势或与数据库的连接状态这样的更复杂的逻辑。

    鼠标跟踪器示例

    如果我们要直接在组件中使用组合式 API 实现鼠标跟踪功能,它会是这样的:

    <template>当前鼠标点击坐标为:({{ coord.x }} ,{{ coord.y }})template>
    
    <script setup>
    import { reactive, onMounted, onUnmounted } from "vue";
    
    const coord = reactive({
      x: 0,
      y: 0,
    });
    const mouseClick = (event) => {
      console.log(event);
      coord.x = event.x;
      coord.y = event.y;
    };
    onMounted(() => window.addEventListener("click", mouseClick));
    onUnmounted(() => window.removeEventListener("click", mouseClick));
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    但是,如果我们想在多个组件中复用这个相同的逻辑呢?我们可以把这个逻辑以一个组合式函数的形式提取到外部文件中:

    // mouse.js
    import { reactive, onMounted, onUnmounted } from "vue";
    export function useMouse() {
        const coord = reactive({
            x: 0,
            y: 0,
        })
        const mouseClick = (event) => {
            console.log(event)
            coord.x = event.x
            coord.y = event.y
        }
        onMounted(() => window.addEventListener("click", mouseClick))
        onUnmounted(() => window.removeEventListener("click", mouseClick))
        return coord
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    下面是它在组件中使用的方式:

    <template>当前鼠标点击坐标为:({{ coord.x }} ,{{ coord.y }})template>
    
    <script setup>
    import { useMouse } from "./mouse.js";
    
    const coord = useMouse();
    script>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在这里插入图片描述

    🔗 vue3官方文档 https://cn.vuejs.org/guide/introduction.html

  • 相关阅读:
    《定时执行专家》官方版介绍 —— 毫秒级精度、多线程、专业级的定时任务执行软件
    Abnova 环孢素A单克隆抗体,及其研究工具
    k8s自动化运维八-如何清理docker存储的大文件
    辅助驾驶功能开发-控制篇(03)-基于PID的请求角度转扭矩算法
    6.搭建Eureka
    PostgreSQL的学习心得和知识总结(六十四)|关于PostgreSQL数据库 图式搜索(graph search)及递归查询 的场景说明
    双链笔记葫芦笔记综合评测:优点、缺点、建议
    剑指offer——JZ77 按之字形顺序打印二叉树 解题思路与具体代码【C++】
    ConstantPool::allocate记录
    C++ list容器模拟实现
  • 原文地址:https://blog.csdn.net/weixin_68531269/article/details/127657031