Vue 项目核心文件详解笔记(初学者入门 & 面试必备)
Vue 项目核心文件详解笔记(初学者必备)
各位小伙伴,学习 Vue 的时候,我们最先接触的就是 Vue 项目的目录结构和核心配置文件。这篇笔记会帮我们彻底搞懂 Vue 项目中关键文件的作用、配置方法和使用技巧,涵盖从项目配置到组件渲染的全流程。有了这篇笔记,就能轻松上手 Vue 项目开发啦!
一、vue.config.js:项目配置核心文件
vue.config.js是 Vue CLI 3 及以后版本新增的可选配置文件,主要用来帮我们配置 Webpack 相关属性(比如打包目录、压缩率)和跨域访问代理。只要它放在项目根目录(和package.json同级),@vue/cli-service就会自动加载它,不用我们手动引入。
1.1 核心配置项列表
我们整理了常用配置项及作用,方便查阅:
| 配置项 | 作用说明 |
|---|---|
publicPath | 项目部署的基础路径(比如子路径部署时配置) |
outputDir | 打包后生成的目录名(默认是dist) |
assetsDir | 静态资源(js、css、img)的存放目录(相对于outputDir) |
indexPath | 生成的index.html文件名(默认是index.html) |
filenameHashing | 是否给打包后的文件加哈希值(默认true,用于缓存控制) |
lintOnSave | 是否在开发时开启 ESLint 语法检查(默认true) |
transpileDependencies | 是否转译第三方依赖(避免兼容性问题) |
productionSourceMap | 生产环境是否生成 sourceMap(默认false,关闭可减小打包体积) |
devServer | 开发服务器配置(端口、跨域代理等,重点!) |
devServer.proxy | 跨域代理配置(解决开发时的跨域问题,核心!) |
configureWebpack | 直接修改 Webpack 配置(对象或函数形式) |
chainWebpack | 链式修改 Webpack 配置(更灵活,适合精细调整) |
css相关配置 | 如css.modules(CSS 模块化)、css.loaderOptions(预处理器配置) |
1.2 实战配置:解决跨域和端口问题
开发中最常用的是配置devServer(开发服务器),比如指定端口、设置跨域代理。下面是完整示例,我们逐行解释:
// 引入Vue CLI提供的defineConfig函数,规范配置格式
const { defineConfig } = require('@vue/cli-service')
// 导出配置对象
module.exports = defineConfig({
// 转译第三方依赖:避免构建后出现未转译的ES6+语法,解决兼容性问题
transpileDependencies: true,
// 开发服务器配置
devServer: {
port: 8000, // 前端端口(可改8888、9000等,避免端口冲突)
proxy: { // 跨域代理配置(重点!)
'/api': { // 匹配所有以"/api"开头的请求(前缀可自定义,如"/api/v1")
target: 'http://localhost:8080', // 后端接口基础地址(目标服务器)
changeOrigin: true, // 开启跨域(模拟同源请求,避免浏览器拦截)
pathRewrite: { // 路径重写:去掉请求中的"/api"(核心!)
'/api': '' // 例:请求"/api/userlist" → 重写为"http://localhost:8080/userlist"
}
}
}
}
})
配置后,我们调用接口就能简化写法:
// 不用写完整地址,代理自动转发
axios.post("/api/userlist")
1.3 易错点 & 注意事项
pathRewrite配置错误导致 404:最常见!如果没写'/api': '',请求会变成http://localhost:8080/api/userlist,后端接口实际是/userlist,会报 404。- 端口冲突:启动时提示 “端口被占用”,修改
devServer.port即可(如改成 8888)。 target地址写错:确保target是后端正确地址(比如后端在另一台服务器,要写"http://192.168.1.100:8080")。
二、package.json:项目依赖与脚本管理
package.json是每个 Node.js 项目的核心文件,在 Vue 中负责管理依赖包、定义运行脚本、配置项目基本信息。我们开发中几乎每天都会用它,一定要吃透!
2.1 核心功能 1:依赖版本控制(重点!)
项目依赖(如vue、vue-router)的版本在这记录,4 种常见控制方式要区分清楚,避免版本不一致导致 bug:
| 控制方式 | 符号 | 示例 | 作用说明 | 注意事项 |
|---|---|---|---|---|
| 指定版本 | 无 | "vue": "3.2.13" | 只装指定版本,完全固定 | 适合严格控版场景,但可能错过 bug 修复版 |
波浪号~ | ~ | "vue": "~3.2.13" | 装3.2.x最新版(≥3.2.13),不更到 3.3.x(主版本 + 次版本不变) | 只更补丁版(修复 bug),兼容性高 |
插入号^ | ^ | "vue": "^3.2.13" | 装3.x.x最新版(≥3.2.13),不更到 4.x.x(主版本不变) | 主版本为 0 时(如^0.2.3),行为和~一致(开发阶段,次版本可能不兼容) |
| 最新版本 | latest | "vue": "latest" | 装依赖的最新版(无论主版本是否变化) | 风险高!可能引入不兼容更新,生产项目慎用 |
例子:
"jquery": "^3.6.4"会装 3.x.x 最新版(如 3.7.0);"jquery": "~3.6.4"只装 3.6.x 最新版(如 3.6.5)。
2.2 核心功能 2:定义运行脚本
scripts字段定义项目脚本,我们用npm run <脚本名>执行,不用输冗长命令。常见脚本示例:
{
"scripts": {
"serve": "vue-cli-service serve", // 启动开发服务器(热更新,开发用)
"build": "vue-cli-service build", // 打包项目(生成生产环境dist目录)
"lint": "vue-cli-service lint" // ESLint检查,修复语法错误
}
}
怎么用?
在终端输入对应命令:
npm run serve:启动开发服务器(默认http://localhost:8080),改代码后页面自动刷新。npm run build:打包项目,生成dist目录(压缩后的 js、css、html),可部署到服务器。npm run lint:检查并修复 ESLint 错误(如缩进、变量未定义)。
2.3 核心功能 3:添加 / 管理本地依赖
用npm install <依赖名>添加依赖,它会做 3 件事:
- 在
node_modules(所有依赖存放地,不提交 Git)下载依赖包。 - 把依赖信息写入
dependencies(生产依赖)或devDependencies(开发依赖)。 - 更新
package-lock.json(锁定版本,后面讲)。
实战示例:安装jquery
npm install jquery
执行后会看到 3 个变化:
node_modules新增jquery目录。package.json的dependencies新增"jquery": "^3.6.4"(版本可能不同)。package-lock.json被更新。
补充:开发依赖 vs 生产依赖
- 生产依赖(
dependencies):项目运行时必须的(如vue、axios),用npm install <依赖名>安装。 - 开发依赖(
devDependencies):仅开发时需要的(如ESLint),用npm install <依赖名> --save-dev安装,打包不包含。
2.4 核心功能 4:管理启动端口
除了vue.config.js,也能在scripts中指定端口:
{
"scripts": {
"serve": "vue-cli-service serve --port 8888", // 启动端口8888
"build": "vue-cli-service build"
}
}
执行npm run serve时,端口就是 8888(和vue.config.js冲突时,以vue.config.js为准)。
2.5 易错点 & 注意事项
- 混淆开发 / 生产依赖:把
axios(生产依赖)装到devDependencies,打包后运行会报错 “Cannot find module 'axios'”。 - 版本号写错:如写成
"vue": "3.2.x"(错误),正确是"vue": "^3.2.0",不能直接写x。 - 忘记
npm install:克隆项目后没执行npm install,缺少node_modules,启动会报 “找不到模块”。
三、package-lock.json:依赖版本锁定文件
很多初学者忽略这个文件,但它是 npm 5 + 的核心!用来解决package.json版本不精确的问题,确保项目在任何环境下都装完全相同的依赖。
3.1 为什么需要它?
package.json的版本可能模糊(如^3.2.13),如果不提交node_modules,别人克隆项目后执行npm install,可能装更新的补丁版(如我们用 3.2.13,别人装 3.2.15)。若补丁版有兼容问题,就会 “我这能跑,他那报错”。
而package-lock.json会精确记录每个依赖的版本、下载地址、依赖树,npm install时必按它的版本装,确保所有人依赖一致。
3.2 核心特性
- 锁定版本:记录每个依赖的精确版(如
"jquery": "3.6.4",非^3.6.4)。 - 提交到 Git:必须提交到 Git,团队成员才能装相同依赖。
- 自动更新:执行
npm install <新依赖>或npm update时,自动更新版本记录。
3.3 易错点 & 注意事项
- 把它加入
.gitignore:严重错误!会导致团队依赖版本混乱,.gitignore中绝不能有package-lock.json。 - 手动修改它:不要手动编辑!它是 npm 自动维护的,手动改会导致依赖树混乱,安装失败。
四、路径别名 @和~的区别(易混淆!)
Vue 项目中经常看到import用@或~开头,比如import HelloWorld from '@/components/HelloWorld.vue',我们彻底讲清楚两者区别!
4.1 @:指向 src 目录的绝对别名
@是 Webpack(Vue CLI 默认集成)预先配置的绝对路径别名,唯一作用是指向项目根目录下的src文件夹。
示例:
项目结构:
src/
components/
HelloWorld.vue
views/
HomeView.vue
则:
import HelloWorld from '@/components/HelloWorld.vue'≡import HelloWorld from '../components/HelloWorld.vue'(在views/HomeView.vue中引入)。import HomeView from '@/views/HomeView.vue'≡import HomeView from './views/HomeView.vue'(在router/index.js中引入)。
优点:
不用写一堆../(相对路径),层级深时更简洁(如从src/views/page1/subpage2.vue引入src/components/common/Header.vue,直接写@/components/common/Header.vue)。
4.2 ~:指向相对路径或 node_modules
~是相对路径的扩展,主要两种用法:
- 指向项目内相对路径:和
../、./类似(如import './style.css'可写成import '~/style.css',但很少用)。 - 指向 node_modules 依赖:最常用场景!引入第三方依赖的文件(如样式)时,
~让 Webpack 自动去node_modules查找。
示例:
安装bootstrap后引入 CSS:
// ~指向node_modules中的bootstrap
import '~/bootstrap/dist/css/bootstrap.min.css'
等价于:
import './node_modules/bootstrap/dist/css/bootstrap.min.css'
4.3 易错点 & 对比总结
| 符号 | 核心用途 | 示例路径 | 常见场景 |
|---|---|---|---|
@ | 指向src目录(绝对别名) | @/components/HelloWorld.vue | 引入src下的组件、视图 |
~ | 指向node_modules或相对路径 | ~/bootstrap/css/bootstrap.css | 引入第三方依赖的样式、JS |
易错点:
@和~用反:如~@/components/HelloWorld.vue是错误的,@已指向src,两者不能叠加。@指向项目根目录:初学者易以为@指向根目录(和package.json同级),实际是指向src!引入public文件夹的图片,要用/img/logo.png(public打包后在dist根目录)。
五、App.vue:所有组件的父容器 & 入口
App.vue是 Vue 项目中所有单文件组件(.vue)的父组件,相当于 “首页容器”,所有子组件(如HomeView.vue)都要通过它展示。我们无法直接访问子组件,必须通过App.vue渲染。
5.1 Vue 单文件组件(SFC)的构成
每个.vue文件(包括App.vue)都由 3 部分组成,这是 Vue 的特色:
| 标签 | 作用说明 |
|---|---|
<template> | 写 HTML 结构(只能有一个根元素,如最外层<div>) |
<script> | 写 JS 逻辑(引入组件、定义数据、方法等) |
<style> | 写 CSS 样式(scoped属性让样式只作用于当前组件,避免污染) |
基础结构示例:
<template>
<div id="app"> <!-- 根元素:Vue 2必须有一个,Vue 3支持多根,但建议保留一个 -->
<!-- 组件内容或子组件 -->
</div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'App', // 组件名
components: { HelloWorld } // 注册子组件
}
</script>
<style scoped>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
5.2 渲染子组件的两种方式
App.vue作为父容器,渲染子组件分静态渲染(固定)和动态渲染(路由切换,重点)。
方式 1:静态渲染(写死组件)
把子组件直接写在<template>中,页面固定显示,不能切换。
示例:渲染HelloWorld
<template>
<div id="app">
<!-- 使用注册好的HelloWorld组件,传参msg -->
<HelloWorld msg="Welcome to Your Vue.js App" />
</div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'App',
components: { HelloWorld } // 必须注册才能用
}
</script>
启动项目后,页面固定显示HelloWorld内容,无法切换其他组件。
方式 2:动态渲染(用<router-view/>,重点!)
实际项目需要切换页面(如首页→关于页),需用Vue Router配合<router-view/>实现动态渲染。<router-view/>是 “动态容器”,按 URL 路径渲染对应组件。
步骤 1:配置路由(router/index.js)
先在src/router/index.js中定义路由规则:
// 引入Vue Router核心函数
import { createRouter, createWebHistory } from 'vue-router'
// 引入组件
import HomeView from '../views/HomeView.vue'
import AboutView from '../views/AboutView.vue'
import Test from '../views/Test.vue'
// 路由规则
const routes = [
{
path: '/', // 路径:http://localhost:8080/
name: 'home',
component: HomeView // 渲染HomeView.vue
},
{
path: '/about', // 路径:http://localhost:8080/about
name: 'about',
// 懒加载:只有访问/about时才加载,优化首屏速度
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
},
{
path: '/test', // 路径:http://localhost:8080/test
name: 'test',
component: Test
}
]
// 创建路由实例
const router = createRouter({
history: createWebHistory(process.env.BASE_URL), // HTML5 History模式
routes
})
export default router // 导出供main.js使用
步骤 2:在App.vue中用<router-view/>
加入<router-view/>和路由链接(<router-link>):
<template>
<div id="app">
<!-- 路由链接:类似<a>标签,但不刷新页面 -->
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/test">测试页</router-link>
</nav>
<!-- 动态容器:按URL渲染组件 -->
<router-view/>
</div>
</template>
<script>
export default { name: 'App' }
</script>
效果:
- 访问
/→ 渲染HomeView.vue - 点击
About→ 渲染AboutView.vue - 点击
测试页→ 渲染Test.vue
5.3 课堂实战:组件传参
我们动手创建Test和FirstView组件,实现父组件给子组件传参,加深理解。
步骤 1:创建Test.vue(父组件,src/views下)
<template>
<div>
<h1>这是测试页面</h1>
<!-- 给子组件FirstView传参:msg="欢迎来到组件页面" -->
<FirstView msg="欢迎来到组件页面" />
</div>
</template>
<script>
// 引入子组件
import FirstView from '@/components/FirstView.vue'
export default {
name: 'Test',
components: { FirstView } // 注册子组件
}
</script>
步骤 2:创建FirstView.vue(子组件,src/components下)
接收父组件传的msg参数:
<template>
<div>
<!-- 显示msg参数 -->
<p>{{ msg }}</p>
</div>
</template>
<script>
export default {
name: 'FirstView',
props: {
// 定义参数类型:确保传参正确
msg: String
}
}
</script>
步骤 3:查看效果
启动项目后,点击测试页,页面会显示:
- 大标题 “这是测试页面”(来自
Test.vue) - 段落 “欢迎来到组件页面”(来自
FirstView.vue,通过msg传递)
5.4 易错点 & 注意事项
template无跟元素:Vue 2 必须有一个根元素,否则报错;Vue 3 支持多根,但建议保留一个。- 忘记注册组件:引入组件后没在
components中注册,直接用会报 “Unknown custom element”。 - 删除
<router-view/>:删除后无论访问哪个路径,都不显示组件(除写死内容),一定要保留。 props没定义类型:虽能显示,但会有 ESLint 警告,建议总是定义类型(如msg: String)。
六、main.js:Vue 项目的 JS 入口文件
main.js是 Vue 项目的JavaScript 入口文件,相当于 “启动器”,核心作用是初始化 Vue 实例、引入资源(组件、路由、Vuex),并把实例挂载到 HTML 指定元素上。
6.1 核心代码(Vue 3 版本)
我们逐行解释 Vue 3 项目中main.js的标准代码:
// 1. 从vue引入createApp:创建Vue应用实例
import { createApp } from 'vue'
// 2. 引入根组件App.vue
import App from './App.vue'
// 3. 引入路由实例(router/index.js导出)
import router from './router'
// 4. 引入Vuex实例(状态管理,store/index.js导出)
import store from './store'
// 5. 初始化Vue并挂载
// createApp(App):创建以App为根组件的实例
// .use(store):使用Vuex(所有组件可访问store数据)
// .use(router):使用Vue Router(所有组件可用路由功能)
// .mount('#app'):挂载到HTML中id为"app"的元素
createApp(App).use(store).use(router).mount('#app')
6.2 易错点 & 注意事项
- 挂载元素 ID 不匹配:
mount('#app')要和public/index.html中的<div id="app"></div>一致,否则找不到挂载点,页面空白。 - 引入路径错误:如把
import App from './App.vue'写成./app.vue(大小写错误),Node.js 区分大小写,会报 “找不到模块”。 - 忘记
use路由 / Vuex:引入router但没写.use(router),路由功能无效(<router-link>不工作);同理,忘use(store)无法访问 Vuex 数据。
七、public/index.html:项目的 HTML 模板
public/index.html是 Vue 项目的HTML 模板文件,也是总入口 HTML。作用是提供挂载点(#app),让main.js初始化的 Vue 实例有地方挂载,webpack 打包时会基于它生成生产环境的index.html。
7.1 核心作用
- 提供挂载点:
<div id="app"></div>是 Vue 实例的挂载目标,Vue 组件会渲染到这里。 - 引入外部资源:可引入第三方 CSS/JS(如百度统计、SDK):
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> - 配置元信息:设置页面标题、字符编码、响应式配置:
<meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue Project</title>
7.2 与 main.js 的关联:Webpack 约定
初学者会问:main.js怎么知道挂载到#app?这是 Webpack 的默认约定!
Vue CLI 内置HtmlWebpackPlugin,打包时自动把main.js的 JS 文件注入到public/index.html,并约定挂载点是#app。内部配置如下(不用我们写):
new HtmlWebpackPlugin({
filename: config.build.index, // 打包后HTML文件名(默认index.html)
template: 'index.html', // 模板路径(public/index.html)
inject: true, // 自动注入JS/CSS
minify: { // 生产环境压缩HTML
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency' // 按依赖排序JS
})
7.3 实战验证:模板的 “覆盖” 特性
我们做个小实验理解模板性质:
- 修改
public/index.html的#app:<div id="app">我是模板内容,会被Vue覆盖!</div> - 启动项目,刷新页面会发现 “我是模板内容...” 一闪而过,然后被
App.vue内容替代。
这说明:
- 浏览器先加载
public/index.html,显示模板内容。 - 再加载 JS,Vue
更多推荐


所有评论(0)