终于还是学起了Vue3——面向初学者(一)

261 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

前提

在学习Vue3之前,首先要知道一下Vue3的优点有哪些?

笼统的来说就是:

  1. Vue3可以更好的支持TypeScript
  2. 速度加快 打包速度减少了41%
  3. 内存减少了54%,渲染加快

具体来说:

  1. 重写了响应式系统、重写了虚拟DOM的实现,性能上得到了提升
  2. 新推出组合式API(composition API),使维护组件代码变得更简单
  3. 新增了一些功能,如Teleport、Suspense、片段
  4. 修改和优化了一些API(生命周期、动画类名),同时移除了一些API(如childrenchildren、listeners、filter)

Vue3最重要的新特性就是composition API,也是接下来重点需要学习的。

setup

在vue组件中我们使用Composition API的地方,我们称为setup。setup执行的时机是在beforeCreate生命函数之前执行,因此在这个函数中是不能通过this来获取实例的;同时为了命名的统一,将beforeDestroy改名为beforeUnmountdestroyed改名为unmounted,因此vue3有以下生命周期函数:

  • beforeCreate(建议使用setup代替)
  • created(建议使用setup代替)
  • setup
  • beforeMount
  • mounted
  • beforeUpdate
  • updated
  • beforeUnmount
  • unmounted

写一个简单的方法来进行对比vue2和vue3:

// vue2
<template>
  <div class="home">{{ msg }},{{ showMessage() }}</div>
</template>

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

export default defineComponent({
  name: "Home",
  data() {
    return {
      msg: "hello world",
    };
  },
  methods: {
    showMessage() {
      return "大家好";
    },
  },
});
</script>
// vue3
<template>
  <div class="home">{{ msg }},{{ showMessage() }}</div>
</template>

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

export default defineComponent({
  name: "Home",
  setup() {
    let msg = "hello world";
    function showMessage() {
      return "大家好";
    }
    return {
      msg,
      showMessage,
    };
  },
});
</script>

ref

ref()函数可以将数据转化为响应式数据,一般用来定义一个基本类型的响应式数据。

在使用ref之前需要在页面中进行引用:

import { ref } from "vue";

在setup中使用时:let count = ref(1);,此时如果要改变count变量的值的时候,改变的是count.value 页面完整代码如下:

<template>
  <div>
    <div>{{ count }}</div>
    <button @click="increase()" type="button"></button>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
export default defineComponent({
  name: "ref",
  setup() {
    let count = ref(1);
    let increase = () => {
      console.log(count);
      count.value++;
    };
    return {
      count,
      increase,
    };
  },
});
</script>
<style lang="scss" scoped>
button {
  width: 100px;
  height: 40px;
}
</style>

打印count:

image.png

reactive

reactive()函数的用法与ref()的用法像是,也是将数据变成响应式数据,当数据发生变化的时候模板视图也会自动更新;不同的是ref()用于基本数据类型,而reactvie()用于引用类型的数据,比如对象和数组。 ref其实也能响应式改变引用类型的值,不过不推荐使用;

<template>
  <div>
    <div class="" v-for="(item, index) in arr" :key="index">
      {{ item.title }}:{{ item.value }}
    </div>
    <button @click="addData()">添加数据</button>
  </div>
</template>
<script lang="ts">
import { defineComponent, reactive } from "vue";
export default defineComponent({
  name: "reactive",
  setup() {
    let arr = reactive([ // 需要注意的是,用法和ref有些出入
      {
        title: "姓名",
        value: "张三",
      },
      {
        title: "姓名",
        value: "李四",
      },
      {
        title: "姓名",
        value: "王五",
      },
    ]);
    let addData = () => {
      arr.push({
        title: "姓名",
        value: "刘麻子",
      });
    };
    return {
      arr,
      addData
    };
  },
});
</script>

响应式原理

面试中经常会被问,Vue3的响应式原理是什么?这里就顺道记录一下:

Vue3的响应式原理是通过Proxy(代理)对对象的属性值进行读写、添加、删除进行劫持,通过Reflect(反射)动态对被代理对象的属性进行特定的操作;Proxy和Reflect不支持IE浏览器,这也是Vue3不支持IE浏览器的主要原因之一。

Vue2的响应式原理是通过defineProperty对对象已有属性值的读取和修改进行劫持(监视/拦截),通过重写数组、更新数组一系列更新元素的方法来实现元素修改的劫持。

Object.defineProperty 不足在于:

  • Object.defineProperty 只能劫持对象的属性(key值.Object.key()),因此我们需要对每个对象的每个属性进行遍历。
  • Object.defineProperty不能监听数组。是通过重写数据的那7个可以改变数据的方法来对数组进行监听的。
  • Object.defineProperty 也不能对 es6 新产生的 Map、Set 这些数据结构做出监听。
  • Object.defineProperty也不能监听新增和删除操作,通过 Vue.set()Vue.delete来实现响应式的。

Vue3用Proxy的优势如下:

  • 可以直接监听整个对象而非属性。
  • 可以直接监听数组的变化。
  • 有13中拦截方法,如ownKeys、deleteProperty、has 等是 Object.defineProperty 不具备的。
  • 返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改;

未完待续~