Vue3教程:同业务:Vue3 setup语法糖版本(和上面原生JS案例一一对应,方便课堂对比教学)
同业务:Vue3 setup语法糖版本(和上面原生JS案例一一对应,方便课堂对比教学)
业务完全一样:住户登记、填写姓名房号、勾选物业费缴费状态、新增、删除住户、统计总户数/欠费户数、模拟后端提交。
世界观:
原生JS:数据改完,程序员手动调用render函数,手动操作DOM广告牌
Vue3:修改响应式收纳盒的数据,Vue自动对比虚拟DOM,自动更新页面广告牌,不再手写DOM操作
<!-- App.vue 等价Vue3版本 -->
<template>
<div>
<h2>🏘️ 阳光智慧小区 - 住户登记大屏【Vue3版本】</h2>
<!-- 表单区域,Vue模板,不用手写querySelector获取DOM -->
<div>
姓名:<input v-model="name" placeholder="输入住户姓名">
房号:<input v-model="room" placeholder="输入房号数字">
<input type="checkbox" v-model="isPaid">已缴物业费
<button @click="addResident">登记住户</button>
</div>
<div>
<h3>统计信息:总户数:{{ residentList.length }},欠费户数:{{ unpaidCount }}</h3>
</div>
<!-- 住户列表,v-for循环渲染,不用手写循环创建DOM、appendChild -->
<div>
<div class="item" v-for="(item, index) in residentList" :key="index">
住户:{{ item.name }},房号:{{ item.room }},物业费:{{ item.isPaid ? "已缴" : "欠费" }}
<span class="del-btn" @click="delResident(index)">【删除】</span>
</div>
</div>
</div>
</template>
<script setup>
// 引入Vue响应式收纳盒ref
import { ref, computed } from 'vue'
// ================== 响应式收纳盒(对应原生JS的let/const)==================
// 输入框绑定数据
const name = ref('')
const room = ref('')
const isPaid = ref(false)
// 住户档案数组(响应式数组,数据变化自动驱动页面更新!核心区别!)
const residentList = ref([])
// computed 计算属性:自动算出欠费人数,自动缓存,不用手动写函数遍历
const unpaidCount = computed(() => {
return residentList.value.filter(item => item.isPaid === false).length
})
// ================== 表单校验函数(和原生逻辑完全一样)==================
function validateInput(nameStr, roomStr) {
if (!nameStr) {
return { ok: false, msg: "❌姓名不能为空!" };
}
if (isNaN(roomStr) || Number(roomStr) <= 0) {
return { ok: false, msg: "❌房号必须是大于0的数字!" };
}
return { ok: true, msg: "✅校验通过" };
}
// ================== 新增住户 ==================
async function addResident() {
try {
const inputName = name.value.trim()
const inputRoom = room.value.trim()
const checkRes = validateInput(inputName, inputRoom)
if (!checkRes.ok) {
alert(checkRes.msg)
return
}
// 新增住户档案
const newResident = {
name: inputName,
room: Number(inputRoom),
isPaid: isPaid.value
}
residentList.value.push(newResident)
// 模拟提交到城市数据中心API
const res = await fetch("[https://jsonplaceholder.typicode.com/posts](https://jsonplaceholder.typicode.com/posts)", {
method: "POST",
body: JSON.stringify(newResident)
})
const backData = await res.json()
console.log("✅总部收到登记,返回回执:", backData);
// 清空表单
name.value = ''
room.value = ''
isPaid.value = false
} catch (err) {
console.error("❌网络上报出错:", err);
alert("网络故障,住户信息保存到本地成功,上报总部失败!");
}
}
// ================== 删除住户 ==================
function delResident(index) {
residentList.value.splice(index, 1)
// ✅重点!!!原生JS这里需要调用renderList();Vue不需要!数组一改页面自动更新!
}
</script>
<style>
.item {margin:4px 0;padding:4px;border:1px solid #aaa;}
.del-btn {margin-left:10px;color:red;cursor:pointer;}
</style>
✅【课堂核心对比清单,黑板板书,重点!】
原生JS版本痛点,Vue全部解决:
原生JS(Vue出现之前)
- 需要手动
document.querySelector查找所有DOM广告牌 - 数据修改之后,必须手动写 renderList() 函数,手动操作DOM更新页面;忘记调用,页面不会刷新
- 需要手写循环:
createElement、appendChild拼接DOM节点 - 事件需要 addEventListener 手动绑定
- 数据和视图完全分开,需要程序员手动负责两边同步,非常容易出现:内存数据变了,页面画面没更新的bug
Vue3版本
- 模板语法
v-model、v-for、@click,不需要手动获取DOM元素 - 直接修改响应式收纳盒
residentList.value,Vue自动监听数据变化,自动更新页面DOM - v-for自动循环渲染列表,不用手写DOM创建、拼接HTML
- 事件直接写在模板
@click,不需要addEventListener - 数据驱动:数据是唯一的数据源。数据一变,页面自动同步。不用人工写渲染函数
课堂一句话口述讲解
原生JS版本:我们维护一份住户档案数组,改完数据,必须手动调用renderList去操作DOM刷新页面。如果忘记调用renderList,页面不会变化。
Vue版本:我们同样维护住户档案数组(响应式ref收纳盒),修改数组,Vue自动帮我们更新页面广告牌,完全不用手写DOM操作、不用写render渲染函数。
Vue底层依然是JavaScript,Vue帮我们封装了「数据监听、虚拟DOM、diff对比、更新DOM」这一大堆重复枯燥的工作。程序员只需要关心业务数据。
上机演示对比实验(课堂实操)
- 原生JS页面:
控制台执行:
residentList.push({name:"小张",room:2002,isPaid:false})
👉 内存数组数据变了,页面完全不变,必须手动执行renderList()页面才刷新。
- Vue页面:
F12控制台输入(找到vue实例,修改响应式数组)
residentList.value.push({name:"小张",room:2002,isPaid:false})
👉 页面立刻自动更新,不需要调用任何渲染函数!
随堂思考题(给学生)
- Vue3里面修改residentList数组,为什么不需要手动写render渲染函数?>
Vue通过响应式系统监听数据变化,自动执行DOM更新。
- Vue是不是抛弃了DOM?>
没有抛弃DOM。Vue底层依然操作DOM,只是Vue帮我们自动完成DOM操作,不用我们手写。
下一步:引入TS
接下来,我们可以给这个Vue3项目加上TS,给住户档案定义接口interface Resident,提前约束档案的类型,在写代码阶段检查数据格式,提前捕获错误,为TypeScript做铺垫。
需要我把这个Vue3代码改成 Vue3 + TS版本,继续对比演示吗?

浙公网安备 33010602011771号