做前端这些年,项目越做越大,代码越来越难管。尤其是数据和视图之间的关系一乱,改一处,崩一片。后来用了MVVM模式,加上TypeScript,感觉像是给代码装了导航和护栏,走哪儿都不迷路。
MVVM到底解决了啥问题
以前写表单,用户输个名字,你要手动绑定input的onchange,再更新data对象,然后还要手动刷新页面上显示的名字。逻辑一多,自己都记不清哪块儿该谁更新。
MVVM把这事儿变简单了。View(视图)和Model(数据)自动同步,中间靠ViewModel牵线。你改数据,页面自动变;页面输入变了,数据也跟着更新。像Vue、Knockout这些框架就是这么干的。
TypeScript怎么帮上忙的
光有MVVM还不够。JavaScript是弱类型,写着写着就忘了某个属性是string还是number。比如用户信息里有个age,你传了个字符串'25',结果某处拿它做加减,莫名其妙变成'251'。
TypeScript这时候就派上用场了。提前把结构定死,谁也别乱来。
interface User {
name: string;
age: number;
isActive: boolean;
}
class UserViewModel {
public user: User;
constructor() {
this.user = {
name: '',
age: 0,
isActive: false
};
}
public updateName(newName: string): void {
this.user.name = newName;
}
}
这样写完,IDE立马提醒你:age不能赋值字符串,name必须是字符串。团队里新人接手也不容易踩坑。
实际场景:做个用户编辑页
假设要做个用户资料编辑页,用Vue 3 + TypeScript实现。
<template>
<div>
<input v-model="viewModel.user.name" placeholder="姓名" />
<input v-model.number="viewModel.user.age" type="number" placeholder="年龄" />
<button @click="save">保存</button>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive } from 'vue';
interface User {
name: string;
age: number;
}
export default defineComponent({
setup() {
const viewModel = reactive({
user: {
name: '',
age: 0
},
save() {
// 提交逻辑,类型安全保底
console.log('提交数据:', this.user);
}
});
return { viewModel };
}
});
</script>
这里reactive自动做了响应式绑定,TypeScript保证user结构不会乱。你想往age里塞null,编译器直接报错。
小细节决定体验
有时候后端返回的数据字段可能为空,比如用户没填年龄,返回的是null。这时候接口定义要留余地。
interface User {
name: string;
age: number | null;
}
再配合v-model.number,输入框清空时也能正确处理为null或0,不会出现NaN。
开发过程中,每次保存自动校验类型,配合ESLint,基本杜绝低级错误。上线后的bug明显少了,测试同事都夸最近提的工单质量高。
这种组合不适合所有项目,小页面确实有点“杀鸡用牛刀”。但如果你在做一个中后台系统,多人协作,长期迭代,MVVM加TypeScript真能省下不少沟通和调试成本。