我的Vue | 半年没学会Vue2,一个月精通Vue3,2和3区别在哪里

2024-07-31 16:28:13 浏览数 (2)

前言

我在19年刚开始学习vue的时候,还没有vue2和vue3之分,一头扎进vue学习文档里,进去的时候生龙活虎,出来的时候是头晕眼花。

笔记做了不少,但是最后想写一个项目的时候,不知道从哪里入手。后来又学习了vue-cli才开始我的vue之路。在开始学习vue2的时候,我时常被vue2的选项式API搞得怀疑人生,在兜兜转转的半年里,最后将学到的vue2忘得干干净净。

2023年底,借着研究开源项目BuildAdmin后台管理系统,用一个月学完了vue3的生态,也写了一系列关于BuildAdmin模块拆解的文章,从此入门前端。

BuildAdmin和vue3专栏

选项式 VS 组合式

在初学vue时,常常在vue2的选项式开发中迷茫。我们先看vue2是如何定义一个vue组件的。

代码语言:javascript复制
export default{
  el: '#app',
  data: {
    fullName: 'Foo Bar'
  },
  computed: {},
  watch: {},
  methods: {},
  mounted() {},
  created: function () {
  }
}

vue2定义组件使用的是选项式开发,每个属性和方法、以及生命周期都在结构中定义好了,我们只需要在指定的地方,放入相应的数据和方法就可以了。选项式开发的好处就是简单,缺点就是在定义一些函数时,一层层的括号让人看的眼花缭乱,而且这种开发模式不太符合正常的编程。

这里就仅仅是定义了data、watch两个选项属性,如果加上methods、computed以及生命周期函数,代码阅读性就会差那么一丢丢。好在vue3迎来了组合式开发,终于告别了vue2的选项式开发。

代码语言:typescript复制
<script setup lang='ts'>
  import {ref, watch, computed} from 'vue'
  const fullName = ref('Foo Bar')
  watch(() => fullName, () => console.log('hello world'))
</script>

在组合式开发中,属性和函数都被抽离了出来,想要使用直接引入就可以。同时,vue2中的data响应数据,在vue3中直接使用ref或者reactive声明。

生命周期

在vue中,一个页面在创建时都要经历一系列的初始化。vue根据初始化过程中不同阶段,会调用一些方法,这些方法就是生命周期函数

一个vue组件的生命周期,包括创建、挂载、更新和销毁。在每个阶段,都有一个before和完成的生命周期函数。

在vue中,通常路由切换会导致组件的创建与销毁,还有v-if在true和false切换时,也会导致组建的创建与销毁,使用keep-alive标签可以避免组件的销毁。

vue2生命周期函数

在vu2的生命周期函数中,我们需要在对应的生命周期函数选项变量中,去定义函数。

代码语言:JavaScript复制
export default{
  beforeCreate: () => {},
  beforeMount: ()  => {
  }
}

vue3生命周期函数

在vue3中的setup中,除了上面选项式定义生命周期函数之外,还可以通过组合式API来定义。

代码语言:typescript复制
<script setup>
import {onMounted, onBeforeMount, onUnmounted} from 'vue'
onBeforeMount(() => {
  // 函数体
})
</script>

vue2中beforeMount的选项式API对应vue3中的OnBeforeMount,其他声明周期函数的对应关系如下图。

因为setup中的代码执行时机,是在生命周期beforeCreate和created之前。所以在组合式API中,直接将这两个生命周期给删除了。

setup语法糖

上面vue3的代码离不开setup,是在组件中使用组合式 API 的入口,而setup是setup()的语法糖。

因为setup执行时机在生命周期beforeCreate和created之前,所以setup()有两个应用场景:

  1. 被用来返回响应数据给template
  2. 如果没有template,直接返回渲染函数h()用来挂载元素。
代码语言:javascript复制
<script lang="ts">
  setup(props) {
      const iconStyle = computed(() => {
          const {size, color} = props
          return () => h('i', {
              class: 'icon '   props.name,
              style: iconStyle.value
          })
      }
  }
</script>

而我们通常都会在script中加上setup,这样就能轻松使用组合式API的编译时语法糖,里面的代码会被编译成组件setup()函数的内容,然后执行。

这意味着与普通的 <script> 只在组件被首次引入的时候执行一次不同,<script setup> 中的代码会在每次组件实例被创建的时候执行。

同时,vue3组件无需export defalut导出之后才能引用,引用组件也无需在components中声明。除此之外还提供了defineProps、defineEmits、defineExpose、withDefaults等简洁方便的API。

defineComponent

defineComponent是vue3中于选项式开发的,上一刻还在讲上面的setup语法糖,怎么绕来绕去最后怎么又回到了vue2的选项式API,这个且听我细细道来。

在上面讲的setup()代码样例中,最后返回的是一个渲染函数h(),这个是setup语法糖做不到的,这种情况下必须使用setup(),而setup()是选项式API的写法。

同时选项式API是无法使用typescript的,为了可以使用typecript,所以使用vue3提供了defineComponent。

代码语言:typescript复制
<script lang="ts">
  import { defineComponent } from 'vue'
  export default defineComponent({
      name: 'Icon',
      props: {
          name: {
              type: String,
              required: true,
          },
      },
      setup(props) {
        return h('i');
      }
  })
</script>

在defineComponent中,可以使用typescript的强类型实现props的类型推导,给予组件正确参数类型推断。

结语

总的来说,vue3在开发的简易程度上已经大大超过了vue2,如果现在还在使用vue2的话,可以迁移到vue3。这样,会提高代码可读性,同时也会降低后续的维护成本。

0 人点赞