Skip to content

00|学习环境:从一个文件到浏览器里的页面 ​

第一件事是让你知道代码应放在哪里、怎样运行、出错时看哪里。后面的模板、组件和响应式实验都可以在这个小目录中单独运行;每次换一个例子时,保留入口,替换对应组件。

先准备运行工具 ​

使用 Node.js 24 系列的 24.15 或更高版本,并确认 npm 版本至少为 10。本书的例子以 Vue 3.5.42 为行为基线。Node 在这里运行开发工具;打开页面后,组件的交互代码主要在浏览器执行。

在终端执行:

sh
node --version
npm --version

能看到版本号,才继续创建目录。若显示找不到命令,先安装对应版本的 Node 并重新打开终端。终端中的当前目录决定新文件创建在哪里;选择自己的练习目录,不在正在维护的应用中运行脚手架。

sh
npm create vue@3.23.0 vue-learning -- --typescript --bare
cd vue-learning
npm install
npm run dev

第一条使用固定版本的官方脚手架创建 vue-learning。--typescript 加入类型支持,--bare 创建简洁的初始页面。若询问是否下载脚手架,确认后继续。目录已存在时,换一个新名称,不覆盖此前的实验。

浏览器打开终端给出的本机地址。默认端口被占用时,工具可能选择其他端口,以实际输出为准。开发服务器保持运行;结束时在它所在终端按 Ctrl+C。

脚手架版本固定并不等于每个间接依赖永远相同。首次安装的间接依赖也可能提高 Node 要求,因此看到 EBADENGINE 时应先核对并更新 Node,不能把警告当作课程已经验证通过。安装成功后保留 package-lock.json;同一份练习目录重新安装使用 npm ci,并用下面的命令确认版本:

sh
npm ls vue vite

三个文件怎样连接 ​

先保留生成的配置文件,把 src/App.vue 替换为:

vue
<script setup lang="ts">
const title = '我的第一段 Vue 笔记'
const lessonCount = 3
</script>

<template>
  <main>
    <h1>{{ title }}</h1>
    <p>今天准备阅读 {{ lessonCount }} 节。</p>
  </main>
</template>

<style scoped>
main {
  max-width: 40rem;
  margin: 3rem auto;
  line-height: 1.8;
}
</style>

页面应出现标题和“今天准备阅读 3 节”。这里只使用普通常量:script setup 中声明的名字可以在本组件模板里读取;双花括号把表达式的结果显示成文字。第一篇会进一步讲插值的求值与边界。

再打开 src/main.ts,入口应包含:

ts
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

import App 引入根组件;createApp(App) 创建应用;mount('#app') 找到 HTML 中 id="app" 的元素,把根组件交给 Vue 渲染。根目录 index.html 中对应的关键部分是:

html
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>

浏览器先取得 HTML,通过模块脚本加载入口,入口再引入组件。Vite 的 Vue 插件负责把浏览器不能直接执行的 .vue 文件转换为 JavaScript 和样式;Vue 运行时负责把组件描述变成页面。

text
index.html 的模块入口
    → src/main.ts 导入 App.vue
    → 工具转换单文件组件
    → createApp 创建应用
    → mount 找到 #app
    → 浏览器中出现组件内容

这里的箭头描述职责关系,不要求你现在实现编译器。第七章会从实际渲染过程解释这些层次。

改文件和改运行中的状态有什么不同 ​

把 lessonCount 改为 4 并保存,页面会显示新文字。这是开发工具发现源文件变化后更新页面,不是普通常量自己获得了响应式能力。

后面会在事件中修改运行中的状态,那时需要 ref 等容器。先分清这两种变化:保存源代码触发开发更新,和用户操作触发应用状态更新,原因不同。

一个完整例子只放在一份对应文件中。标为 Child.vue 的组件应另存为文件,再由父组件导入;不要把两个组件的 script setup 拼接进同一个 App.vue。标为“局部片段”的代码需要放在正文指定的已有上下文中。

TypeScript 在例子中负责什么 ​

本书沿用 lang="ts",让错误的参数和组件输入尽早被检查。TypeScript 以 JavaScript 为基础,类型标注不会替你验证服务器返回的数据。

ts
const title: string = '插值'   // 这个变量接受字符串
const scores: number[] = [8, 9] // 数字数组
const selected: number | null = null // 数字或尚未选择

后文看到 ref<number | null>(null),尖括号限定容器可以保存的类型,括号中的 null 才是实际初值。看到 type Person = { name: string },它描述对象形状,不会创建一个人。涉及更复杂的类型工具时,先读 TypeScript 学习路线中的对应知识;基础示例不以复杂类型技巧作为理解 Vue 的门槛。

区分三种检查 ​

开发页面能出现,不代表类型检查通过。生成的目录提供:

sh
npm run type-check
npm run build
npm run preview

type-check 检查 TypeScript 和模板类型;build 检查类型并生成 dist 中的生产文件;preview 在本机预览生成的产物,运行前应先完成构建。它不会在你修改源码后自动重建产物。

页面空白时,先看终端的编译错误,再看浏览器控制台的运行错误;只有正常运行了,才继续分析状态为什么不更新。检查导入文件名、挂载点和打开的端口,往往能把“环境没起来”和“知识点理解错了”分开。

练习:追踪入口和挂载点 ​

先预测,再逐项实验,每次完成后恢复文件:

  1. 把标题改为自己的章节名称,保存后解释页面为什么变化。
  2. 只把 index.html 中的 id="app" 改为 id="reader",入口不改。观察页面与控制台。
  3. 让入口和 HTML 都使用 reader,确认页面恢复。
  4. 把 const lessonCount: number = 3 改为 const lessonCount: number = 'three',运行类型检查,记录失败原因,然后改回数字。

本题只依赖本页的文件关系与类型标注,不需要表单或事件。参考结果放在第一章答案:运行环境。

接着阅读插值与表达式。

用心记录每一步成长