尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Vue.js 从入门到实战:环境搭建、核心概念与工程化指南

Vue.js 从入门到实战:环境搭建、核心概念与工程化指南 1. 从“Hello World”到构建现代前端应用为什么是Vue如果你刚踏入前端开发的大门或者是从 jQuery 时代一路走来的开发者面对如今 React、Vue、Angular 三大框架的“神仙打架”可能会感到一丝迷茫。我最初接触 Vue 时也是抱着试试看的心态但很快就被它的“渐进式”理念和上手速度所吸引。简单来说Vue 的核心价值在于它允许你从一个简单的页面交互开始平滑地演进为一个功能完整、结构清晰的大型单页应用SPA。这与一些“全家桶”式框架要求你一开始就接受其完整哲学和复杂工具链的做法截然不同。看看那些热搜词“vue安装及环境配置”、“vue项目实战”、“vue面试题”……这恰恰反映了 Vue 生态的两个核心面向极低的学习曲线和强大的企业级应用能力。新手关心如何快速跑起来而资深开发者则关注性能优化、架构设计和工程化实践。Vue 通过其清晰的核心库只关注视图层和灵活可选的官方配套工具如 Vue Router、Vuex/Pinia、Vite成功地覆盖了这两个群体。当你用{{ message }}在页面上渲染出第一个变量时你已经踏入了响应式数据绑定的世界而当你开始用单文件组件.vue文件组织代码并搭配 Vue Router 管理路由时你已经在构建一个现代化前端应用的路上。2. 环境搭建与第一个Vue应用不只是“npm install”很多教程会把环境搭建一笔带过但这里恰恰是新手容易卡住的地方。我们避开复杂的祖传历史直接从现代工具链开始。2.1 核心工具选型Node.js、包管理器与构建工具首先你需要 Node.js 运行环境。这不是因为 Vue 本身依赖 Node.js运行时并不依赖而是因为现代前端开发离不开 npm或 yarn、pnpm这个包管理工具以及像 Vite 这样的构建工具。去 Node.js 官网下载 LTS长期支持版本安装即可。包管理器我强烈推荐pnpm。相比 npm 和 yarnpnpm 通过硬链接和符号链接的方式存储依赖能极大节省磁盘空间并且安装速度更快能有效避免“幽灵依赖”问题。安装完 Node.js 后可以通过 npm 全局安装 pnpmnpm install -g pnpm。接下来是构建工具。官方推荐并已默认使用的是Vite。它是一个基于原生 ES 模块的构建工具开发服务器启动速度极快热更新HMR效率也远超传统的 Webpack。对于新手而言你不需要理解其底层原理只需要享受它带来的流畅开发体验。2.2 创建项目的两种姿势CLI 与 手动初始化最主流、最省心的方式是使用 Vue 官方的命令行工具CLIvue/cli或更现代的create-vue。方式一使用create-vue官方推荐这是基于 Vite 的下一代项目脚手架。打开终端执行pnpm create vuelatest这条命令会下载并执行create-vue启动一个交互式的项目创建向导。你会被询问一系列问题项目名称是否添加 TypeScript 支持对于新手可以先选 No但强烈建议后期学习并引入是否添加 JSX 支持通常用于需要灵活渲染逻辑的组件初期可不选是否添加 Vue Router 进行单页面应用开发建议选 Yes这是构建 SPA 的核心是否添加 Pinia 进行状态管理对于简单应用可不选中大型应用建议选 Yes是否添加测试工具如 Vitest、Cypress可根据需要选择是否添加 ESLint 用于代码规范建议选 Yes保持代码风格统一向导结束后按照提示进入项目目录安装依赖并启动开发服务器cd your-project-name pnpm install pnpm dev此时访问http://localhost:5173Vite 默认端口你就看到了你的第一个 Vue 应用。方式二手动初始化用于深入理解如果你想知道一个最简 Vue 项目是如何组成的可以手动创建新建一个项目文件夹初始化package.jsonpnpm init -y。安装 Vuepnpm add vue。安装 Vite 及 Vue 插件pnpm add -D vite vitejs/plugin-vue。创建vite.config.js文件配置 Vue 插件。创建index.html作为入口通过script typemodule引入你的主 JS 文件。创建src/main.js或src/main.ts使用createApp函数创建 Vue 应用实例并挂载到 DOM。这种方式步骤繁琐但能让你清晰看到从零到一的过程。对于学习和调试底层问题有帮助但对于日常开发强烈推荐使用create-vue。注意很多教程会提到 Vue CLIvue/cli它基于 Webpack功能强大且成熟但配置相对复杂启动和热更新速度不如 Vite。对于新项目除非有特定的 Webpack 生态依赖否则无脑选择 Vite create-vue是更优解。2.3 理解项目结构文件与职责使用create-vue创建的项目其核心结构如下your-project/ ├── node_modules/ # 项目依赖包 ├── public/ # 静态资源如图标会被直接复制到构建输出目录 ├── src/ # 源代码目录 │ ├── assets/ # 模块化资源如图片、样式会经过构建处理 │ ├── components/ # 可复用 Vue 组件 │ ├── views/ # 页面级组件通常与路由对应 │ ├── router/ # Vue Router 路由配置如果选择了 │ ├── stores/ # Pinia 状态管理仓库如果选择了 │ ├── App.vue # 应用根组件 │ └── main.js # 应用入口文件 ├── index.html # 页面模板Vite 注入构建后的资源 ├── package.json # 项目依赖和脚本配置 ├── vite.config.js # Vite 构建配置文件 └── ... # 其他配置文件如 ESLint, .gitignore关键文件解读index.html这是应用的“壳”div idapp/div是 Vue 应用的挂载点。注意Vite 环境下你可以直接使用 ES 模块语法引入src/main.js。src/main.js应用入口。这里使用createApp工厂函数从根组件App.vue创建应用实例并调用.mount(‘#app’)将其挂载到 DOM 上。如果配置了路由或状态管理也会在这里进行安装。src/App.vue根组件。它是所有其他组件的容器通常包含顶层的布局如导航栏和router-view用于渲染当前路由对应的页面组件。3. Vue 核心概念深度解析不止于模板语法很多人学 Vue 是从模板语法开始的这没错但理解其背后的响应式原理和组件化思想更为关键。3.1 声明式渲染与响应式系统数据如何驱动视图Vue 的核心是一个响应式系统。我们通过一个简单的例子来看template div p{{ message }}/p button clickreverseMessage反转消息/button /div /template script setup import { ref } from vue; const message ref(Hello Vue!); function reverseMessage() { message.value message.value.split().reverse().join(); } /script{{ message }}这是“Mustache”语法双大括号用于数据绑定。它告诉 Vue这里需要显示message的值。ref(‘Hello Vue!’)ref函数创建一个响应式引用。它接收一个内部值返回一个响应式的、可变的 ref 对象该对象只有一个.value属性指向这个内部值。在模板中Vue 会自动“解包” ref所以我们直接写{{ message }}而不是{{ message.value }}。但在 JavaScript 中我们需要通过.value来访问或修改它。click“reverseMessage”是v-on指令的简写用于监听 DOM 事件。这里监听了按钮的点击事件并调用reverseMessage方法。当我们点击按钮reverseMessage函数修改了message.value。由于message是一个响应式 refVue 能够追踪到这个变化并自动更新所有依赖message的 DOM 部分即那个p标签。这就是“数据驱动视图”。为什么是ref和reactiveVue 3 提供了两种创建响应式数据的主要 APIref和reactive。ref常用于定义基本类型字符串、数字、布尔值的响应式数据也可以定义对象或数组。它返回一个带有.value属性的对象。在模板中自动解包在 JS 中需要.value访问。reactive用于定义对象类型包括数组的响应式数据。它返回一个原始对象的 Proxy 代理。访问和修改属性可以直接像普通对象一样操作无需.value。选择建议定义单个的、独立的基本类型数据用ref。定义一组逻辑上相关联的数据如表单对象、配置对象用reactive。在组合式函数Composables中返回响应式数据时通常使用ref因为它更容易在解构后保持响应性。3.2 条件渲染与列表渲染v-if与v-for的细节条件渲染v-ifvsv-showv-if是“真正的”条件渲染。它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if也是惰性的如果在初始渲染时条件为假则什么也不做直到条件第一次变为真时才会开始渲染条件块。v-show就简单得多——不管初始条件是什么元素总是会被渲染并且只是简单地基于 CSS 的display属性进行切换。如何选择如果需要非常频繁地切换使用v-show较好因为切换开销小只是修改 CSS。如果在运行时条件很少改变或者需要确保条件块内的组件状态被销毁/重建则使用v-if更合适。列表渲染v-forv-for指令基于一个数组或对象来渲染一个列表。必须使用:key这个特殊的 attribute 来给每个节点提供一个唯一的标识。template ul li v-foritem in items :keyitem.id {{ item.text }} /li /ul /template:key是必须的。它帮助 Vue 识别每个节点的身份从而重用和重新排序现有元素。key的值必须是唯一标识符理想情况下是数据项本身的唯一 ID如item.id。切勿使用数组索引index作为key除非你渲染的列表是静态的永不重新排序或过滤否则会导致渲染错误和性能问题。v-for和v-if避免在同一节点上使用。因为v-for的优先级比v-if更高这意味着v-if将分别重复运行于每个v-for循环中可能不是你想要的。如果目的是有条件地跳过循环的执行可以将v-if置于外层元素或template标签上。3.3 计算属性与侦听器何时用哪个这是 Vue 响应式系统中处理衍生数据的两大利器。计算属性 (computed) 用于声明式地描述一个依赖其他响应式数据的值。计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。script setup import { ref, computed } from vue; const firstName ref(张); const lastName ref(三); // 计算属性 const fullName computed(() { return firstName.value lastName.value; }); // 当 firstName 或 lastName 改变时fullName 会自动更新 /script使用场景当你需要根据一个或多个响应式数据计算出一个新的值并且这个计算可能比较耗时或者你希望缓存结果时。侦听器 (watch和watchEffect) 用于在响应式数据变化时执行有“副作用”的代码如发起异步请求、操作 DOM、打印日志等。watch需要明确指定要侦听的数据源和一个回调函数。它更精确可以获取变化前后的值。script setup import { ref, watch } from vue; const question ref(); const answer ref(); // 侦听一个 ref watch(question, async (newQuestion, oldQuestion) { if (newQuestion.includes(?)) { answer.value 思考中...; try { // 模拟异步请求 const res await fetch(https://yesno.wtf/api); const data await res.json(); answer.value data.answer; } catch (error) { answer.value 错误 error.message; } } }); /scriptwatchEffect立即运行一个函数同时响应式地追踪其依赖并在依赖变更时重新执行。你不需要明确指定侦听源它会自动追踪回调函数中用到的所有响应式属性。script setup import { ref, watchEffect } from vue; const count ref(0); watchEffect(() { console.log(count 的值是${count.value}); // 这里如果还使用了其他 ref也会被自动追踪 }); // 立即打印 “count 的值是0” /script如何选择如果你需要在数据变化时执行异步操作或开销较大的操作并需要基于变化前后的值进行逻辑处理用watch。如果你需要根据一些响应式状态自动应用副作用并且不关心具体是哪个属性变了或者副作用依赖多个属性用watchEffect更简洁。一个重要的区别watch是惰性的默认不会在侦听器创建时立即执行回调除非你设置{ immediate: true }。而watchEffect会立即执行一次。4. 组件化开发构建可复用的砖块组件是 Vue 应用的基石。理解如何创建、使用和通信组件至关重要。4.1 单文件组件 (SFC).vue文件的魔法一个.vue文件单文件组件将模板、逻辑和样式封装在一个文件中这是 Vue 的标志性特性。!-- MyComponent.vue -- template div classmy-component h2{{ title }}/h2 slot/slot !-- 插槽用于接收父组件传入的内容 -- /div /template script setup // 使用 script setup 语法糖更简洁 import { defineProps } from vue; // 定义组件接收的属性 const props defineProps({ title: { type: String, required: true } }); /script style scoped /* scoped 属性使样式仅作用于当前组件 */ .my-component { border: 1px solid #ccc; padding: 1rem; } /styletemplate包含组件的 HTML 模板。所有 Vue 指令和绑定在这里生效。script setup使用组合式 API 的编译时语法糖。在这个标签内声明的顶级变量、函数、import 都会自动暴露给模板。defineProps、defineEmits等编译器宏无需导入即可使用代码非常简洁。style scoped带scoped的 CSS。Vue 会通过给元素添加唯一属性如>!-- 父组件 Parent.vue -- template ChildComponent :user-namename :ageuserAge / /template script setup import ChildComponent from ./ChildComponent.vue; import { ref } from vue; const name ref(李四); const userAge ref(25); /script!-- 子组件 ChildComponent.vue -- template div姓名{{ userName }} 年龄{{ age }}/div /template script setup defineProps({ userName: String, age: Number }); /script注意Props 是只读的。子组件不应该直接修改接收到的 prop。如果子组件需要基于 prop 的值做出改变应该定义一个本地的 data property 或计算属性。2. 子传父自定义事件 (Emits)子组件通过触发自定义事件将数据传递回父组件。父组件监听这些事件并做出响应。!-- 子组件 ChildComponent.vue -- template button click$emit(enlarge-text, 0.1)放大文字/button !-- 或者在 script setup 中定义 -- button clickhandleClick另一种方式/button /template script setup // 定义组件可以触发的事件 const emit defineEmits([enlarge-text]); function handleClick() { emit(enlarge-text, 0.2); // 触发事件并传递参数 } /script!-- 父组件 Parent.vue -- template ChildComponent enlarge-textonEnlargeText / p :style{ fontSize: postFontSize em }一段文字/p /template script setup import { ref } from vue; import ChildComponent from ./ChildComponent.vue; const postFontSize ref(1); function onEnlargeText(enlargeAmount) { postFontSize.value enlargeAmount; } /script3. 跨层级组件通信Provide / Inject对于深度嵌套的组件如果层层传递 props 非常麻烦。这时可以用provide和inject。一个父组件相对于其所有的后代组件可以作为依赖提供者。任何后代组件无论层级多深都可以注入由父组件提供的依赖。!-- 祖先组件 Ancestor.vue -- script setup import { provide, ref } from vue; const theme ref(dark); provide(theme, theme); // 提供响应式数据 /script!-- 深层后代组件 Descendant.vue -- script setup import { inject } from vue; const theme inject(theme); // 注入 // 现在可以使用 theme.value 了 /script提示为了确保注入方和提供方之间的数据流向清晰最好将provide的值设置为一个响应式对象如ref或reactive这样后代组件注入后当提供方的数据变化时注入方也能响应式地更新。对于应用级的全局状态如用户信息更推荐使用专门的状态管理库 Pinia。4.3 插槽 (Slots)内容分发的艺术插槽让组件变得更加灵活允许父组件向子组件模板的指定位置插入任意内容。默认插槽子组件中用slot/slot定义占位符父组件传入的内容会替换它。具名插槽子组件中定义多个带名字的插槽slot name“header”父组件使用template v-slot:header或#header来指定内容插入哪个插槽。作用域插槽子组件可以将自身的数据通过插槽的 attribute 传递给父组件父组件在插槽内容中使用这些数据。这是实现可复用渲染逻辑的强力工具例如用于封装数据获取和遍历逻辑的列表组件。!-- 子组件 FancyList.vue -- template ul li v-foritem in items :keyitem.id !-- 将 item 对象作为 slotProps 传递出去 -- slot nameitem :itemitem{{ item.defaultText }}/slot /li /ul /template script setup defineProps({ items: Array }); /script!-- 父组件使用 -- template FancyList :itemsitems !-- 接收子组件传递的 slotProps命名为 props -- template #itemprops div classfancy-item {{ props.item.text }} - 来自父组件的渲染 /div /template /FancyList /template5. 路由与状态管理构建单页应用 (SPA) 的骨架当应用变得复杂多个视图和共享状态的管理就提上日程。5.1 Vue Router管理你的页面视图Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成让构建单页应用变得轻而易举。基本配置 在src/router/index.js中import { createRouter, createWebHistory } from vue-router; import HomeView from ../views/HomeView.vue; const routes [ { path: /, // 路径 name: home, // 路由名称可用于编程式导航 component: HomeView // 对应的组件 }, { path: /about, name: about, // 路由级代码分割生成一个单独的 chunk component: () import(../views/AboutView.vue) }, { path: /user/:id, // 动态路由参数 name: user, component: () import(../views/UserView.vue), props: true // 将路由参数 params.id 作为 prop 传递给组件 } ]; const router createRouter({ history: createWebHistory(import.meta.env.BASE_URL), // 使用 HTML5 History 模式 routes }); export default router;History 模式 vs Hash 模式createWebHistory使用 HTML5history.pushStateAPIURL 看起来更干净如example.com/about。但需要服务器配置支持确保所有路径都返回index.html。createWebHashHistory使用 URL hash如example.com/#/about无需服务器额外配置但 URL 中有#不太美观。动态路由匹配路径中的冒号:标记动态段如:id。在组件中可以通过$route.params.id访问或者如果设置了props: true可以直接通过defineProps([‘id’])接收。编程式导航除了使用router-link组件还可以在 JS 中使用router.push(‘/about’)或router.push({ name: ‘user’, params: { id: 123 } })进行导航。导航守卫用于在路由跳转前、后或跳转过程中进行控制。例如可以在全局前置守卫router.beforeEach中进行用户身份验证。5.2 Pinia新一代的状态管理Vuex 曾是 Vue 的官方状态管理库但 Vue 3 时代更推荐使用Pinia。它更简洁类型支持更好且与组合式 API 配合得天衣无缝。核心概念Store一个保存状态和业务逻辑的实体。每个 Store 都是独立的。StateStore 中保存的响应式数据。Getters相当于 Store 的计算属性用于派生状态。Actions相当于组件中的 methods用于封装业务逻辑可以是异步的。创建一个 Store(src/stores/counter.js)import { defineStore } from pinia; import { ref, computed } from vue; // defineStore 的第一个参数是 Store 的唯一 ID export const useCounterStore defineStore(counter, () { // State const count ref(0); // Getter const doubleCount computed(() count.value * 2); // Action function increment() { count.value; } async function fetchData() { // 异步 action const response await fetch(/api/data); // ... 更新 state } return { count, doubleCount, increment, fetchData }; });在组件中使用template div pCount: {{ store.count }}/p pDouble: {{ store.doubleCount }}/p button clickstore.increment()1/button /div /template script setup import { useCounterStore } from /stores/counter; const store useCounterStore(); // 或者使用解构但为了保持响应性需要使用 storeToRefs // import { storeToRefs } from pinia; // const { count, doubleCount } storeToRefs(store); /scriptPinia 的 Store 可以直接在组件中像使用一个组合式函数一样使用非常直观。状态修改的逻辑集中在 Store 的 Actions 中使得组件逻辑更清晰也便于复用和测试。6. 工程化、性能与进阶实践掌握了核心概念和基本开发流程后要写出健壮、可维护的应用还需要关注工程化和性能。6.1 代码组织与风格指南随着项目变大统一的代码风格和结构至关重要。使用 ESLint Prettier在创建项目时选择它们。ESLint 负责检查代码质量问题Prettier 负责代码格式化。配置保存时自动格式化能极大提升团队协作效率。组件命名多单词命名如UserProfile避免与 HTML 元素冲突。单文件组件文件名使用 PascalCase大驼峰如MyComponent.vue。Props 定义尽量使用对象形式定义类型和默认值增加可读性和健壮性。目录结构按功能而非类型组织文件。例如将某个功能相关的组件、Composable、Store 放在同一个功能文件夹下而不是把所有组件都扔进一个巨大的components目录。6.2 性能优化要点列表渲染 Key重申一遍为v-for设置唯一且稳定的key这是 Vue 高效更新虚拟 DOM 的基础。计算属性缓存对于依赖其他响应式数据且计算成本较高的值务必使用computed进行缓存。避免不必要的组件渲染使用v-once渲染静态内容对于复杂组件如果其 props 在父组件更新时未变化可以使用v-memoVue 3.2或手动实现shouldComponentUpdate逻辑通过组合式 API 的watch和条件渲染。异步组件与路由懒加载使用defineAsyncComponent或路由配置中的component: () import(‘…’)来分割代码实现按需加载减少初始包体积。合理使用ref和reactive对于不需要响应式的数据不要用它们包裹减少不必要的依赖追踪开销。侦听器的清理在组件卸载前如果使用了watch或watchEffect侦听了外部资源如定时器、事件总线、DOM 事件记得在组件的生命周期钩子onUnmounted中清理它们防止内存泄漏。6.3 组合式 API (Composables) 封装这是 Vue 3 组合式 API 的精髓所在。你可以将可复用的响应式逻辑抽取为“组合式函数”。// src/composables/useMouse.js import { ref, onMounted, onUnmounted } from vue; export function useMouse() { const x ref(0); const y ref(0); function update(event) { x.value event.pageX; y.value event.pageY; } onMounted(() window.addEventListener(mousemove, update)); onUnmounted(() window.removeEventListener(mousemove, update)); return { x, y }; }在组件中使用script setup import { useMouse } from /composables/useMouse; const { x, y } useMouse(); /script template 鼠标位置{{ x }}, {{ y }} /template通过这种方式可以像搭积木一样组合各种功能逻辑极大提高了代码的复用性和可维护性。这也是解决“Vue 与 React 算法对比”这类问题的关键——Vue 的组合式 API 提供了与 React Hooks 类似的能力但在依赖追踪和心智模型上有所不同避免了 Hooks 的闭包陷阱和调用顺序限制。7. 常见问题与避坑指南这里汇总了开发中高频出现的问题和容易踩的坑。7.1 响应式数据更新了视图为什么不更新这是新手最常见的问题根本原因在于你修改数据的方式没有触发 Vue 的响应式系统。对于reactive对象直接给整个对象重新赋值会丢失响应性。state newObject❌正确做法是修改属性state.someProp newValue✅或者使用Object.assign(state, newObject)来合并属性。直接通过索引设置数组项或修改数组长度不会触发视图更新arr[0] newValue❌arr.length 0❌。正确做法是使用数组的变更方法push,pop,shift,unshift,splice,sort,reverse或使用arr.splice(0, 1, newValue)。对于ref在 JS 中操作时务必通过.value属性。count 5❌count.value 5✅。对于从reactive或ref中解构出来的基本类型值它们会失去响应性。如果需要解构并保持响应性请使用toRefs或toRef。import { reactive, toRefs } from vue; const state reactive({ a: 1, b: 2 }); // 错误解构后 a, b 不再是响应式 // let { a, b } state; // 正确使用 toRefs let { a, b } toRefs(state); // 现在 a.value, b.value 是响应式的7.2 生命周期钩子使用时机组合式 API 的生命周期钩子需要显式导入并以onXxx的形式在setup中同步调用。script setup import { onMounted, onUpdated, onUnmounted } from vue; onMounted(() { // 组件挂载后执行适合操作 DOM、发起异步请求、订阅事件 console.log(组件挂载了); }); onUpdated(() { // 组件更新后执行小心无限循环 console.log(组件更新了); }); onUnmounted(() { // 组件卸载前执行必须清理副作用如清除定时器、取消事件监听、取消未完成的网络请求。 console.log(组件即将卸载); }); /script重要提示onMounted不会保证所有子组件也都挂载完毕。如果需要等待整个视图都渲染完毕可以在nextTick中操作。在onUpdated中修改响应式状态可能导致无限更新循环务必小心。清理副作用是必须的在onUnmounted中清理在onMounted或setup中创建的订阅、事件监听器、定时器等是防止内存泄漏的关键。7.3 开发与调试工具Vue Devtools浏览器扩展是开发 Vue 应用的必备神器。它可以检查组件树、查看组件状态和 props、追踪事件、进行时间旅行调试等。确保在开发环境中正确安装和启用。Vite 热更新 (HMR)Vite 提供了极快的热更新。但有时你可能遇到热更新失效的情况通常是因为代码语法错误导致 HMR 更新失败。状态管理库如 Pinia的 Store 不是通过defineStore定义的导致 HMR 无法识别。某些特殊的代码模式可能超出了 Vite 的 HMR 处理范围。可以尝试手动刷新页面。7.4 部署上线注意事项构建命令运行pnpm run build或npm run buildVite 会在项目根目录生成一个dist文件夹里面是优化和压缩后的静态资源。路由 History 模式如果使用了createWebHistory你需要配置生产服务器将所有非静态文件请求重定向到index.htmlFallback。对于 Nginx配置如下location / { try_files $uri $uri/ /index.html; }公共路径 (publicPath)如果项目不是部署在域名的根路径下例如https://example.com/my-app/需要在vite.config.js中配置base: ‘/my-app/’。环境变量使用.env文件管理不同环境开发、生产的变量。以VITE_开头的变量会在构建时被静态替换并可以通过import.meta.env.VITE_XXX在客户端代码中访问。敏感信息切勿放在客户端可访问的环境变量中。从“Hello World”到构建一个结构清晰、性能良好的 Vue 应用这条路需要一步步扎实地走。Vue 的优雅和渐进性让它成为前端入门和进阶的绝佳选择。关键在于多动手从一个小项目开始逐步引入路由、状态管理、组合式函数在实践中去理解和解决遇到的问题。遇到报错时仔细阅读控制台信息善用 Vue Devtools 进行调试大部分问题都能找到答案。
返回列表