Vue2和Vue3的区别

响应式系统

Vue 2
  • 技术基础 :使用 Object.defineProperty 实现响应式。
  • 局限性
    • 无法监听新增属性:如果在创建实例后添加新属性,这些属性不会自动成为响应式的。
    • 数组变更检测问题:直接通过索引设置值或长度不会触发更新。

示例:Vue 2 中的响应式数据

javascript 复制代码
// Vue 2 示例
new Vue({
  data() {
    return {
      message: 'Hello, Vue 2!',
      items: []
    };
  },
  methods: {
    addItem() {
      // 直接修改数组不会触发视图更新
      this.items[0] = 'New Item';
      // 正确的做法是使用 Vue.set 或 this.$set
      this.$set(this.items, 1, 'Another Item');
    }
  }
});
Vue 3
  • 技术基础 :基于 ES6 Proxy 的全新响应式系统。
  • 优势
    • 全面监听:可以拦截对象的所有操作,包括属性的添加、删除、访问和修改。
    • 深层嵌套对象:对深层嵌套的对象也能自动追踪变化。

示例:Vue 3 中的响应式数据

javascript 复制代码
// Vue 3 示例
import { reactive } from 'vue';

const state = reactive({
  message: 'Hello, Vue 3!',
  items: []
});

state.items.push('New Item'); // 自动触发视图更新
state.items[0] = 'Updated Item'; // 自动触发视图更新

组合式 API (Composition API)

Vue 2
  • 逻辑复用:依赖于混入(mixins),容易导致命名冲突和维护困难。
Vue 3
  • 逻辑复用:引入了 Composition API,允许开发者将相关逻辑封装到函数中,并在不同的组件之间共享。

示例:组合式 API 使用

javascript 复制代码
// 定义一个可重用的逻辑钩子
import { ref, onMounted } from 'vue';

function useMousePosition() {
  const x = ref(0);
  const y = ref(0);

  function update(event) {
    x.value = event.pageX;
    y.value = event.pageY;
  }

  onMounted(() => window.addEventListener('mousemove', update));

  return { x, y };
}

// 在组件中使用
export default {
  setup() {
    const { x, y } = useMousePosition();

    return {
      x,
      y
    };
  }
};

生命周期钩子

Vue 2
  • 钩子名称 :提供了明确的生命周期钩子,如 beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeDestroy, 和 destroyed
Vue 3
  • 钩子调整 :保留了大部分原有的钩子,但为了统一命名规则,做了如下更改:

    • 创建阶段:setup

    • 挂载阶段:onBeforeMount,onMounted

    • 更新阶段:onBeforeUpdate,onUpdated

    • 卸载阶段:onBeforeUnmount,onUnmounted

  • setup() 钩子:这是一个新的组件选项,运行在实例创建之前。

示例:Vue 3 中使用生命周期钩子

javascript 复制代码
import { onMounted, onUnmounted } from 'vue';

export default {
  setup() {
    onMounted(() => {
      console.log('Component is mounted');
    });

    onUnmounted(() => {
      console.log('Component is unmounted');
    });

    return {};
  }
};

模板支持与渲染函数

Vue 2
  • 根节点限制:模板必须有一个单一的根元素。
Vue 3
  • 片段支持:移除了单个根节点的要求,允许模板中有多个顶级元素。

示例:Vue 3 中的多根节点模板

javascript 复制代码
<template>
  <h1>Title</h1>
  <p>Paragraph</p>
</template>

性能提升

Vue 2
  • 虚拟 DOM:尽管已经很高效,但在大规模应用中仍可能遇到性能瓶颈。
Vue 3
  • 改进的虚拟 DOM:重新设计的虚拟 DOM 实现,采用了更高效的算法来比较和更新 DOM 树。

示例:Vue 3 中的性能优化

虽然性能优化更多体现在框架内部,但从开发者的角度来看,减少不必要的计算和渲染可以帮助提高性能。例如,使用 computed 属性而不是方法来缓存计算结果:

javascript 复制代码
import { computed } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const doubleCount = computed(() => count.value * 2);

    return {
      count,
      doubleCount
    };
  }
};

TypeScript 支持

Vue 2
  • 类型支持:虽然可以结合 TypeScript 使用,但不是从一开始就设计好的。
Vue 3
  • 全面支持:核心库完全用 TypeScript 编写,提供了强大的类型定义和支持。

示例:Vue 3 中使用 TypeScript

javascript 复制代码
import { defineComponent, ref } from 'vue';

export default defineComponent({
  name: 'MyComponent',
  props: {
    msg: {
      type: String as PropType<string>,
      required: true
    }
  },
  setup(props) {
    const count = ref<number>(0);

    return {
      count,
      increment: () => count.value++
    };
  }
});

