ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Vue3实战入门:从环境搭建到组件通信的学习路径

Vue3实战入门:从环境搭建到组件通信的学习路径 Vue3 从入门到精通最难的不是语法本身而是学习顺序。很多人一上来就啃官方文档结果在 ref、reactive、setup、defineProps 这些概念之间反复绕最后连一个页面都没写出来。这篇文章我按真实前端项目的开发顺序重新拆了一遍先搭环境再写组件再通信再路由再排查错误每一步都给出判断标准和常见坑。零基础能跟着做有 Vue2 经验的人可以直接拉到差异对比部分看。1. 先搞清楚 Vue3 到底解决了什么问题1.1 为什么很多团队从 Vue2 迁移到了 Vue3Vue3 核心解决了 Vue2 在复杂业务下逻辑复用困难、响应式性能瓶颈、TypeScript 支持不够友好这三个痛点。Vue2 用 Options API 写一个复杂页面时同一个业务逻辑代码会被拆散到 data、methods、watch、computed 四个选项里。比如一个购物车功能数据在 data 里方法在 methods 里计算逻辑可能在 computed 里它们被分散在同一个文件的不同区块逻辑复杂时阅读起来很费力。Vue3 的 Composition API 解决的就是这个问题。它允许你把同一个业务逻辑放在一起写比如购物车相关的数据、计算属性、方法可以集中在一个区块。代码组织方式从按选项类别分变成了按业务逻辑分可读性和维护性都更好。Vue3 的响应式从 Object.defineProperty 换成了 Proxy。Object.defineProperty 只能拦截对象已有的属性新增属性、删除属性、通过数组下标修改值这些在 Vue2 里要么需要额外 APIVue.set、Vue.delete要么会出现视图不更新的问题。Proxy 可以直接拦截整个对象的新增、删除、读取、赋值操作所以 Vue3 里新增属性、删除属性都是响应式的底层设计更干净。Vue3 也适合三类人正在做前端开发、需要从 Vue2 迁移的人零基础想直接学新框架的人准备面试时发现很多岗位要求 Vue3 的人。Vue2 不是不能学而是新项目基本都从 Vue3 起步招聘描述里也普遍写的是熟悉 Vue3。1.2 Vue2 和 Vue3 的核心差异这里用一张表把高频区别列出来对比维度Vue2Vue3响应式原理Object.definePropertyProxyAPI 风格Options APIComposition API 为主兼容 Options APITypeScript支持较弱原生支持更好v-model单一 v-model用 .sync 修饰符支持多个 v-model如 v-model:title全局 APIVue.use、Vue.componentapp.use、app.componentfilters 过滤器支持移除用计算属性或方法替代包体积较大Tree-Shaking 后更小插槽语法slot-scopev-slot 统一这个表格里最值得细看的是响应式差异。Vue2 的 Object.defineProperty 在初始化时递归遍历对象的属性把它转成 getter 和 setter。如果后续给对象新增一个属性Vue2 默认不知道新属性存在所以视图不会更新。Vue3 用 Proxy 包装原始对象任何属性的读取、赋值、新增、删除都会触发拦截性能开销更小行为也更符合直觉。1.3 零基础学 Vue3 的合理学习路径如果从零开始学不要按照官方文档的目录顺序走。我建议按这个顺序HTML、CSS、JavaScript 基础至少要能看懂函数、对象、数组和模板字符串。Vue3 基础语法插值、指令、事件绑定、v-if、v-for。Composition APIref、reactive、computed、watch。组件通信props、emit、v-model、provide/inject。路由Vue Router 4 的基本配置、嵌套路由、动态路由。接口请求在 setup 里使用 axios 或 fetch。项目实战做一两个后台管理页面把上面的知识点串起来。每个阶段都有很明确的验证目标第一阶段验证数据能绑定到页面第二阶段验证事件能改数据、条件能切换展示第三阶段验证依赖数据能自动计算和监听第四阶段验证父子组件能互相通信第五阶段验证多个页面之间能跳转第六阶段验证页面能从接口拿数据第七阶段验证你能独立完成一个完整功能模块。不需要背面试题先写代码遇到问题再回来查概念。2. 环境准备与第一个 Vue3 项目2.1 安装 Node.js 和包管理器创建 Vue3 项目电脑上必须有 Node.js。Vue3 加 Vite 这套组合对 Node 版本有要求一般建议直接安装 Node.js 的 LTS 版本。安装完成后打开终端Windows 用 CMD 或 PowerShellmacOS 用 Terminal执行两个命令检查node -v npm -v能输出版本号说明 Node 环境正常。npm 是 Node.js 自带的包管理器用来安装依赖。如果 npm 下载慢可以把 registry 切到国内镜像也可以先用默认源只是首次安装依赖会多等一会儿。第一次学的时候不太建议折腾镜像配置按默认流程跑通最重要。如果你用的是旧版 Node启动 Vite 时可能会提示版本太低。判断标准很简单启动命令后终端出现明确的 Node 版本不满足提示就去 Node 官网重新装一个 LTS 版本。新手不要同时保留多套 Node 环境路径冲突排查起来很麻烦。2.2 用官方脚手架创建 Vue3 项目Vue 官方推荐的创建命令是npm create vuelatest执行后命令行会提示输入项目名称然后依次询问是否安装 TypeScript、Vue Router、Pinia、Vitest 等。第一次练习时TypeScript 可以先不装这样你只需要专注 JavaScript 语法报错信息更直观。Vue Router 建议装上因为路由是核心功能后面会用到。创建完成后进入项目目录安装依赖并启动cd my-vue-app npm install npm run dev跑起来之后终端会输出本地访问地址默认通常是 http://localhost:5173 。浏览器打开后能看到 Vue3 的默认欢迎页面说明项目创建成功。如果你更习惯用 Vite 直接创建也可以npm create vitelatest my-vue-app -- --template vue两种方式本质上都是基于 Vite 的模板。官方脚手架会多出一些官方推荐的目录结构比如 views、components、assets更适合后续学习。注意创建项目时不要选太多预设。第一次练习选一个 Vue Router 就够了Pinia、ESLint、Prettier 这些等熟悉了再加否则报错排查时很容易分不清是业务问题还是工具链问题。2.3 项目目录结构认识创建成功后重点看这几个目录和文件src/main.js应用入口负责创建应用实例和挂载组件。src/App.vue根组件页面最终渲染到这个组件里。src/components存放可复用的子组件。src/views存放页面级组件配合路由使用。vite.config.jsVite 构建配置和开发服务器配置。index.htmlHTML 模板入口一般不用改。第一次看到 Vue3 工程目录不要慌只需要明白一件事所有代码都在 src 里写一个页面就是一个 .vue 文件。一个 .vue 文件包含 template、script、style 三个部分。理解这个之后就可以开始写页面了。3. 核心语法setup、ref、reactive、computed、watch3.1 setup 的两种写法和 script setupVue3 的 Composition API 核心入口是 setup 函数。在 .vue 文件里有两种写法。第一种是传统写法export default { setup() { const count ref(0) return { count } } }第二种是目前推荐的标准写法script setup import { ref } from vue const count ref(0) /scriptscript setup 是语法糖优点很明显变量不需要手动 return模板里可以直接使用组件引入后不需要额外注册。现在主流 Vue3 项目几乎都用 script setup面试题里也经常问。3.2 ref 和 reactive该用哪个ref 和 reactive 都用来定义响应式数据但它们适用的数据形态不一样ref 适合定义基本类型比如数字、字符串、布尔值也适合定义对象和数组使用时需要 .value 访问。reactive 只能定义对象和数组定义基本类型会报错使用时直接访问属性。import { ref, reactive } from vue const name ref(张三) name.value 李四 const state reactive({ count: 0 }) state.count实际开发里我的建议是能用 ref 就尽量用 ref。原因有三个ref 对数据类型的兼容性更好对象、数组、基本类型都能包。在 script setup 中ref 变量统一用 .value 赋值不会混用两种访问方式。当数据需要作为 props 传给子组件时ref 的解包行为更一致。reactive 也不是没用当你在定义多层嵌套对象且大部分场景都按属性访问时reactive 写起来更简洁。但如果你已经用了 ref就不要在同一个业务里混用两种访问方式不一致很容易出错。3.3 computed 和 watch 分开用computed 用来生成派生数据。比如页面上的总数、过滤后的列表这类值不是单独从接口拿的而是依赖现有数据计算出来的import { ref, computed } from vue const price ref(100) const count ref(2) const total computed(() price.value * count.value)computed 的特点是有缓存。只有当依赖的响应式数据变化时它才会重新计算。如果依赖没变多次访问 total 不会重复执行计算函数。这是一个容易忽略的性能优化点。watch 用来监听单组数据变化然后执行副作用。比如搜索框输入变化后触发接口请求import { ref, watch } from vue const keyword ref() watch(keyword, (newVal, oldVal) { console.log(关键词变化, newVal) // 在这里调用接口 })computed 和 watch 最容易混淆的地方是想同步拿到计算结果时用 computed想监听变化后做异步操作、写日志、请求接口时用 watch。computed 不能写异步逻辑watch 可以。3.4 在 setup 中使用 axios 请求数据很多初学者问 Vue3 里怎么用 axios。其实 axios 和 Vue 本身没有直接绑定关系它是独立的 HTTP 请求库。在 Vue3 项目里使用npm install axios然后在组件里写import { ref, onMounted } from vue import axios from axios const list ref([]) async function fetchData() { const res await axios.get(/api/list) list.value res.data.data } onMounted(() { fetchData() })需要注意两点请求接口是异步的不能在 setup 顶层直接赋值必须等接口返回后更新 list。实际项目中建议把 axios 实例封装成独立模块统一配置 baseURL、超时时间、请求拦截器和响应拦截器不要在组件里直接散落 axios。4. 组件通信props、emit、provide/inject4.1 父传子用 defineProps子组件需要接收父组件传入的数据用 defineProps 声明!-- Child.vue -- script setup defineProps({ title: String, count: Number }) /script template h3{{ title }}/h3 /template父组件里直接绑定变量script setup import { ref } from vue import Child from ./Child.vue const title ref(这是标题) /script template Child :titletitle / /template注意props 是单向数据流。子组件不能直接修改 props 的值正确做法是调用 emit 通知父组件修改。4.2 子传父用 defineEmits子组件需要通知父组件时用 defineEmits 声明事件名!-- Child.vue -- script setup const emit defineEmits([submit]) function handleClick() { emit(submit, { id: 1, name: 张三 }) } /script template button clickhandleClick提交/button /template父组件监听script setup import Child from ./Child.vue function handleSubmit(data) { console.log(收到子组件数据, data) } /script template Child submithandleSubmit / /template这里最容易踩的坑是事件名拼写不一致。父组件监听的是 submit子组件 defineEmits 声明的是 [submit]两者必须完全一样大小写也不能错。Vue3 官方建议事件名用 kebab-case 风格比如 update:title、on-save。v-model 在组件上的本质也是 props 加 emit。Vue3 支持在组件上用多个 v-model比如 v-model:title、v-model:content作用是让自定义组件也像表单元素一样支持双向绑定。这个能力在封装输入弹窗、筛选组件时很好用。4.3 跨层级通信用 provide/inject如果组件层级很深比如根组件到布局组件到页面组件再到子组件逐层传 props 会非常繁琐。provide/inject 可以跨层级提供数据// 根组件或任意上层组件 import { provide } from vue import { ref } from vue const user ref({ name: admin, role: manager }) provide(user, user)// 任意下层组件 import { inject } from vue const user inject(user)注意provide/inject 适合传递全局或半全局状态比如当前登录用户、主题颜色、国际化配置。如果你只是想让两个兄弟组件同步一份数据那就不是 provide/inject 的典型场景应该考虑用状态管理库 Pinia或者把数据提升到公共父组件。4.4 后台管理系统的权限首页实现思路热搜里经常出现根据权限显示不同首页之类的问题本质上是动态路由加权限判断。后台管理系统的常见做法是登录成功接口返回当前用户的角色、权限码、可访问的路由列表。通过 router.addRoute 动态注册路由。根据权限码控制菜单显示。刷新页面时从本地存储恢复权限数据避免路由丢失。这个流程涉及 Vue Router 4 的动态路由 API入门阶段只需要理解思路具体实现可以放到做后台管理项目时再深入。5. 路由、状态管理与项目实战5.1 Vue Router 4 基本配置安装 Vue Router 4npm install vue-router4在 src/router 下建 index.jsimport { createRouter, createWebHistory } from vue-router import Home from ../views/Home.vue import About from ../views/About.vue const routes [ { path: /, name: Home, component: Home }, { path: /about, name: About, component: About } ] const router createRouter({ history: createWebHistory(), routes }) export default router然后在 main.js 中注册import { createApp } from vue import App from ./App.vue import router from ./router createApp(App).use(router).mount(#app)页面跳转不要用 a 标签用 router-linkrouter-link to/首页/router-link router-link to/about关于/router-link5.2 动态路由和权限控制前面提到根据权限显示不同首页核心代码如下router.addRoute({ path: /admin, component: () import(../views/Admin.vue) })addRoute 可以在应用运行过程中动态加入路由。用户登录后根据后端返回的菜单权限遍历权限列表逐一 addRoute最后再 router.push 到目标页面。这样普通用户和管理员进入系统后看到的首屏和菜单就不同。这段逻辑听起来不复杂但实际做的时候容易遇到一个问题刷新页面后动态路由丢失。因为刷新浏览器后 Vue 应用重新初始化路由表里只有基础路由动态注册的路由没了。解决办法是在路由守卫里每次要进入页面之前检查当前用户有权限的路由是否已经注册过没有就重新注册再执行导航。这是后台管理系统经常考的点。5.3 状态管理Pinia 是 Vue3 的默认选择Vuex 在 Vue2 项目里很常见Vue3 时代官方推荐用 Pinia。Pinia 的优点是 API 简单、支持 Composition API、TypeScript 支持好。安装npm install pinia在 main.js 中使用import { createApp } from vue import { createPinia } from pinia import App from ./App.vue const app createApp(App) app.use(createPinia()) app.mount(#app)创建一个 storeimport { defineStore } from pinia export const useUserStore defineStore(user, { state: () ({ token: , role: }), actions: { setToken(token) { this.token token } } })Pinia 相比 Vuex 少了很多概念没有 mutationsactions 支持同步和异步写起来更接近普通 JavaScript。对初学者来说Pinia 是目前更合适的状态管理选择。5.4 用组件化思维拆解页面入门阶段最容易犯的错误是一上来就照着设计稿写一个大页面然后发现一个 .vue 文件有几百行代码。更合理的拆分方式先看页面有哪些可复用的区域比如筛选栏、表格、弹窗。把可复用的区域拆成组件。页面负责数据和状态管理组件负责展示和交互。组件之间通过 props 和 emit 通信。比如一个商品列表页面可以拆成 SearchBar、GoodsTable、EditDialog 三个组件。父组件保存商品列表数据和控制弹窗开关子组件只负责渲染和触发事件。这样写的好处是当弹窗内容需要修改时你只需要定位到 EditDialog.vue不会影响其他部分。6. 进阶用法与高频坑位6.1 Vue3 使用 JSX 的场景Vue3 默认用模板语法写界面但有些场景更适合用 JSX。比如动态渲染根据配置生成表单字段、封装一个高度定制化的表格列组件。Vue3 官方支持在 .jsx 或 .tsx 文件里写 JSXconst renderItem (item) { return div key{item.id}{item.name}/div }模板语法和 JSX 可以同时存在于一个项目中。对初学者来说先掌握模板语法就行JSX 可以等需要写复杂渲染函数时再补。如果面试被问到Vue3 支不支持 JSX答案是支持Vite 自带的插件提供了 JSX 编译支持。6.2 自定义指令自定义指令可以理解成对 DOM 操作的一种封装。比如页面加载后自动给输入框聚焦const vFocus { mounted: (el) el.focus() }在模板中使用input v-focus /在 script setup 中以 v 开头的变量都会被识别为自定义指令。其他常见场景有权限控制隐藏按钮、拖拽指令、点击外部关闭弹窗。自定义指令不是 Vue3 的核心知识点但它在封装公共能力时很有价值。6.3 修改组件库样式Vue3 修改 tabs 标签页样式这类问题本质是覆盖公共组件库的样式。Element Plus 这类组件库为了保持全局一致组件内部节点用了很多固定的类名和 CSS 变量。想覆盖它在 scoped 样式里要用 deep 选择器style scoped :deep(.el-tabs__item) { font-size: 14px; } /stylescoped 样式默认只作用于当前组件的 DOM。当你想覆盖子组件内部节点的样式时普通选择器选不中需要 :deep() 穿透。这是 Vue3 项目里每天都会用到的知识点。6.4 数据变了但页面没反应Vue3 里数据变了但页面没反应先不要急着找强制刷新的方法按下面顺序排查数据是不是用 ref 或 reactive 定义的还是在一个普通对象上改了属性有没有在组件外部用非响应式方式修改对象修改数据时是不是直接替换了顶层对象如果确实需要强制刷新可以用 v-if 让组件重新渲染template MyComponent v-ifshow / /template script setup import { ref, nextTick } from vue const show ref(true) function forceRefresh() { show.value false nextTick(() { show.value true }) } /script但这是临时方案更好的做法是找到数据失去响应的原因把数据处理干净。页面不更新大多数情况下是响应式数据管理的问题不是框架 bug。6.5 集成地图、播放器和导出 Word热搜里经常出现 Vue3 使用高德地图、视频播放器、导出 Word 这些问题这里统一说下定位方式Vue3 项目集成第三方库本质上和普通 JavaScript 项目没有区别。你只需要三步安装对应的 npm 包。在组件里引入对应的方法或组件。按照第三方库的文档初始化。高德地图在 Vue3 项目里常见做法是安装 amap/amap-jsapi-loader通过 loader 加载地图 SDK再初始化地图实例。视频播放器一般用 video.js 或 vue-video-player 的相关组件。导出 Word 的常用方案是 docxtemplater 配合模板文件。遇到这类问题最好的搜索方式是第三方库名 Vue3而不是问Vue3 怎么做导出 Word因为第三方库的用法是主导Vue3 只是载体。7. 实战建议与学习节奏提醒7.1 先把单条流程跑通我见过很多初学者拿到项目后第一件事就是想把整个后台管理系统的代码都跑起来结果报错后无从下手。我更建议先把单条流程跑通创建一个简单页面页面上只有一个输入框和一个按钮。输入内容后点击按钮把内容打印在页面上。再慢慢加接口请求、加路由、加组件拆分。能跑通单条流程说明你对响应式、事件、绑定这些基础语法已经掌握了。这时候再去看项目源码就不会觉得处处都是黑盒。排查报错时最忌讳的是看到一个错误就立刻改代码。先确认报错信息里提到的文件、行号和变量名再动手。7.2 遇到报错时的排查顺序Vue3 项目里常见的报错可以按这个顺序排查看浏览器控制台区分是 JS 报错、网络请求报错还是 Vue 警告。看终端里 Vite 的报错一般会指出具体文件和行号。确认文件路径和大小写。.vue 文件引入时大小写不敏感的系统可能不报错但部署到 Linux 后会出问题。确认组件是否正确注册、路由是否正确匹配。确认依赖版本。Vue3 项目要用 vue-router4、pinia2有些教程混用 Vue2 时代的依赖会导致运行时报错。如果报错信息提示Cannot read properties of undefined通常不是写错了语法而是某个对象还没有拿到数据就访问了属性。解决方法一般是先用 v-if 判断数据是否存在或者用可选链 ?. 保护访问
返回列表