Vue.js 3 相较于 Vue.js 2.x 的改动
性能提升
Vue.js 3 在性能方面做了许多改进:
- 打包大小减少 41%:这意味着 Vue.js 3 的文件更小,更快加载。
- 内存占用减少 54%:使用 Vue.js 3 的应用程序会更节省内存。
- 初次渲染快 55%,更新渲染快 133%:页面加载和更新速度更快,更流畅。
源码升级
- 使用 Proxy 代替 Object.defineProperty:Vue.js 3 使用了更现代的 JavaScript 技术来实现响应式数据,使代码更简洁、性能更好。
- 重写虚拟 DOM 和 Tree-Shaking:重写的虚拟 DOM 提升了效率,Tree-Shaking 让代码中未使用的部分不会被打包,提高了应用性能。
TypeScript 支持优化
Vue.js 3 更好地支持 TypeScript,开发者可以更方便地使用类型检查和自动补全,减少代码错误。
新特性
-
Composition API(组合 API)
- setup 配置:一种新的函数式写法,让代码更易读和复用。
- ref 与 reactive:新的响应式 API,让管理状态变得更简单。
- watch 与 watchEffect:更灵活的监视数据变化的方法。
- provide 与 inject:让父子组件之间共享数据更方便。
-
新的内置组件
- Fragment:让你可以返回多个根节点,不用再包裹一个不必要的 div 了。
- Teleport:让你可以将内容渲染到 DOM 的其他位置。
- Suspense:处理异步组件,让你可以优雅地显示加载状态。
-
其它改变
- 新的生命周期钩子:如
onMounted
、onUpdated
等,命名更直观。 - data 选项始终声明为一个函数:确保每个组件实例都有独立的数据。
- 移除 keyCode 支持:使用更直观的键盘事件修饰符,如
v-on:keyup.enter="onPressEnter"
。
- 新的生命周期钩子:如
Vitejs
Vite 是 Vue 官方推荐的新一代构建工具,和 webpack 有很大的区别:
- 开发环境中,无需打包:Vite 可以快速启动项目,不需要打包过程。
- 轻量快速的热重载(HMR):页面变化会立即显示,不需要刷新整个页面。
- 按需编译:只编译当前需要的部分,不用等待整个应用编译完成
使用Vue-cli创建工程
创建Vue 3项目可以按照以下步骤进行:
1.确保你已经安装了Node.js和npm。你可以在终端中运行以下命令来检查是否安装了它们:
node -v
npm -v
2.如果你已经安装了npm,你可以运行以下命令来全局安装Vue CLI:
npm install -g @vue/cli
3.创建一个新的Vue 3项目,可以使用以下命令:
vue create my-project
4.在创建项目的过程中,你将会被要求选择一个预设。你可以选择默认的预设(Default)或手动选择功能(Manually select features)。如果你选择手动选择功能,你可以使用上下箭头键来选择或取消选择不同的功能。在Vue 3中,你还可以选择使用Composition API。
5.完成项目创建后,切换到项目目录中:
cd my-project
6.使用以下命令来启动开发服务器:
npm run serve
7.现在你可以在浏览器中访问 http://localhost:8080 来查看你的Vue 3项目。
这些是创建Vue 3项目的基本流程。你可以根据需要进行进一步的配置和开发。
入口文件
和之前一样,main.js是vue项目的入口文件,只是在vue3.0中,创建vm的方法有很大的变化,在2.x中,是这样创建的
import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h => h(App),
}).$mount('#app')
而在3.0中,可以通过createApp()方法来创建vm,然后使用mount()方法将它挂载到指定元素上,示例如下:
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
这是Vue 3.0中使用的新方法,与Vue 2.x相比有所变化。createApp()方法将App组件作为参数传递进去,然后使用mount()方法将它挂载到id为"app"的元素上。这个入口文件就负责创建Vue实例,并将根组件挂载到指定元素上。
组件新特性
provide和inject
provide和inject的作用就是解决父组件传值给后组件通过props传值需要一步一步往下传的痛点,provide提供的值可以在任意层级的后代中通过inject获取访问:
父组件:
<template>
<div>{{ "x is: " + x }}</div>
<computed-child />
<button @click="increase">+</button>
</template>
<script>
import ComputedChild from "./ComputedChild.vue";
import { computed } from "vue";
export default {
components: { ComputedChild },
data() {
return {
x: 0,
y: 1,
};
},
provide() {
return { x: computed(() => this.x), y: computed(() => this.y), sum:computed(() => this.x + this.y) };
},
methods: {
increase() {
this.x++;
this.y++;
},
},
created() {
window.b = this;
},
};
</script>
<style></style>
子组件:
<template>
computed-child
<div>{{ x }}</div>
<div>{{ y }}</div>
<div>{{ "sum is: " + sum.value }}</div>
</template>
<script>
export default {
inject: ["x", "y", "sum"],
};
</script>
<style></style>
为什么需要组合式 API?
在 Vue 2.x 中,组件的逻辑通常是通过选项式 API(如 data
、methods
、computed
等)来组织的。当组件变得复杂时,相关逻辑分散在不同的选项中,可能会变得难以管理。组合式 API 提供了一种将逻辑聚合在一起的方式,使代码更清晰、更易维护。
基本用法
组合式 API 的核心是 setup
函数。这个函数会在组件实例创建之前调用,并作为一个选项添加到组件中。它是组合式 API 的入口点。
<template>
<div>{{ message }}</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const message = ref('Hello Vue 3!')
return { message }
}
}
</script>
组合式 API 的主要功能
1. ref
和 reactive
ref
:用于定义一个响应式的单个值。reactive
:用于创建一个响应式对象。import { ref, reactive } from 'vue' export default { setup() { const count = ref(0) const state = reactive({ name: 'Vue', version: 3 }) return { count, state } } }
2.
computed
计算属性可以通过
computed
函数来创建,类似于 Vue 2.x 中的计算属性。
import { ref, computed } from 'vue'
export default {
setup() {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
return { count, doubleCount }
}
}
3. watch
和 watchEffect
watch
:用于监听特定数据的变化。watchEffect
:用于在响应式数据变化时执行副作用。
import { ref, watch, watchEffect } from 'vue'
export default {
setup() {
const count = ref(0)
watch(count, (newValue, oldValue) => {
console.log(`count changed from ${oldValue} to ${newValue}`)
})
watchEffect(() => {
console.log(`count is ${count.value}`)
})
return { count }
}
}
4. provide
和 inject
用于在组件树中共享数据,类似于 Vue 2.x 中的 provide
和 inject
。
import { provide, inject } from 'vue'
const ParentComponent = {
setup() {
provide('message', 'Hello from Parent')
}
}
const ChildComponent = {
setup() {
const message = inject('message')
return { message }
}
}