Vue 入门:创建项目与组件
版本与前置知识
先读 HTML、CSS、JavaScript 与模块基础。本篇的新项目示例使用 Vue 3 与单文件组件,旧 Vue CLI 项目另在下方说明。不要把 Vue 2 的构建模板、Vue CLI 脚本和当前工具链命令混在一次初始化中。
Vue 官方快速开始使用 create-vue 创建基于 Vite 的项目。运行前核对 官方环境要求,使用满足其要求且受支持的 Node.js 版本;这里不把某个版本写成永久最新版本。
创建与运行
node --version
npm --version
npm create vue@latest按提示选择项目名和需要的功能;不熟悉的可选能力先不启用。进入生成目录后执行:
cd vue-demo
npm install
npm run dev
npm run buildvue-demo 替换为创建时选择的名称。开发服务器地址以实际终端输出为准。脚本最终以 package.json 为准,测试和 lint 仅在选择了相关工具、确实存在脚本时运行。
一个单文件组件
将 src/App.vue 改为以下内容:
<script setup>
import { computed, ref } from 'vue';
const name = ref('');
const count = ref(0);
const greeting = computed(() => `Hello, ${name.value.trim() || 'visitor'}!`);
</script>
<template>
<main>
<label for="name">名字</label>
<input id="name" v-model="name">
<p>{{ greeting }}</p>
<button type="button" @click="count += 1">点击 {{ count }} 次</button>
</main>
</template>
<style scoped>
main { max-width: 32rem; margin: 2rem auto; padding: 1rem; }
</style>ref 保存响应式值,脚本中通过 .value 访问,模板中的顶层 ref 通常自动解包。computed 从已有状态推导新值;v-model 关联输入值,@click 注册事件。scoped 限定样式匹配范围,不等同于 Shadow DOM 隔离。
继续拆组件时,父组件用 props 传数据,子组件用 emits 通知变化;多个页面再引入路由。共享状态方案依据真实需求选择,不把 Router、状态库、UI 库和 Sass 全列为必装依赖。
目录怎么读
| 位置 | 职责 |
|---|---|
package.json 与锁文件 | 脚本、依赖及可复现安装信息 |
src/main.js 或 .ts | 创建并挂载应用 |
src/App.vue | 根组件 |
src/components | 可复用组件,生成内容依选择而不同 |
public | 直接提供的静态资源 |
vite.config.* | Vite 配置,按项目实际文件阅读 |
router、views、stores、api、utils 是可选约定,不是 Vue 强制目录。环境变量的暴露规则遵循构建工具,不要把客户端可见变量当作秘密存储。
维护 Vue CLI 与更早项目
Vue CLI 官方页面将其标为维护模式。维护旧项目先检查依赖与脚本,按其 Node、包管理器和锁文件要求安装,不直接全局升级工具。
| 项目特征 | 常见脚本或文件 | 处理方式 |
|---|---|---|
旧 vue-cli + webpack 模板 | vue init webpack、常见 npm run dev | 早期模板历史笔记,按原项目依赖恢复 |
@vue/cli-service | 常见 npm run serve、vue.config.js | Vue CLI 项目;脚本以 package.json 为准 |
| Vite | 常见 npm run dev、vite.config.* | 当前本篇使用的构建方式 |
新项目不需要先全局安装 vue-cli、@vue/cli 或 cnpm。不要照抄旧淘宝镜像地址、Node 10 输出、node-sass@latest 或一组无版本配套的安装命令。已有项目升级应独立评估并测试,不能只改启动命令就视为迁移完成。
验证与练习
在生成项目中输入名字,确认问候更新;点击按钮两次,确认计数为 2;刷新应回到初始状态。再把按钮提取成子组件,用 props/emits 传递计数操作。最后运行 npm run build,检查生产打包是否成功。
参考解法
把子组件保存为src/components/CounterButton.vue:
<script setup>
defineProps({ count: { type: Number, required: true } });
defineEmits(['increment']);
</script>
<template><button type="button" @click="$emit('increment')">点击 {{ count }} 次</button></template>父组件在原script setup中增加import CounterButton from './components/CounterButton.vue',把原按钮替换为<CounterButton :count="count" @increment="count += 1" />。count仍由父组件拥有,子组件只发事件;两次点击显示2,刷新回0,名字全空白时显示Hello, visitor!。构建成功只说明工具接受项目,不能代替上述交互验收。
深入课程已接续:响应式依赖与作用域清理。基础内容与旧锚点保留,按当前路线进入完整机制和实践。
继续阅读
- 组件与状态
- 排错
- 开发实践