包大小

Vue 2
  • 体积问题:随着功能的增加,Vue 2 的核心库体积也在增大。
Vue 3
  • 模块化设计:通过 tree-shaking 技术,Vue 3 能够只打包实际使用的代码,显著减小了最终打包文件的体积。

示例:Vue 3 中的按需加载

javascript 复制代码
// 只导入需要的部分
import { createApp, ref } from 'vue';

组件注册与全局配置

Vue 2
  • 组件注册 :可以使用 Vue.component 注册全局组件,或者在单文件组件中通过 components 选项注册局部组件。
  • 全局配置 :如全局事件总线、全局过滤器等,通常通过 Vue.prototype 或者 Vue.mixin 实现。
Vue 3
  • 组件注册 :推荐使用 app.component 来注册全局组件,局部组件仍然可以通过 components 选项注册。
  • 全局配置 :不再推荐使用 Vue.prototypeVue.mixin,而是提供了新的 API 如 app.config.globalPropertiesprovide/inject 来实现类似功能。

示例:Vue 3 中的全局属性

javascript 复制代码
import { createApp } from 'vue';
import App from './App.vue';

const app = createApp(App);

// 添加全局属性或方法
app.config.globalProperties.$globalMethod = () => {
  console.log('This is a global method');
};

app.mount('#app');

插件系统

Vue 2
  • 插件安装 :通过 Vue.use(plugin) 安装插件,插件可以添加全局组件、指令、混入等。
Vue 3
  • 插件安装 :依然使用 app.use(plugin) 安装插件,但插件的设计更加模块化,鼓励按需加载和更细粒度的功能分割。

示例:Vue 3 中的插件

javascript 复制代码
// 插件定义
export default {
  install(app, options) {
    // 添加一个全局方法
    app.config.globalProperties.$myPluginMethod = function() {
      console.log('Plugin method called');
    };

    // 添加一个全局指令
    app.directive('focus', {
      mounted(el) {
        el.focus();
      }
    });
  }
};

// 使用插件
import myPlugin from './plugins/myPlugin';

const app = createApp(App);
app.use(myPlugin);
app.mount('#app');

指令系统

Vue 2
  • 自定义指令 :通过 Vue.directive 或者在组件内部使用 directives 选项来定义自定义指令。
Vue 3
  • 自定义指令 :仍然支持自定义指令,但 API 略有变化,现在是通过 app.directive 来定义。此外,钩子函数的名称也做了调整(例如,bind 改为 mounted)。

示例:Vue 3 中的自定义指令

javascript 复制代码
import { createApp } from 'vue';

const app = createApp({});

app.directive('colorize', {
  mounted(el, binding) {
    el.style.color = binding.value || 'red'; // 默认颜色为红色
  }
});

app.mount('#app');

// 在模板中使用
<template>
  <p v-colorize="'blue'">这段文本应该是蓝色。</p>
</template>

自定义渲染器

Vue 2
  • 自定义渲染器:如果需要创建自定义渲染器(例如用于不同的 DOM 环境),则需要从头开始编写,这相对复杂。
Vue 3
  • 自定义渲染器 :引入了 @vue/runtime-core@vue/runtime-dom,使得创建自定义渲染器变得更加简单和模块化。开发者可以利用这些包提供的工具函数快速搭建适合特定环境的渲染逻辑。

示例:Vue 3 中的自定义渲染器

虽然这个例子较为复杂,但它展示了如何创建一个简单的自定义渲染器:

javascript 复制代码
import { createRenderer } from '@vue/runtime-core';

const renderer = createRenderer({
  createElement(type) {
    return document.createElement(type);
  },
  patchProp(el, key, prevValue, nextValue) {
    if (key.startsWith('on')) {
      const event = key.slice(2).toLowerCase();
      el.addEventListener(event, nextValue);
    } else {
      if (nextValue == null) {
        el.removeAttribute(key);
      } else {
        el.setAttribute(key, nextValue);
      }
    }
  },
  insert(child, parent, anchor = null) {
    parent.insertBefore(child, anchor);
  },
  remove(child) {
    const parent = child.parentNode;
    if (parent) {
      parent.removeChild(child);
    }
  },
  setElementText(node, text) {
    node.textContent = text;
  }
});

renderer.createApp(App).mount(document.querySelector('#app'));

响应式数据类型

Vue 2
  • 响应式数据类型:仅限于对象和数组。
Vue 3
  • 响应式数据类型 :除了对象和数组外,还支持原始类型的响应式包装(如 refreactive)。这允许对基本类型(如数字、字符串)进行响应式处理。

