【Vue3】前置知识简单概述(包括ES6核心语法,模块化ESM以及npm基础)

目录

    • [一、ES6+ 核心语法](#一、ES6+ 核心语法)
      • [1.1 解构赋值](#1.1 解构赋值)
      • [1.2 箭头函数](#1.2 箭头函数)
      • [1.3 模板字符串](#1.3 模板字符串)
      • [1.4 展开运算符 `...`](#1.4 展开运算符 ...)
      • [1.5 async / await](#1.5 async / await)
      • [1.6 可选链 `?.`](#1.6 可选链 ?.)
      • [1.7 空值合并 `??`](#1.7 空值合并 ??)
      • [1.8 Map 和 Set](#1.8 Map 和 Set)
    • [二、模块化 ESM](#二、模块化 ESM)
      • [2.1 为什么需要模块化](#2.1 为什么需要模块化)
      • [2.2 ESM 是什么](#2.2 ESM 是什么)
      • [2.3 导出语法](#2.3 导出语法)
      • [2.4 导入语法](#2.4 导入语法)
      • [2.5 动态 import](#2.5 动态 import)
      • [2.6 ESM vs CommonJS](#2.6 ESM vs CommonJS)
      • [2.7 `import { ref } from 'vue'` 完整解读](#2.7 import { ref } from 'vue' 完整解读)
    • [三、Node.js / npm 基础](#三、Node.js / npm 基础)
      • [3.1 Node.js 是什么](#3.1 Node.js 是什么)
      • [3.2 npm 和 pnpm](#3.2 npm 和 pnpm)
      • [3.3 常用命令](#3.3 常用命令)
      • [3.4 package.json 结构](#3.4 package.json 结构)
      • [3.5 版本号规则](#3.5 版本号规则)
      • [3.6 node_modules 是什么](#3.6 node_modules 是什么)
      • [3.7 一个 Vue 项目的完整启动流程](#3.7 一个 Vue 项目的完整启动流程)

一、ES6+ 核心语法

ES6 = JavaScript 的一次革命性版本更新 + 一套影响至今的现代语法规范。本质上就是js。在Vue3里有广泛使用,所以总结以下常用的写法。


1.1 解构赋值

语法:

复制代码
// 对象解构
const { 键名1, 键名2, 键名3 } = 对象

// 数组解构
const [ 变量1, 变量2, 变量3 ] = 数组

对象解构:等号右边的对象里,取出与左边同名的键,赋值给左边的变量。左边写什么键名,就去右边取什么值。

数组解构:按位置对应------第一个变量取数组第一个元素,第二个取第二个,依此类推。

详细讲解:

传统写法中,要从对象里拿几个字段出来,需要重复写 对象.字段,既啰嗦又容易写错:

javascript 复制代码
const name = user.name;
const age = user.age;
const email = user.email;   // 3 个字段就要写 3 遍 user.

解构赋值一行搞定:

javascript 复制代码
const { name, age, email } = user;

这行的意思是:从 user 对象中找到 name 这个键,把它的值赋给变量 nameageemail 同理。左边就是一个"模板",右边就是数据源,模板和数据源的结构对上就提取出来了。

更高级的用法------改名(当键名不合适时):

javascript 复制代码
const { name: userName, age: userAge } = user;
// 把 user.name 赋给变量 userName,user.age 赋给 userAge

Vue3 中无处不在:

javascript 复制代码
const { ref, computed, onMounted } = from 'vue';
// 从 vue 包里取 ref、computed、onMounted 这三个东西

const { name, age } = defineProps(['name', 'age']);
// 从 defineProps 返回的对象里取 name 和 age

const { query, push } = useRouter();
// 从 useRouter 返回的对象里取 query 和 push

1.2 箭头函数

语法:

复制代码
// 一个参数,一个表达式(省略括号和 return)
参数 => 返回值表达式

// 多个参数,一个表达式
(参数1, 参数2) => 返回值表达式

// 多个参数,多行函数体(需要写 return)
(参数1, 参数2) => {
  语句1
  语句2
  return 返回值
}

// 无参数
() => 返回值表达式

箭头函数由三部分组成:参数列表 + => + 函数体。函数体如果只有一个表达式,可以省略 {}return,这个表达式的结果自动作为返回值。

详细讲解:

箭头函数是传统函数的简写形式,但有一个重要区别------它不绑定自己的 this,this 继承自外层作用域。

javascript 复制代码
// 传统函数
const add = function(a, b) {
  return a + b;
};

// 箭头函数 ------ 完全等价
const add = (a, b) => a + b;

// 一个参数的极简形式
const double = n => n * 2;

// 无参数
const getRandom = () => Math.random();

对于 Vue3 来说,为什么箭头函数是主流?

Vue2 时代大量用 thisthis.namethis.countthis.method()。Vue3 的组合式 API(<script setup>)抛弃了 this,所有数据和函数都在顶层作用域直接访问。箭头函数不绑定 this 在这里正好------它继承外层作用域,行为自然。

javascript 复制代码
// Vue3 写法 ------ 没有 this
const count = ref(0);
const double = computed(() => count.value * 2);
function increment() {
  count.value++;
}

不用的后果:Vue3 的所有官方示例、教程、组件库源码,回调全是箭头函数。你不用这个写法,连官方文档都看不懂。


1.3 模板字符串

语法:

复制代码
`字符内容 ${JavaScript表达式} 更多字符内容`

`第一行
第二行
第三行`

用反引号 `````(键盘上数字 1 左边那个键)包裹。${} 里面可以写任何 JS 表达式(变量、函数调用、三元运算等),它的结果会被拼接到字符串中。支持直接换行,不需要写 \n

详细讲解:

传统字符串拼接的问题:

javascript 复制代码
// 传统 ------ + 号把字符串断成好几截,容易漏空格
const msg = 'Hello, ' + name + '! You are ' + age + '.';

// 模板字符串 ------ 插值符 ${} 一目了然
const msg = `Hello, ${name}! You are ${age}.`;

// 多行 HTML ------ 传统写法要用 + 和 \n
const html = '<div>\n' +
             '  <h1>' + title + '</h1>\n' +
             '  <p>' + content + '</p>\n' +
             '</div>';

// 模板字符串 ------ 直接换行,自然
const html = `
  <div>
    <h1>${title}</h1>
    <p>${content}</p>
  </div>
`;

Vue3 中动态拼接 class 名、URL、样式值:

javascript 复制代码
const btnClass = `btn btn-${variant} ${isActive ? 'btn-active' : ''}`;
const apiUrl = `https://api.example.com/v1/users/${userId}/posts`;

不用的后果:你要写大量 + 号拼接,代码又碎又容易出错(比如忘了加空格或逗号)。


1.4 展开运算符 ...

语法:

复制代码
// 展开 ------ 把数组/对象拆开放到新容器中
[...原数组, 新元素]
{...原对象, 新键: 新值}

// 剩余 ------ 把剩余元素收集成一个数组
function 函数名(固定参数, ...剩余参数数组) {}
const [第一项, 第二项, ...剩余数组] = 数组

三个点 ... 在不同位置含义不同。展开 是把已有的东西"抖开"放进去;剩余是把剩下的东西"收拢"成一个数组。

详细讲解:

展开(Spread)------ 用在赋值等号右侧,或数组/对象的字面量中:

javascript 复制代码
// 数组展开
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];
// arr2 结果是 [1, 2, 3, 4, 5]

// 对象展开
const user = { name: 'Alice', age: 25 };
const updated = { ...user, role: 'admin' };
// updated 结果是 { name: 'Alice', age: 25, role: 'admin' }
// 注意:这是建立了一个新对象,原对象 user 没有被修改

剩余(Rest)------ 用在赋值等号左侧,或函数参数位置:

javascript 复制代码
// 数组解构中的剩余
const [first, second, ...rest] = [1, 2, 3, 4, 5];
// first=1, second=2, rest=[3, 4, 5]

// 函数参数中的剩余 ------ 把多个参数收成一个数组
function logAll(...args) {
  args.forEach(arg => console.log(arg));
}
logAll('a', 'b', 'c');  // args = ['a', 'b', 'c']

Vue3 中最重要的用法------不可变更新。在 Vue 的响应式系统中,直接修改原数据可能会导致不可预期的副作用。标准做法是创建一个新对象,覆盖旧对象:

javascript 复制代码
const user = ref({ name: 'Alice', age: 25, role: 'user' });

function promoteToAdmin() {
  user.value = { ...user.value, role: 'admin' };
  // 新对象 = 把 user 原来的所有字段展开 + 覆盖 role
}

不用的后果:你写不了符合 Vue3 规范的"不可变数据更新",要么直接改出 bug,要么代码很笨重地逐字段复制。


1.5 async / await

语法:

复制代码
async function 函数名(参数) {
  try {
    const 结果1 = await Promise对象1;
    const 结果2 = await Promise对象2;
    return 最终结果;
  } catch (错误对象) {
    // 处理错误
  }
}

async 加在 function 前面,声明这个函数内部有异步操作。await 加在 Promise 对象前面,会暂停当前函数的执行,等 Promise 完成后拿到结果再继续往下走。用 try/catch 包裹 await 来捕获错误。

详细讲解:

JavaScript 中很多操作是异步的------发网络请求、读取文件、定时器。传统上用回调函数或 .then() 来处理:

javascript 复制代码
// 回调地狱 ------ 嵌套越来越多
fetchUser(id, function(user) {
  fetchPosts(user.id, function(posts) {
    fetchComments(posts[0].id, function(comments) {
      render(comments);
    });
  });
});

// Promise 链式 ------ 比回调好,但每多一步就多一个 .then()
fetchUser(id)
  .then(user => fetchPosts(user.id))
  .then(posts => fetchComments(posts[0].id))
  .then(comments => render(comments))
  .catch(err => console.error(err));

async/await 让异步代码看起来像同步一样自然:

javascript 复制代码
async function loadFullData(userId) {
  try {
    const user = await fetchUser(userId);
    const posts = await fetchPosts(user.id);
    const comments = await fetchComments(posts[0].id);
    render(comments);
  } catch (err) {
    console.error('加载失败', err);
  }
}

注意:await 会暂停当前函数,但不会阻塞整个程序------浏览器界面照常响应其他事件。这是 JS 事件循环的机制。

Vue3 中几乎所有组件初始化都需要发请求拿数据:

javascript 复制代码
onMounted(async () => {
  loading.value = true;
  try {
    const res = await api.getUserList();
    users.value = res.data;
  } catch (e) {
    error.value = e.message;
  } finally {
    loading.value = false;
  }
});

不用的后果:你在 Vue 组件中发 API 请求时,要么用 .then() 链(多一步嵌套就乱一层),要么写不出来"先拿用户 ID → 再拿用户文章 → 最后才渲染"这种有依赖关系的异步流程。


1.6 可选链 ?.

语法:

复制代码
对象?.属性
对象?.属性?.更深属性
对象?.方法?.()
数组?.[索引]

?. 前面的值是 nullundefined 时,整个表达式直接返回 undefined,不再继续访问后面的内容,也不报错。如果前面的值存在,就正常访问后面的属性。

详细讲解:

深层嵌套的对象,中间某一层可能是 nullundefined。传统写法需要每一层都做判断:

javascript 复制代码
// 传统 ------ 少写一个 && 就崩
const city = user && user.address && user.address.city;

// 可选链 ------ 一行搞定,安全
const city = user?.address?.city;

// 如果 user 是 undefined → 返回 undefined,不往后走
// 如果 user.address 是 null → 返回 undefined,不往后走
// 都正常 → 返回 user.address.city 的值

不用的后果:null.city 这种表达式会直接抛出 TypeError: Cannot read properties of null,导致整个页面白屏崩溃。特别是 API 返回的数据结构不可控时,某个字段可能不存在。

javascript 复制代码
// Vue3 模板中
<p>{{ user?.profile?.avatar?.url }}</p>
<!-- 即使 profile 或 avatar 是 null,页面照常渲染,只是不显示这段内容 -->

1.7 空值合并 ??

语法:

复制代码
可能为null或undefined的值 ?? 兜底的默认值

如果左边不是 null 也不是 undefined,返回左边;否则返回右边。

详细讲解:

??|| 看起来像,但有本质区别:

javascript 复制代码
const score = 0;

// || 会把所有"假值"都当作不存在:0、''、false、null、undefined
const a = score || 100;   // a = 100 ❌ 0 被吞了

// ?? 只认 null 和 undefined,0 是有效值
const b = score ?? 100;   // b = 0 ✅

// 同理
const name = '';
const c = name || '匿名';  // c = '匿名' ❌ 空字符串被吞了
const d = name ?? '匿名';  // d = '' ✅

什么时候用 ??:当 0''false 本身是有效值,你只希望在真正"没传"(null/undefined)时才给默认值。

javascript 复制代码
// Vue3 中 ------ 组件 props 设置默认值
const pageSize = props.pageSize ?? 20;   // 没传 pageSize 时用 20
const count = data?.total ?? 0;          // 从 API 取数据,没有就给 0

1.8 Map 和 Set

语法:

复制代码
// Set ------ 不重复值的集合
const 变量名 = new Set([初始值1, 初始值2, ...])
变量名.add(值)
变量名.has(值)
变量名.delete(值)
变量名.size

// Map ------ 键值对集合(键可以是任何类型)
const 变量名 = new Map()
变量名.set(键, 值)
变量名.get(键)
变量名.has(键)
变量名.delete(键)
变量名.size

Set 类似数组,但每个值只能出现一次(自动去重)。Map 类似对象,但键可以是对象、函数等任意类型,而不限于字符串。

详细讲解:

javascript 复制代码
// Set ------ 自动去重
const arr = [1, 2, 2, 3, 3, 3];
const unique = new Set(arr);
// unique 里面是 {1, 2, 3}
unique.size;             // 3
unique.has(2);           // true
unique.add(4);           // 添加
[...unique];             // 转回数组 [1, 2, 3, 4]

// Map ------ 键可以是对象
const userScores = new Map();
const user1 = { id: 1 };
const user2 = { id: 2 };

userScores.set(user1, 95);
userScores.set(user2, 87);

userScores.get(user1);   // 95
userScores.size;         // 2

Vue3 源码中,Map 是响应式系统的核心数据结构------用来存储"哪个数据被哪些组件/副作用依赖了"。作为初学者,知道有这两种结构即可,等以后研究源码时再深挖。


二、模块化 ESM

2.1 为什么需要模块化

假设你写了一个 formatDate 函数,在页面 A、页面 B、页面 C 中都要用:

复制代码
❌ 不模块化:三个页面各复制粘贴一遍 formatDate
       改日期格式时,三个地方都要改,漏一个就 bug

✅ 模块化:把 formatDate 写在 utils/format.js 里
       三个页面各自 import
       只改一个地方,全部生效

模块化就是一个文件可以导出自己的一部分,其他文件按需导入使用。每个文件各司其职,互不污染全局作用域。

2.2 ESM 是什么

ES Modules(ESM)是 ES6 正式纳入 JavaScript 标准的模块系统。Vue3 + Vite 项目全部使用 ESM

复制代码
写代码时:一个 .vue 文件 或 .js 文件 = 一个模块
          模块可以 export(导出)自己的代码
          其他模块可以 import(导入)这些代码

构建时:Vite 把所有 import/export 关系理清
        打包成一个或多个浏览器能识别的文件

2.3 导出语法

语法:

复制代码
// 方式一:在声明时直接导出
export const 常量名 = 值;
export function 函数名(参数) { ... }

// 方式二:在文件底部统一导出
const 常量名 = 值;
function 函数名(参数) { ... }
export { 常量名, 函数名 };

// 默认导出 ------ 一个文件最多一个
export default 值;

一个文件同时只能有一个 export default,但可以有多个 export

详细讲解:

javascript 复制代码
// ===== file: utils/math.js =====

// 命名导出 ------ 导出的东西有精确的名字
export const PI = 3.14159;
export function add(a, b) {
  return a + b;
}
export function multiply(a, b) {
  return a * b;
}

// ===== file: utils/validator.js =====

// 默认导出 ------ 不定义名字,由导入方取名
export default function validateEmail(email) {
  return email.includes('@');
}

命名导出 vs 默认导出怎么选:

命名导出 默认导出
一个文件能导几个 多个 最多一个
导入写法 import { 精确名字 } import 任意名字
IDE 自动补全 ✅ 输入名字就提示 ❌ 导入方自己取名,无法自动补全
重构时 改名自动同步到所有导入方 容易断
适用场景 工具函数、常量、多个 API 一个文件主要只导出一个东西(组件、类)
Vue 组件惯例 不常用(除非一个文件有多个组件) ✅ 最常用(一个 .vue 文件 = 一个组件)

如果一个文件主要用于提供一个东西(比如一个 Vue 组件、一个配置对象),用 export default。如果一个文件提供多个工具函数或常量,用命名导出。

2.4 导入语法

语法:

复制代码
// 导入命名导出 ------ 大括号内写要导入的具体名字,必须和导出时一致
import { 名字1, 名字2 } from '模块路径'

// 导入默认导出 ------ 不用大括号,名字自己起
import 任意名字 from '模块路径'

// 同时导入两种
import 默认导出名字, { 命名导出1, 命名导出2 } from '模块路径'

// 改名导入 ------ 避免名字冲突
import { 原名 as 新名 } from '模块路径'

// 整体导入 ------ 把模块的所有命名导出收成一个对象
import * as 对象名 from '模块路径'

详细讲解:

javascript 复制代码
// ===== file: app.js =====

// 按名字取
import { PI, add, multiply } from './utils/math.js';
console.log(add(1, 2));   // 3

// 默认导入 ------ 名字可以自己定
import validate from './utils/validator.js';
validate('test@test.com');  // true

// 改名 ------ 项目中可能有两个不同模块都导出了 formatDate
import { formatDate as fd } from './utils/a.js';
import { formatDate as displayDate } from './utils/b.js';

// 整体导入 ------ 把所有导出装进一个对象
import * as MathUtils from './utils/math.js';
MathUtils.PI;           // 3.14159
MathUtils.add(1, 2);    // 3

模块路径规则:

复制代码
import xxx from 'vue'           → 去 node_modules 找第三方包
import xxx from './xxx.js'      → 去当前文件同级的 ./xxx.js 找(本地文件)
import xxx from '@/xxx.js'      → @ 是 Vite 配置的路径别名,通常指 src/ 目录

2.5 动态 import

语法:

复制代码
const 模块对象 = await import('模块路径')

import() 是一个函数,返回 Promise。做到运行时按需加载------不需要在文件顶部提前加载,而是等到"需要的时候"才去加载。

详细讲解:

javascript 复制代码
// 静态导入 ------ 文件一执行就加载(不管后面用不用)
import { Chart } from 'heavy-chart-lib';

// 动态导入 ------ 用户点击时才加载
async function loadChart() {
  const { Chart } = await import('heavy-chart-lib');
  const chart = new Chart(container);
}

document.getElementById('btn').onclick = loadChart;

Vue3 路由懒加载的应用:

javascript 复制代码
// 常规导入 ------ 用户访问首页时就把所有页面都加载了
import Home from './views/Home.vue';
import Dashboard from './views/Dashboard.vue';
import Settings from './views/Settings.vue';

// 动态导入 ------ 只有用户访问 /dashboard 时才加载 Dashboard.vue
const Dashboard = () => import('./views/Dashboard.vue');
const Settings = () => import('./views/Settings.vue');

这样首屏加载只加载必要的代码,其他页面等用户点到时再加载,显著提升首次打开速度。

2.6 ESM vs CommonJS

CommonJS 是 Node.js 传统的模块系统(用 require / module.exports)。Vue 项目不用它,但有时候会见到(比如一些老的 Node.js 工具、配置文件),了解区别有助于不混淆。

语法对比:

javascript 复制代码
// ===== CommonJS(Node.js 传统) =====
const fs = require('fs');
const path = require('path');
module.exports = { myFunction };
exports.helper = () => {};

// ===== ESM(Vue 项目用) =====
import fs from 'fs';
import path from 'path';
export const myFunction = () => {};
export function helper() {}

本质区别:

ESM CommonJS
加载时机 编译时静态解析(代码运行前分析依赖) 运行时动态加载(执行到 require 才加载)
浏览器支持 ✅ 原生支持(现代浏览器 <script type="module"> ❌ 不支持
Tree-shaking ✅ 打包时可"摇掉"没用的代码 ❌ 不能
静态分析 ✅ 工具可以分析出导出了什么 ❌ 因为是动态的,分析不了
Vue 生态 ✅ 全部用 ESM ❌ 不用

一个文件同时看到两种语法怎么办?

javascript 复制代码
// 有时在 .config 文件中看到
module.exports = {
  // CommonJS 写法
};

// 在 .vue 和 src/ 下的 .js 中看到
import xxx from 'xxx'
export const xxx = ...

规则是:.vue 文件和 src/ 目录下的 JS 文件用 ESM。vite.config.js 等构建配置文件有时用 CommonJS(因为 Vite 内部处理了兼容)。写 Vue 组件时只用 ESM 即可。

2.7 import { ref } from 'vue' 完整解读

这句是你进入 Vue3 世界后看到的第一行代码,逐段拆开:

复制代码
import   { ref, onMounted }         from            'vue'
   ↑             ↑                   ↑                ↑
ESM 关键字    解构赋值,从          "来自哪里"      npm 包名,
(声明导入)  vue包中取出 ref                    去 node_modules
             和 onMounted 这两个                  找 vue 这个包
             命名导出

本质上就是:去 node_modules 里找到 vue 这个包,
从它的导出中取出 ref 和 onMounted 这两个东西,
赋值给当前文件的同名变量使用。

如果你没写这行,直接写 ref(0),浏览器会报错:ref is not defined


三、Node.js / npm 基础

3.1 Node.js 是什么

Node.js 是服务端 JavaScript 运行环境。Vue 项目最终在浏览器运行,但开发和构建过程依赖 Node.js。

复制代码
在终端输入 pnpm run dev
        │
        ▼
   Node.js 启动 Vite(构建工具)
        │
        ▼
   Vite 把 .vue 文件编译成浏览器能识别的
   .html + .js + .css
        │
        ▼
   打开浏览器访问 http://localhost:5173
       看到你的项目

所以 Vue 开发 = 用 Node.js 跑一个开发服务器,然后浏览器连上去。你改代码 → 服务器自动重新编译 → 浏览器自动刷新。

3.2 npm 和 pnpm

npm(Node Package Manager)是 Node.js 自带的包管理器。pnpm 是它的升级替代品,更快、更省磁盘空间。Vue 官方推荐用 pnpm,命令语法基本一样。

3.3 常用命令

语法:

复制代码
pnpm create 项目模板名    ← 用模板创建项目(如 vue@latest)
pnpm install              ← 安装 package.json 中所有依赖
pnpm add 包名             ← 安装某个包到 dependencies
pnpm add -D 包名          ← 安装某个包到 devDependencies
pnpm remove 包名          ← 卸载某个包
pnpm run 脚本名           ← 执行 package.json 中 scripts 里定义的命令

详细讲解:

bash 复制代码
# 创建一个 Vue 项目(交互式问答:项目名、是否用 TS / 路由 / Pinia 等)
pnpm create vue@latest

# 进入项目目录
cd my-vue-app

# 安装所有依赖(根据 package.json 中列出的包全部下载到 node_modules)
pnpm install

# 安装运行时依赖(项目运行必须的,打包时会包含)
pnpm add vue-router
pnpm add pinia

# 安装开发依赖(只有开发时用,打包后不包含)
pnpm add -D eslint prettier
pnpm add -D @types/node

# 运行脚本
pnpm run dev       # 启动开发服务器(热更新,改代码自动刷新)
pnpm run build     # 构建生产版本(生成 dist/ 目录,放服务器上线)
pnpm run preview   # 本地预览构建后的结果

3.4 package.json 结构

语法:

json 复制代码
{
  "name": "项目名",
  "version": "版本号",
  "private": true,
  "scripts": {
    "命令名1": "要执行的命令",
    "命令名2": "要执行的命令"
  },
  "dependencies": {
    "包名": "版本范围"
  },
  "devDependencies": {
    "包名": "版本范围"
  }
}

name:项目名称,也是 npm 包名(发布到 npm 时用)。如果不发布,加 "private": true 防止误发布。

scripts:自定义的快捷命令。pnpm run dev 就是执行这里 "dev": "vite"

dependencies:项目运行时需要的包。比如 Vue 本身、路由库、状态管理库。这些会被打包进最终文件。

devDependencies开发阶段需要的工具。比如构建工具 Vite、代码检查 ESLint、格式化 Prettier。它们不会打包进最终文件。

json 复制代码
{
  "name": "my-vue-app",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "vue": "^3.4.0",
    "vue-router": "^4.3.0",
    "pinia": "^2.1.0"
  },
  "devDependencies": {
    "vite": "^5.0.0",
    "eslint": "^8.0.0",
    "prettier": "^3.0.0"
  }
}

3.5 版本号规则

语法:

复制代码
主版本 . 次版本 . 补丁版本
  3    .   4    .    0

^3.4.0   → 接受 >=3.4.0 且 <4.0.0(自动升级次版本和补丁版本)
~3.4.0   → 接受 >=3.4.0 且 <3.5.0(只自动升级补丁版本)
 3.4.0   → 锁死,绝不自动升级
*        → 任何版本(不推荐,太不可控)
  • 主版本:大改版,API 不向下兼容(3→4 可能有破坏性变化)
  • 次版本:加新功能,向下兼容(3.3→3.4 加了东西但旧代码不受影响)
  • 补丁:修 Bug,向下兼容(3.4.0→3.4.1 只是修补)

^ 的意思是"接受兼容范围内的最新版本"------安装时如果已有 3.4.5,就装 3.4.5 而不是 3.4.0。需要锁死时必须明确写 "vue": "3.4.0"

3.6 node_modules 是什么

运行 pnpm install 后,项目根目录会出现 node_modules/ 文件夹。里面装着 Vue 及 Vue 所依赖的所有代码包。一个中等项目可能有几百 MB。

这个文件夹永远不会提交到 Git ------在 .gitignore 中声明忽略。因为:

  1. 文件太大,git 仓库根本存不下
  2. 它是可生成的------任何人在任何机器上运行 pnpm install 都能重建

3.7 一个 Vue 项目的完整启动流程

复制代码
你在终端输入:                    背后发生:

pnpm create vue@latest    →  下载 Vue 项目模板
  └─ 交互式问答                生成项目文件结构
     项目名?                    创建 my-vue-app/
     用 TS?                    创建 src/、public/ 等目录
     用 Vue Router?            写入 package.json、vite.config.ts
     用 Pinia?                  等等
     用 ESLint?

cd my-vue-app              →  进入项目目录

pnpm install               →  读取 package.json
                               下载 vue、vite 等所有依赖
                               放到 node_modules/
                               生成 pnpm-lock.yaml(锁版本号)

pnpm run dev               →  执行 "vite"
                               Vite 启动开发服务器
                               默认打开 http://localhost:5173
                               .vue 文件被编译成浏览器能识别的代码
                               改代码 → 自动热更新

此时打开浏览器,输入 http://localhost:5173,看到页面就说明一切正常。

相关推荐
研☆香11 小时前
es6新特性功能介绍(四)
前端·ecmascript·es6
有梦想的程序星空14 小时前
【环境配置】Vue3项目离线化本地部署echarts全攻略
前端·javascript·vue·echarts
Lucky_云佳17 小时前
ArcMap-去除底图水印
经验分享·arcgis·arcmap·google earth
YHHLAI1 天前
Prompt 做 NLP 任务开发|ES6 + 模块化
自然语言处理·prompt·es6
向日的葵0061 天前
vue路由(二)
前端·javascript·vue.js·vue
sugar__salt1 天前
基于Prompt的NLP项目实战:ES6模块化落地开发指南
javascript·自然语言处理·prompt·es6
meilindehuzi_a1 天前
掌握 ES6 核心语法与大模型(NLP)项目工程化搭建指南
前端·自然语言处理·es6
雪的季节1 天前
ARGIS制图效果展示
arcgis
小妖6662 天前
Hydration completed but contains mismatches
javascript·vue·vuepress