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 易错点 & 注意事项

  1. pathRewrite配置错误导致 404:最常见!如果没写'/api': '',请求会变成http://localhost:8080/api/userlist,后端接口实际是/userlist,会报 404。
  2. 端口冲突:启动时提示 “端口被占用”,修改devServer.port即可(如改成 8888)。
  3. target地址写错:确保target是后端正确地址(比如后端在另一台服务器,要写"http://192.168.1.100:8080")。

二、package.json:项目依赖与脚本管理

  package.json每个 Node.js 项目的核心文件,在 Vue 中负责管理依赖包、定义运行脚本、配置项目基本信息。我们开发中几乎每天都会用它,一定要吃透!

2.1 核心功能 1:依赖版本控制(重点!)

        项目依赖(如vuevue-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 件事:

  1. node_modules(所有依赖存放地,不提交 Git)下载依赖包。
  2. 把依赖信息写入dependencies(生产依赖)或devDependencies(开发依赖)。
  3. 更新package-lock.json(锁定版本,后面讲)。
实战示例:安装jquery
npm install jquery

执行后会看到 3 个变化:

  1. node_modules新增jquery目录。
  2. package.jsondependencies新增"jquery": "^3.6.4"(版本可能不同)。
  3. package-lock.json被更新。
补充:开发依赖 vs 生产依赖
  • 生产依赖(dependencies:项目运行时必须的(如vueaxios),用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 易错点 & 注意事项

  1. 混淆开发 / 生产依赖:把axios(生产依赖)装到devDependencies,打包后运行会报错 “Cannot find module 'axios'”。
  2. 版本号写错:如写成"vue": "3.2.x"(错误),正确是"vue": "^3.2.0",不能直接写x
  3. 忘记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 核心特性

  1. 锁定版本:记录每个依赖的精确版(如"jquery": "3.6.4",非^3.6.4)。
  2. 提交到 Git:必须提交到 Git,团队成员才能装相同依赖。
  3. 自动更新:执行npm install <新依赖>npm update时,自动更新版本记录。

3.3 易错点 & 注意事项

  1. 把它加入.gitignore:严重错误!会导致团队依赖版本混乱,.gitignore中绝不能有package-lock.json
  2. 手动修改它:不要手动编辑!它是 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

~相对路径的扩展,主要两种用法:

  1. 指向项目内相对路径:和.././类似(如import './style.css'可写成import '~/style.css',但很少用)。
  2. 指向 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

易错点:

  1. @~用反:如~@/components/HelloWorld.vue是错误的,@已指向src,两者不能叠加。
  2. @指向项目根目录:初学者易以为@指向根目录(和package.json同级),实际是指向src!引入public文件夹的图片,要用/img/logo.pngpublic打包后在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 课堂实战:组件传参

我们动手创建TestFirstView组件,实现父组件给子组件传参,加深理解。

步骤 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 易错点 & 注意事项

  1. template无跟元素:Vue 2 必须有一个根元素,否则报错;Vue 3 支持多根,但建议保留一个。
  2. 忘记注册组件:引入组件后没在components中注册,直接用会报 “Unknown custom element”。
  3. 删除<router-view/>:删除后无论访问哪个路径,都不显示组件(除写死内容),一定要保留。
  4. 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 易错点 & 注意事项

  1. 挂载元素 ID 不匹配mount('#app')要和public/index.html中的<div id="app"></div>一致,否则找不到挂载点,页面空白。
  2. 引入路径错误:如把import App from './App.vue'写成./app.vue(大小写错误),Node.js 区分大小写,会报 “找不到模块”。
  3. 忘记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 核心作用

  1. 提供挂载点<div id="app"></div>是 Vue 实例的挂载目标,Vue 组件会渲染到这里。
  2. 引入外部资源:可引入第三方 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>
    
  3. 配置元信息:设置页面标题、字符编码、响应式配置:
    <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 实战验证:模板的 “覆盖” 特性

我们做个小实验理解模板性质:

  1. 修改public/index.html#app
    <div id="app">我是模板内容,会被Vue覆盖!</div>
    
  2. 启动项目,刷新页面会发现 “我是模板内容...” 一闪而过,然后被App.vue内容替代。

这说明:

  • 浏览器先加载public/index.html,显示模板内容。
  • 再加载 JS,Vue
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