示例:Vue 3 中的 refreactive

javascript 复制代码
import { ref, reactive } from 'vue';

// 使用 ref 包装基本类型
const count = ref(0);

// 使用 reactive 包装对象
const state = reactive({
  message: 'Hello, Vue!',
  items: []
});

// 更新响应式数据
count.value++;
state.items.push('New Item');

错误处理与调试

Vue 2
  • 错误处理:主要依赖于开发者手动捕获错误并在代码中处理,Vue Devtools 提供了一些基本的帮助。
Vue 3
  • 错误处理:增强了内置的错误处理机制,提供了更友好的错误捕获和报告方式。同时,Vue Devtools 也得到了显著改进,增加了更多调试选项,如时间旅行调试、性能分析等。

示例:Vue 3 中的错误处理

javascript 复制代码
import { createApp } from 'vue';

const app = createApp(App);

// 设置全局错误处理器
app.config.errorHandler = (err, vm, info) => {
  console.error(`Error in ${info}: ${err.message}`);
};

app.mount('#app');

插槽(Slots)

Vue 2
  • 语法多样:既有具名插槽也有作用域插槽,存在多种语法形式。
Vue 3
  • 统一语法v-slot 成为了指定作用域插槽的唯一方式。

示例:Vue 3 中的作用域插槽

javascript 复制代码
<!-- 父组件 -->
<template>
  <child-component v-slot="slotProps">
    {{ slotProps.message }}
  </child-component>
</template>

<!-- 子组件 -->
<template>
  <slot :message="msg"></slot>
</template>

<script>
export default {
  data() {
    return {
      msg: 'Hello from child'
    };
  }
};
</script>

新增功能

Vue 3
  • Teleport:用于解决弹出层等场景下的 DOM 结构问题。
  • Suspense:用于等待异步依赖加载完成。

示例:使用 Teleport 和 Suspense

javascript 复制代码
<!-- 使用 Teleport 将内容移动到 body -->
<template>
  <teleport to="body">
    <div id="modal">Modal content</div>
  </teleport>
</template>

<script>
import { defineAsyncComponent } from 'vue';

export default {
  components: {
    AsyncComponent: defineAsyncComponent(() => import('./components/AsyncComponent.vue'))
  }
};
</script>

<!-- 使用 Suspense 等待异步组件加载 -->
<template>
  <suspense>
    <template #default>
      <async-component />
    </template>
    <template #fallback>
      <div>Loading...</div>
    </template>
  </suspense>
</template>

移除的功能

Vue 3
  • .native 修饰符:移除,现在可以直接在自定义组件上监听原生事件。
  • keyCode 事件修饰符:移除,推荐使用键盘事件对象进行键码判断。
  • 过滤器:移除,鼓励使用计算属性或其他替代方案。

示例:Vue 3 中处理键盘事件

javascript 复制代码
<template>
  <input @keyup.enter="submitForm" />
</template>

<script>
export default {
  methods: {
    submitForm(event) {
      if (event.key === 'Enter') {
        // 处理表单提交逻辑
      }
    }
  }
};
</script>

其他改进

Vue 3
  • 调试工具:Vue Devtools 得到了增强,提供了更多调试选项。
  • SSR 支持:改善了服务器端渲染的支持。
  • 错误处理:提供了更友好的错误捕获和报告机制。

示例:Vue 3 中的全局错误处理

javascript 复制代码
import { createApp } from 'vue';

const app = createApp(App);

app.config.errorHandler = (err, vm, info) => {
  // 处理错误
  console.error(`Error in ${info}: ${err.message}`);
};

app.mount('#app');
相关推荐
燃先生._.3 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
2401_857600957 小时前
SSM 与 Vue 共筑电脑测评系统:精准洞察电脑世界
前端·javascript·vue.js
2401_857600957 小时前
数字时代的医疗挂号变革:SSM+Vue 系统设计与实现之道
前端·javascript·vue.js
GDAL7 小时前
vue入门教程:组件透传 Attributes
前端·javascript·vue.js
轻口味7 小时前
Vue.js 核心概念:模板、指令、数据绑定
vue.js
2402_857583497 小时前
基于 SSM 框架的 Vue 电脑测评系统:照亮电脑品质之路
前端·javascript·vue.js
java_heartLake8 小时前
Vue3之性能优化
javascript·vue.js·性能优化
ddd君317749 小时前
组件的声明、创建、渲染
vue.js
前端没钱9 小时前
从 Vue 迈向 React:平滑过渡与关键注意点全解析
前端·vue.js·react.js
顽疲10 小时前
springboot vue 会员收银系统 含源码 开发流程
vue.js·spring boot·后端