27.vue3和vue2的区别?

93 阅读4分钟

1. main.js 不同

import { createApp } from "vue";
import App from "./App.vue";
import "./index.css";

//vue2
// const app = new Vue(options)
// app.$mount("#app")

//vue3
// 不存在构造函数Vue
// const app = createApp(App);
// app.mount("#app");

2. vue3的 template 可以存在多个根节点,而vue2不能存在多个根节点

3.生命周期钩子函数不同

vue2vue2中的生命周期

  • beforeCreate 组件创建之前
  • created 组件创建之后
  • beforeMount 组价挂载到页面之前执行
  • mounted 组件挂载到页面之后执行
  • beforeUpdate 组件更新之前
  • updated 组件更新之后

vue3vue3中的生命周期

  • setup 开始创建组件
  • onBeforeMount 组价挂载到页面之前执行
  • onMounted 组件挂载到页面之后执行
  • onBeforeUpdate 组件更新之前
  • onUpdated 组件更新之后

而且vue3.x 生命周期在调用前需要先进行引入。除了这些钩子函数外,vue3.x还增加了onRenderTracked 和onRenderTriggered函数。

4. API不同

vue2:vue2使用选项类型api,选项型api在代码里分割了不同的属性:data,computed,methods等。

vue3:vue3使用组合式api,新的合成型api能让我们使用方法来分割,相比于旧的api使用属性来分组,这样代码会更加简便和整洁

组合式API更容易实现把高内聚的目的,更容易把相同的功能写在一坨,而不是写的到处都是。

vue2:vue2是把数据放入data中,在vue2中定义数据变量是data(){} ,创建的方法要在methods:{} 中。

vue3:,vue3就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。使用以下三个步骤来建立反应性数据:

  • 从vue引入reactive
  • 使用reactive() 方法来声明数据为响应性数据;
  • 使用setup()方法来返回我们的响应性数据,从而template可以获取这些响应性数据。

其实Vue3的本质就是将vue2的 data,method,computed等都放在setup里面,然后再将这些东西返回,返回后就会挂载在vue实例上,这样就可以在模版里面使用了。

vue3 其实是将不同的功能可以分在不同的文件中,不同的文件提供不同的响应式数据,计算属性和方法。 这些不同的文件都是给模版使用的,不同的文件一般是代表不同的功能,有时候需要一个模块需要用到别的模块的数据,就可以在模版所在文件中,将数据以参数的形式传给另一个模块,所有的模块都使用的是响应式数据,这样就可以形成一个响应式链条,而且可以将这个聊天进行随意的修改。这其实就是vue3 组合式API的本质

import { ref, onMounted, onUnmounted, computed } from "vue";
import { filter } from "../util/todoStorage";

const validHash = ["all", "active", "completed"];

export default function useFilter(todosRef) {
  const visibilityRef = ref("all");

  const onHashChange = () => {
    const hash = location.hash.replace(/#\/?/, "");
    if (validHash.includes(hash)) {
      //有效的
      visibilityRef.value = hash;
    } else {
      location.hash = "";
      visibilityRef.value = "all";
    }
  };

  // 1. 组件挂载完成的生命周期函数
  onMounted(() => {
    window.addEventListener("hashchange", onHashChange);
  });
  // 2. 组件销毁过后的生命周期函数
  onUnmounted(() => {
    window.removeEventListener("hashchange", onHashChange);
  });

  // 计算属性
  const filteredTodosRef = computed(() => {
    return filter(todosRef.value, visibilityRef.value);
  });

    // 计算属性
  const remainingRef = computed(() => {
    return filter(todosRef.value, "active").length;
  });
  // 计算属性
  const completedRef = computed(() => {
    return filter(todosRef.value, "completed").length;
  });

  return {
    // 以下是响应式数据
    visibilityRef,
    //下面是计算属性
    filteredTodosRef,
    remainingRef,
    completedRef,
  };
}

import { ref } from "vue";
import { generateId } from "../util/todoStorage";

export default function useNewTodo(todosRef) {
  const newTodoRef = ref(""); // 新任务的标题
  
  // 代替原来方法的位置
  const addTodo = () => {
    // 新增一个任务
    const value = newTodoRef.value && newTodoRef.value.trim();
    if (!value) {
      return;
    }
    // 生成一个任务对象,将其加入到任务列表中
    const todo = {
      id: generateId(),
      title: value,
      completed: false, // 任务是否完成
    };
    todosRef.value.push(todo);
    newTodoRef.value = "";
  };
  return {
    newTodoRef,
    //供模版和其他模块使用的方法
    addTodo,
  };
}

还有一个就是对响应式数据的处理问题,vue2 放在data,computed里面就是响应式数据。而在vue3 中需要将响应式数据用ref包装一下,然后在setup里面数据被包装成一个对象,由于setup函数是在所有的 props 被赋值后就会执行,在vue实例被创建前调用,所以这时setup 中的this指向 undefined,接着前面的,由于数据被包装成一个对象,此时访问该数据需要用data.value去访问。而在temple里面数据,vue实例已经生成。

下图是vue3 响应式数据的处理

vue3对ref的特殊处理.jpg

5.组件里面的this指向不同

vue2 中this指向组件实例,vue3中this指向的是代理,代理里面也有一个组件实例对象。

vue3的组件实例代理.jpg