Vue3(篇一) 核心概念——响应式模板语法与组件基础

Vue3(篇一) 核心概念——响应式模板语法与组件基础 目录前言一、Vue 是什么1.1 前端框架的定位1.2 Vue 的核心思想二、技术选型概览三、环境准备3.1 创建项目3.2 配置开发工具3.3 安装调试工具3.4 配置开发服务器四、项目结构解析4.1 入口文件index.html4.2 应用入口main.ts4.3 根组件App.vue五、响应式数据ref 与 reactive5.1 为什么需要响应式5.2 ref包装任意类型5.3 reactive包装对象类型5.4 ref vs reactive如何选择六、数据绑定6.1 文本绑定双花括号6.2 属性绑定v-bind简写 :6.3 事件绑定v-on简写 6.4 表单绑定v-model双向绑定七、计算属性与监听器7.1 计算属性computed7.2 监听器watch八、条件渲染与列表渲染8.1 条件渲染v-if、v-else、v-show8.2 列表渲染v-for8.3 v-if 与 v-for 的优先级总结前言如何高效地构建用户界面传统的做法是用原生 JS 操作 DOM——获取元素、绑定事件、更新内容。这种方式在小项目中尚可但一旦项目变大代码就会变得难以维护。你需要在数据变化时手动更新页面在用户操作时手动同步数据繁琐且容易出错。Vue3 正是为了解决这个问题而生——它提供了一套响应式机制让数据和页面自动同步。你只需要关注数据本身页面会自动更新。本文将从零开始搭建 Vue3 项目理解其核心概念响应式数据与数据绑定。一、Vue 是什么1.1 前端框架的定位如果把前端开发比作盖房子HTML是砖块和钢筋结构CSS是涂料和装饰样式JavaScript是施工工具行为Vue/React/Angular是建筑图纸和施工团队框架框架的核心价值让开发者专注于盖什么而不是怎么盖。1.2 Vue 的核心思想Vue 的核心理念是数据驱动视图。传统方式Vue 方式数据变化 → 手动更新 DOM数据变化 →自动更新 DOM用户操作 → 手动同步数据用户操作 →自动同步数据代码分散在多处代码集中在组件中用一句话概括你改变数据Vue 改变页面。二、技术选型概览在开始之前先了解一下 Vue3 项目的常见技术选型类别选项推荐说明API 风格选项式 API / 组合式 API组合式 API✅Vue3 新特性更灵活、更易复用组件格式HTML 模板 / 单文件组件单文件组件✅.vue文件结构清晰语言JavaScript / TypeScriptTypeScript✅类型安全开发体验更好构建工具Vue CLI / ViteVite✅速度更快Vue 官方推荐路由vue-routervue-router✅官方路由方案状态管理Vuex / PiniaPinia✅Vue3 官方推荐更简洁UI 组件库Element Plus / Ant Design VueElement Plus✅Vue3 生态最成熟的组件库本文将基于以上推荐组合进行讲解。三、环境准备3.1 创建项目Vue3 官方推荐使用 Vite 创建项目。打开终端执行npminit vitelatest按提示输入项目名称、选择框架Vue、选择语言TypeScript✔ Project name: vue3-demo ✔ Select a framework: › Vue ✔ Select a variant: › TypeScript进入项目目录并安装依赖cdvue3-demonpminstall启动开发服务器npmrun dev打开浏览器访问http://localhost:5173看到 Vue 的欢迎页面说明项目创建成功。3.2 配置开发工具推荐使用VSCode作为开发工具并安装以下插件插件名作用Vue - Official (原名 Volar)Vue3 语法高亮、类型提示ESLint代码规范检查安装后打开.vue文件就能获得良好的开发体验。3.3 安装调试工具浏览器安装Vue DevTools扩展可以实时查看组件状态、路由信息等。Chrome 扩展Vue.js devtools安装后按 F12 打开开发者工具就能看到 Vue 标签页。3.4 配置开发服务器有时需要修改开发服务器配置比如端口号、代理等。编辑vite.config.tsimport{defineConfig}fromviteimportvuefromvitejs/plugin-vueexportdefaultdefineConfig({plugins:[vue()],server:{port:3000,// 修改端口open:true,// 启动时自动打开浏览器proxy:{// 配置代理解决跨域/api:{target:http://localhost:8080,changeOrigin:true}}}})跨域问题前端运行在localhost:3000后端运行在localhost:8080直接请求会产生跨域错误。配置代理后前端请求/api/xxx会被转发到http://localhost:8080/api/xxx。四、项目结构解析用 VSCode 打开项目目录结构如下vue3-demo/ ├── index.html # 入口 HTML ├── package.json # 项目配置 ├── tsconfig.json # TypeScript 配置 ├── vite.config.ts # Vite 配置 ├── public/ # 静态资源不参与打包 └── src/ ├── main.ts # 应用入口 ├── App.vue # 根组件 └── ... # 其他源码4.1 入口文件index.html!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8/titleVue3 Demo/title/headbodydividapp/divscripttypemodulesrc/src/main.ts/script/body/htmldiv idapp是挂载点Vue 应用会渲染到这里script引入main.ts这是应用的入口4.2 应用入口main.tsimport{createApp}fromvueimportAppfrom./App.vuecreateApp(App).mount(#app)这段代码做了三件事createApp(App)- 创建 Vue 应用实例参数是根组件.mount(#app)- 将应用挂载到index.html中idapp的元素上类比 Java这就像 Java 的main方法是整个应用的启动入口。4.3 根组件App.vuescript setup langts import { ref } from vue const msg ref(Hello, Vue3!) /script template h1{{ msg }}/h1 /template style scoped h1 { color: #42b983; } /style这是 Vue 的单文件组件.vue由三部分组成部分作用类比script setupJavaScript/TypeScript 逻辑Java 类的方法templateHTML 模板JSP/Thymeleaf 模板style scopedCSS 样式scoped 表示仅作用于当前组件组件内部样式setup关键字这是 Vue3 组合式 API 的标志表示在组件创建时执行此代码块。五、响应式数据ref 与 reactiveVue 的核心魔法是响应式——数据变化页面自动更新。要实现这一点数据必须用ref或reactive包装。5.1 为什么需要响应式看一个普通变量的例子script setup langts let msg Hello function change() { msg World // 修改普通变量 } /script template h1{{ msg }}/h1 button clickchange修改/button /template点击按钮后msg确实变成了World但页面上的{{ msg }}不会更新。原因Vue 无法追踪普通变量的变化。5.2 ref包装任意类型用ref包装变量让它变成响应式script setup langts import { ref } from vue const msg ref(Hello) function change() { msg.value World // 注意需要 .value } /script template h1{{ msg }}/h1 !-- 模板中不需要 .value -- button clickchange修改/button /template这次点击按钮页面会自动更新。关键规则script中访问/修改msg.valuetemplate中使用直接用msgVue 自动解包类比 Javaref类似 Java 的包装类如AtomicReference内部封装了值和变更通知机制。5.3 reactive包装对象类型reactive用于包装对象让它变成响应式script setup langts import { reactive } from vue const user reactive({ name: 张三, age: 18 }) function grow() { user.age // 不需要 .value } /script template p姓名{{ user.name }}/p p年龄{{ user.age }}/p button clickgrow长大一岁/button /template5.4 ref vs reactive如何选择特性refreactive适用类型任意类型基本类型、对象仅对象类型访问方式需要.value直接访问属性重新赋值可以整体替换不能整体替换会丢失响应式推荐场景基本类型、需要重新赋值的场景复杂对象、表单数据推荐做法基本类型用ref对象类型两者皆可如果对象结构固定用reactive如果需要整体替换用refscript setup langts import { ref, reactive } from vue // 推荐基本类型用 ref const count ref(0) const name ref(张三) // 推荐复杂对象、结构固定用 reactive const form reactive({ username: , password: }) // 也行对象用 ref需要整体替换时推荐 const user ref({ name: 张三, age: 18 }) user.value { name: 李四, age: 20 } // 整体替换 OK /script六、数据绑定响应式数据需要绑定到模板中才能展示和交互。Vue 提供了多种绑定方式。6.1 文本绑定双花括号template h1{{ msg }}/h1 p计算结果{{ 1 2 }}/p p当前时间{{ new Date().toLocaleString() }}/p /template{{ }}中可以写任何 JavaScript 表达式。类比 JSP类似于% msg %或 EL 表达式${msg}。6.2 属性绑定v-bind简写:将数据绑定到 HTML 属性script setup langts import { ref } from vue const url ref(https://vuejs.org) const imgPath ref(/images/logo.png) /script template !-- 完整写法 -- a v-bind:hrefurlVue 官网/a !-- 简写推荐 -- a :hrefurlVue 官网/a img :srcimgPath altLogo /template写法说明v-bind:属性名表达式完整写法:属性名表达式简写推荐6.3 事件绑定v-on简写绑定事件处理函数script setup langts import { ref } from vue const count ref(0) function increment() { count.value } function decrement() { count.value-- } /script template button v-on:clickdecrement-/button span{{ count }}/span button clickincrement/button !-- 简写推荐 -- /template写法说明v-on:事件名函数名完整写法事件名函数名简写推荐传递参数和事件对象script setup langts function handleClick(msg: string, event: MouseEvent) { console.log(msg, event.target) } /script template !-- 传递参数 -- button clickhandleClick(删除, $event)删除/button !-- 简写直接访问事件对象 -- button click(e) console.log(e.target)点击/button /template6.4 表单绑定v-model双向绑定表单元素input、select、checkbox 等需要双向绑定数据变化更新视图视图变化更新数据。script setup langts import { ref } from vue const user ref({ name: , age: 18, sex: 男, hobbies: [] }) /script template div !-- 文本框 -- label姓名/label input typetext v-modeluser.name /div div !-- 数字框 -- label年龄/label input typenumber v-modeluser.age /div div !-- 单选框 -- label性别/label input typeradio value男 v-modeluser.sex 男 input typeradio value女 v-modeluser.sex 女 /div div !-- 复选框绑定数组 -- label爱好/label input typecheckbox value游泳 v-modeluser.hobbies 游泳 input typecheckbox value打球 v-modeluser.hobbies 打球 input typecheckbox value阅读 v-modeluser.hobbies 阅读 /div div !-- 下拉框 -- label城市/label select v-modeluser.city option value请选择/option option value北京北京/option option value上海上海/option /select /div pre{{ user }}/pre /template类比 Java类似于 JavaBean 的属性绑定但自动双向同步。表单类型v-model 绑定类型说明text、textareastring文本内容numbernumber数值radiostring单选值checkboxboolean / string[]单个用 boolean多个用数组selectstring / string[]单选用 string多选用数组七、计算属性与监听器7.1 计算属性computed有时需要基于现有数据计算出新值script setup langts import { ref, computed } from vue const firstName ref(三) const lastName ref(张) // 计算属性自动缓存依赖变化才重新计算 const fullName computed(() { return lastName.value firstName.value }) /script template p全名{{ fullName }}/p /template计算属性 vs 方法script setup langts // 计算属性有缓存依赖不变就不重新计算 const fullName computed(() { console.log(computed 执行) return lastName.value firstName.value }) // 方法每次调用都执行 function getFullName() { console.log(方法执行) return lastName.value firstName.value } /script template !-- 计算属性多次使用只计算一次 -- p{{ fullName }}/p p{{ fullName }}/p !-- 方法每次都执行 -- p{{ getFullName() }}/p p{{ getFullName() }}/p /template特性计算属性方法缓存✅ 有依赖不变不重新计算❌ 无每次调用都执行使用方式{{ fullName }}{{ getFullName() }}适用场景需要复用计算结果每次都需要新结果类比 Java计算属性类似于带缓存的 getter 方法。7.2 监听器watch监听数据变化执行副作用如保存到 localStorage、发送请求script setup langts import { ref, watch } from vue const name ref(localStorage.getItem(name) || ) // 监听 name 变化自动保存到 localStorage watch(name, (newValue) { localStorage.setItem(name, newValue) }) /script template input typetext v-modelname placeholder输入姓名 /template监听对象属性script setup langts import { reactive, watch } from vue const user reactive({ name: 张三, age: 18 }) // 监听对象的某个属性 watch( () user.age, // getter 函数 (newValue, oldValue) { console.log(年龄从 ${oldValue} 变为 ${newValue}) } ) /script监听多个数据script setup langts import { ref, watch } from vue const firstName ref(三) const lastName ref(张) // 监听多个数据 watch([firstName, lastName], ([newFirst, newLast], [oldFirst, oldLast]) { console.log(姓名变化${oldLast}${oldFirst} - ${newLast}${newFirst}) }) /script八、条件渲染与列表渲染8.1 条件渲染v-if、v-else、v-show根据条件决定是否渲染元素script setup langts import { ref } from vue const isLoggedIn ref(false) const role ref(admin) /script template !-- v-if条件为真才渲染会销毁和重建 DOM -- div v-ifisLoggedIn欢迎回来/div div v-else请先登录/div !-- v-else-if多条件 -- div v-ifrole admin管理员页面/div div v-else-ifrole user用户页面/div div v-else游客页面/div !-- v-show始终渲染只是切换 display 样式 -- div v-showisLoggedIn这个元素始终存在于 DOM 中/div /template指令特点适用场景v-if真正销毁和重建 DOM条件很少改变v-show只切换 CSS display频繁切换类比 Javav-if类似于条件语句v-show类似于控制可见性的布尔标志。8.2 列表渲染v-for遍历数组或对象script setup langts import { ref } from vue const students ref([ { id: 1, name: 张三, age: 18 }, { id: 2, name: 李四, age: 19 }, { id: 3, name: 王五, age: 20 } ]) const user ref({ name: 张三, age: 18, sex: 男 }) /script template !-- 遍历数组 -- ul li v-forstudent in students :keystudent.id {{ student.name }} - {{ student.age }}岁 /li /ul !-- 遍历对象 -- ul li v-for(value, key) in user :keykey {{ key }}: {{ value }} /li /ul /template:key的重要性!-- ❌ 不推荐使用索引作为 key -- li v-for(student, index) in students :keyindex !-- ✅ 推荐使用唯一标识符作为 key -- li v-forstudent in students :keystudent.id类比 Java:key类似于 Map 的 key用于标识列表项的唯一性。Vue 通过 key 来判断哪些元素发生了变化从而高效更新 DOM。8.3 v-if 与 v-for 的优先级重要规则不要把 v-if 和 v-for 放在同一个元素上!-- ❌ 不推荐v-if 和 v-for 同级 -- li v-forstudent in students v-ifstudent.age 18 :keystudent.id !-- ✅ 推荐使用 template 包裹 -- template v-forstudent in students :keystudent.id li v-ifstudent.age 18{{ student.name }}/li /template !-- ✅ 推荐使用计算属性过滤 -- script setup langts import { computed } from vue const adultStudents computed(() { return students.value.filter(s s.age 18) }) /script li v-forstudent in adultStudents :keystudent.id总结本文从零开始搭建了 Vue3 项目并深入讲解了其核心概念概念作用关键点响应式数据数据变化自动更新视图ref适用于任意类型reactive适用于对象数据绑定数据与视图同步{{ }}文本、:属性、事件、v-model表单计算属性缓存计算结果依赖变化才重新计算监听器数据变化时执行副作用如保存到 localStorage条件渲染按条件显示元素v-if真正销毁v-show只是隐藏列表渲染遍历显示列表必须提供唯一的:key下一步在掌握了数据绑定后我们需要学习如何与后端 API 交互。下一篇文章将讲解 axios 和请求封装。作者小张 | 转载请注明出处