Vue 3 入门指南
-
什么是vue
Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。
-
单页面(SPA)和多页面(MPA)的介绍
1)单页面应用: SPA是指整个应用只有一个HTML文件,所有页面内容都包含在这个HTML文件中,但页面之间的跳转仅刷新局部资源,
①其优点包括用户体验好(因为不需要重新加载整个页面)②更好的性能(通过缓存和懒加载技术),以及前后端分离的开发模式,便于维护和升级,
①其缺点包括SEO不友好(因为只有一个HTML文件),②首屏加载可能较慢,以及浏览器兼容性问题。
多页面应用。MPA是指每个页面对应一个HTML文件,每次页面跳转时都需要重新加载整个页面,这种应用模式通常使用后端模板引擎如JSP或Thymeleaf来生成页面,
①其优点包括更好的浏览器兼容性和SEO友好性(因为每个页面都有独立的URL),以及开发效率较高(因为每个页面是独立的),
②其缺点包括用户体验较差(每次跳转都需要重新加载页面),以及开发和维护成本较高。 -
工程创建
3.1:vue-cil 创建查看@vue/cli版本,确保@vue/cli版本在4.5.0以上
vue --version
安装或者升级你的@vue/cli
npm install -g @vue/cli
创建 项目名称为vue_test的vue3项目
vue create vue_test
启动
cd vue_test // 进入vue_test项目文件
npm run serve // 启动vue3项目
Vue cli创建项目时键盘操作无效;vue3.0项目搭建自定义配置
3.2:使用 vite 创建Vite 是一个 web 开发构建工具,由于其原生 ES 模块导入方式,可以实现闪电般的冷服务器启动。(这里不详细研究)
通过在终端中运行以下命令,可以使用 Vite 快速构建 Vue 项目。
npm 6.x
npm init vite@latest 项目文件名称 --template vue
npm 7+,需要加上额外的双短横线
npm init vite@latest 项目文件名称 – --template vue
cd 项目文件名称
npm install // 安装node依赖包
npm run dev // 启动vue3项目3.3:对比两种方式创建项目# Vue 3 的新特性
vite 优势如下:① 开发环境中,无需打包操作,可快速的冷启动。
② 轻量快速的热重载(HMR)。
③ 真正的按需编译,不再等待整个应用编译完成。传统 webpack 编译:每次执行编译时,都会通过入口 entry 先去找到各个路由,再去加载每个路由各自的模块,然后会进行打包成为 bundle.js 文件,最后才通知服务器热更新。所以换句话说就是等所有文件加载就绪之后才去渲染更新页面的==》较慢
vite 编译:与传统构建不同的是,vite 会先准备好服务器更新,再去找到入口文件然后再动态的找到需要加载的路由去编译那个路由下的模块,类似于按需加载,总体体积较小且更新更快。
Vue 3 的新特性
Vue 3 的新特性包括
- 组合式API:这是Vue 3最重要的新特性之一,它允许更灵活、更逻辑化地组织代码。
- 更好的性能:Vue 3的虚拟DOM重写,提供了更快的挂载、修补和渲染速度。
- 更小的打包大小:由于新的架构和树摇技术,Vue 3的打包大小比Vue 2小。
- 更好的TypeScript支持:Vue 3在内部使用了TypeScript,因此它为开发者提供了更好的TypeScript支持
Vue 3与Vue 2的主要区别包括:
- 构建:Vue 3使用monorepo架构,更容易管理和维护。
- API:Vue 3引入了新的组合式API,它提供了更灵活的代码组织方式。
- 性能:Vue 3提供了更好的性能,包括更快的渲染速度和更小的打包大小。
- TypeScript:Vue 3提供了更好的TypeScript支持。
-
Composition api
- 使用选项式 (option)API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 data、methods和 mounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。
// 选项式 (option)API, <template> <button @click="increment">Count is: {{ count }}</button> </template> <script> export default { // data() 返回的属性将会成为响应式的状态 // 并且暴露在 `this` 上 data() { return { count: 0 } }, // methods 是一些用来更改状态与触发更新的函数 // 它们可以在模板中作为事件监听器绑定 methods: { increment() { this.count++ } }, // 生命周期钩子会在组件生命周期的各个不同阶段被调用 // 例如这个函数就会在组件挂载完成后被调用 mounted() { console.log(`The initial count is ${this.count}.`) } } </script>
- Composition api 组合api 就是把选项api组合起来 方便管理、并且还能把某些功能单独剥离成一个文件来复用、组合api其实就是需要使用setup函数!
- 可以更加优雅的组织的代码,函数。让相关功能的代码更加有序的组织在一起,更加有逻辑性可读性
script setup 中的导入和顶层变量/函数都能够在模板中直接使用。
<template> <button @click="increment">Count is: {{ count }}</button> </template> <script setup> import { ref, onMounted } from 'vue' // 响应式状态 const count = ref(0) // 用来修改状态、触发更新的函数 function increment() { count.value++ } // 生命周期钩子 onMounted(() => { console.log(`The initial count is ${count.value}.`) }) </script>
- setup 函数
- 使用变量 或者事件 需要把名字 return 出去即可在模板中使用。
export default { setup() { let name = 'zhang' function at() { console.log(1) } return { name, at, } }, }
- 使用变量 或者事件 需要把名字 return 出去即可在模板中使用。
// 若返回一个渲染函数:则可以自定义渲染内容 import { h } from 'vue' export default { setup() { return () => h('h1', '你好') }, }
注意 vue3 虽然可以向下兼容 vue2,但是尽量不能混合使用。
Vue2.x 配置(data、methos、computed…)中可以访问到 setup 中的属性、方法
但是由于 setup 中没有 this,所以 setup 中没办法读取 Vue2.x 配置中的数据和方法
如果有重名, setup 优先setup 的注意点
数问题 setup 接收 2 个参数
setup 执行的时机是最早的,在 beforeCreate 之前执行,所以此时 this 是 undefined 参// 在子组件中 export default { props: ['msg', 'school'], emits: ['hello'], setup(props, context) { // props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。 // props接收props配置项中的相应式数据{msg:'',school:''} // context相当于上下文对象,里面有三个值attrs,slots,emit // attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 ```this.$attrs```。 // slots: 收到的插槽内容, 相当于 ```this.$slots```。 // emit: 分发自定义事件的函数, 相当于 ```this.$emit``` //方法 function test() { // 调用父组件方法 context.emit('hello', 666) } return { test, } }, }
-
Teleport
Teleport 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。
应用场景:
一个组件模板的一部分在逻辑上从属于该组件,但从整个应用视图的角度来看,它在 DOM 中应该被渲染在整个 Vue 应用外部的其他地方。
主要解决的问题 因为Teleport节点挂载在其他指定的DOM节点下,完全不受父级style样式影响
- 通过to 属性 插入指定元素位置 to=“body” 便可以将Teleport 内容传送到指定位置
接收一个 to prop 来指定传送的目标。to 的值可以是一个 CSS 选择器字符串,也可以是一个 DOM 元素对象。这段代码的作用就是告诉 Vue“把以下模板片段传送到 body 标签下”。<button @click="open = true">Open Modal</button> <Teleport to="body"> <div v-if="open" class="modal"> <p>Hello from the modal!</p> <button @click="open = false">Close</button> </div> </Teleport>
注: 挂载时,传送的 to 目标必须已经存在于 DOM 中。理想情况下,这应该是整个 Vue 应用 DOM 树外部的一个元素。如果目标元素也是由 Vue 渲染的,你需要确保在挂载 之前先挂载该元素。 - 禁用 Teleport
通过对 动态地传入一个 disabled prop 来处理这两种不同情况。将一个组件当做1:浮层来渲染,2:当作行内组件来渲染
使用disabled 设置为 true则 to属性不生效 false 则生效 (默认 false)<teleport :disabled="true" to='body'> <A></A> </teleport>
- 也可以自定义传送位置 支持 class id等 选择器
<!-- 确保有一个具有.modal类的元素在某处 --> <div class="modal"> <!-- 这里的内容将会被Teleport传送进来 --> </div> <!-- Vue组件中使用Teleport --> <Teleport to=".modal"> <!-- 这里是你想要传送的内容 --> </Teleport>
- 多个使用场景
<!-- 确保有一个具有.modal类的元素在某处 --> <div id="modals"></div> <!-- Vue组件中使用Teleport --> <Teleport to="#modals"> <div>A</div> </Teleport> <Teleport to="#modals"> <div>B</div> </Teleport>
- Fragments
-
Fragments 是什么?
在传统的 Vue 2 中,如果我们想渲染多个子元素,写多个根元素会报错,通常需要使用一个包裹元素来包含这些子元素。<template> <div> <h1>标题</h1> <p>正文内容</p> <button>点击我</button> </div> </template>
vue3引入了Fragments, 模板中可以存在多个根元
<template> <div><div> <div><div> <div><div> </template>
-
Fragments 的优势
-
简洁性
Fragments 允许我们在不引入多余包裹元素的情况下,组合和渲染多个子元素。这样可以减少 DOM 结构的嵌套层级,使代码更加简洁易读。 -
更好的性能
相对于使用包裹元素的方式,Fragments 可以减少不必要的 DOM 元素,从而提高渲染性能。因为在 Fragments 中,不会创建额外的 DOM 节点。 -
更好的样式控制
使用 Fragments 可以避免引入额外的包裹元素,从而减少对样式的影响。特别是在使用 CSS 布局库或者进行样式复用时,Fragments 可以提供更好的样式控制。
注意事项 在使用 Fragments 时,需要确保你的项目使用了 Vue 3 或更高版本。如果你正在使用 Vue 2
或之前的版本,是不支持 Fragments 的。另外,需要注意 Fragments 的语法使用尖括号 <> 和 </>,而不是普通的 HTML 标签 -
-
全局 API 重命名
Vue 3 中,许多全局 API 的名称被重命名,以下是一些需要注意的。- 过滤器被移除:在 Vue 3 中,过滤器已经被移除了,我们需要使用计算属性或方法来替代它们。
- 全局 API 被重命名:Vue 3 中一些全局 API 已经被重命名了,例如 Vue.filter 变成了 Vue.app.filter,Vue.directive 变成了 Vue.app.directive 等等。
- 自定义指令 API 发生变化:在 Vue 3 中,自定义指令的 API 发生了变化,我们需要使用 created 和 beforeUnmount 代替 bind 和 unbind。另外,update 方法也被移除了,我们需要使用 beforeUpdate 和 updated 代替它。
-
更好的 Tree-Shaking 支持
- Tree-Shaking是什么
Tree-Shaking最先在rollup.js中应用,后来webpack,vite。简单来说就是移除掉项目中永远不会被执行的代码(dead code),即代码虽然依赖某个模块,但只使用其中的某些功能,通过Tree-shaking,将没有使用的模块代码移除掉,削减项目的体积。- tree-shaking是依赖于ES6的模块特性,即模块必须是ESM(ES Module)。这是因为ES6模块的依
赖关系是确定的、静态的,和运行的时的状态无关,可以进行静态分析。 - tree-shaking只对使用export导出的变量生效
- tree-shaking是依赖于ES6的模块特性,即模块必须是ESM(ES Module)。这是因为ES6模块的依
import { createApp } from 'vue' import App from './App.vue' import { createStore } from 'vuex' import { createRouter, createWebHistory } from 'vue-router' const store = createStore({ state: { count: 0 } }) const router = createRouter({ history: createWebHistory(), routes: [ { path: '/', component: Home }, { path: '/about', component: About } ] }) const app = createApp(App) app.use(store) app.use(router) app.mount('#app') // 在这个例子中,我们只导入了实际使用的 createApp、createStore 和 createRouter 函数,而没有导入整个 vue 和 vue-router 库。这将使编译器能够在构建时更好地优化我们的应用程序,减少包大小和提高性能。
- Tree-Shaking是什么
-
Tree-Shaking的作用
通过Tree shaking,Vue3给我们带来的好处是:- 程序体积更小
- 程序执行时间更快
- 程序低耦合便于未来架构的优化
即 Vue 3.0的模块化系统允许你按需加载组件,只引入应用所需的部,避免将整个Vue库全部打包进应用中,从而减小了代码体积;
Vue 3.0的编译器会将模板中未被使用的部分自动优化掉。这意味着如果你的模板中有未使用的元素或指令,它们将不会出现在最终的渲染函数中,从而减少了代码的大小。
- 性能优化
Vue 3 进行了大量的性能优化,包括更快的渲染速度、更小的包大小和更少的运行时错误。这使得 Vue 3 成为了一个更快、更可靠的框架。以下是一些性能优化的具体内容:
- 使用 Proxy 替代 Object.defineProperty,提高响应式系统的性能
- 使用reactive或ref代替data中的对象,以便更有效地跟踪依赖。使用computed值代替复杂的计算表达式。
- 重构虚拟 DOM,减少了创建和比较虚拟 DOM 的开销
使用v-for时提供key属性,帮助Vue识别列表中的各个项,减少DOM更新的开销。
避免在列表渲染中使用v-if,因为这可能导致v-for处理过程中的渲染问题 - 优化组件实例初始化过程,减少了内存分配和初始化的开销
使用setup简化组件,减少模板和脚本之间的耦合。
避免创建不必要的组件实例,使用v-if而不是v-show来控制是否渲染组件。 - 工具和插件:
使用Vue Devtools进行性能分析。
使用Tree-shaking(树枝摇晃)来减少打包大小。
使用插件如Pinia管理状态,它提供更好的状态管理和更好的性能。 - 服务端渲染(SSR)优化:
使用defer属性在SSR页面中延迟加载JavaScript。
使用Webpack的output.splitChunks配置优化代码分割。 - 图像优化:
使用懒加载(如img标签的loading="lazy"属性)来提高页面加载性能。
使用Web图像优化工具来减少图片大小。 - 使用Web应用架构:
使用Vite等构建工具提升开发体验和项目构建速度。
使用持续集成和部署工具自动化部署流程。 - 性能监控和分析:
使用Performance API和其他浏览器性能分析工具来识别瓶颈。
使用Vue的nextTick或watch来优化异步更新。
- 新的组件钩子
Vue 3 中的组件钩子有一些变化。以下是一些新的组件钩子:
- onBeforeMount:在组件挂载之前调用。这个钩子在 Vue 2 中被称为 beforeMount。
- onMounted:在组件挂载之后调用。这个钩子在 Vue 2 中被称为 mounted。
- onBeforeUpdate:在组件更新之前调用。这个钩子在 Vue 2 中被称为 beforeUpdate。
- onUpdated:在组件更新之后调用。这个钩子在 Vue 2 中被称为 updated。
- onBeforeUnmount:在组件卸载之前调用。这个钩子在 Vue 2 中被称为beforeDestroy。
- onUnmounted:在组件卸载之后调用。这个钩子在 Vue 2 中被称为 destroyed。
<script lang="ts"> import { defineComponent, ref, onMounted, onUnmounted } from 'vue' export default defineComponent({ setup () { const msg = ref<number>(0) const open = ref(false) onMounted(() => { console.log('Component mounted') }) onUnmounted(() => { console.log('Component unmounted') }) return { msg, open } } }) </script> //例子中,我们使用了 onMounted 和 onUnmounted 钩子来处理组件的生命周期。在组件挂载时,onMounted 钩子会被调用,我们可以在这里执行一些初始化操作。在组件卸载时,onUnmounted 钩子会被调用,我们可以在这里清理一些资源。
- TypeScript 支持
Vue 3 提供了对 TypeScript 的原生支持,这意味着我们可以使用 TypeScript 来编写 Vue 应用程序。在使用 TypeScript 时,我们需要为 Vue 3 安装相应的 TypeScript 类型。如果您使用的是 Vue CLI 创建的项目,那么这些类型已经自动安装了。如果你使用的是其他方式创建的项目,则可以使用以下命令安装:npm install --save-dev @types/vue
<template> <div> {{ message }} </div> </template> <script setup lang="ts"> import { ref } from 'vue' let message: string = ref('hello word') </script>
- 响应式系统和模板编译器的改进
- 在 Vue.js 3版本中,响应式系统采用了 Proxy 替代了 Object.defineProperty,提高了性能和可维护性。同时,Vue.js 3版本的响应式系统也支持了嵌套对象和数组的深层监听。
- Vue.js 3版本的模板编译器也进行了改进,支持了更多的特性和指令,如 v-model 的多个参数、v-bind 的缩写语法、v-for 的模板片段等。此外,Vue.js 3版本的模板编译器还支持了标记和片段的缓存,提高了性能。