project from jirengu.com
MVC重构
- 用
MVC设计模式
,把项目代码在数据层面进行重构,所有数据Model层面的集中到一个文件,所有视图View放在一起。 -
- 初始化数据:
recordList: Record[] = JSON.parse(window.localStorage.getItem(recordList) || '[]');
-
- 更新数据,往数据里添加东西:
saveRecord() {
const record2: Record = JSON.parse(JSON.stringify(this.record));
record2.createdAt = new Date();
this.recordList.push(record2);
}
-
- 保存数据:
@Watch('recordList')
onRecordListChange() {
window.localStorage.setItem(recordList, JSON.stringify(this.recordList));
- 如何用
js
来封装Model
:新建文件在src根目录
下,名为model.js
:
const localStorageKeyName= 'recordList'
const model = {
fetch(){ //获取数据
return JSON.parse(window.localStorage.getItem(localStorageKeyName) || '[]')
},
save(data){
window.localStorage.setItem(localStorageKeyName, JSON.stringify(this.recordList));
}
}
export default model
- 此时直接在
Money.vue
中的ts
引入model.js
文件,会出现识别fetch
函数的情况,是因为引入语法的问题:
const model = require('@/model.js') //ts引入js的正确打开方式
const recordList: Record[] = model.fetch()
- 应修改导出
model.js
的原语句为具名导出:
export default model //原来的导出语句
export {model} //修改为此方式
//Money.vue
const model = require('@/model.js').model;
const {model} =require('@/model.js'); //这种析构写法也可以
const recordList: Record[] = model.fetch();
-
如何把
model.js
改写为model.ts
: -
直接在原
model.js
右键,refactor->rename,取消勾选,改后缀为model.ts
,再把Money.vue中的Record
重构为RecordItem
,最后在src根目录
新建一个custom.d.ts
,用来自定义全局声明。
//custom.d.ts
type RecordItem = { //TS类型声明只写类型,JS类型声明写具体内容
tags: string[]
notes: string
type: string
amount: number
createdAt: Date
}
//model.ts
save(data: RecordItem[]) {
window.localStorage.setItem(localStorageKeyName, JSON.stringify(data));
}
- 重新引用model:
//Money.vue
import model from '@/model';
const recordList: RecordItem[] = model.fetch()
//model.ts
const localStorageKeyName = 'recordList';
const model = {
fetch() { //获取数据
return JSON.parse(window.localStorage.getItem(localStorageKeyName) || '[]');
},
save(data: RecordItem[]) {
window.localStorage.setItem(localStorageKeyName, JSON.stringify(data));
}
};
export default model;
fetch
的返回值类型定义一下:
fetch() { //获取数据
return JSON.parse(window.localStorage.getItem('localStorageKeyName') || '[]') as RecordItem[];
},
封装的结果为:
//Money.vue
<template>
<Layout class-prefix="layout">
{{recordList}}
<NumberPad @update:value="onUpdateAmount" @submit="saveRecord"/>
<Types :value.sync="record.value"/>
<Notes @update:value="onUpdateNotes"/>
<Tags :data-source.sync="tags" @update:value="onUpdateTags"/>
</Layout>
</template>
<script lang="ts">
import Vue from 'vue';
import NumberPad from '@/components/Money/NumberPad.vue';
import Types from '@/components/Money/Types.vue';
import Notes from '@/components/Money/Notes.vue';
import Tags from '@/components/Money/Tags.vue';
import {Component, Watch} from 'vue-property-decorator';
import model from '@/model';
const recordList = model.fetch();
@Component({
components: {Tags, Notes, Types, NumberPad}
})
export default class Money extends Vue {
tags = ['餐饮', '购物', '交通', '娱乐', '医疗'];
recordList: RecordItem[] = JSON.parse(window.localStorage.getItem('recordList') || '[]');
record: RecordItem = {
tags: [], notes: '', type: '-', amount: 0
};
onUpdateAmount(value: string) {
this.record.amount = parseFloat(value);
}
onUpdateType(value: string) {
this.record.type = value;
}
onUpdateNotes(value: string) {
this.record.notes = value;
}
onUpdateTags(value: string[]) {
this.record.tags = value;
}
saveRecord() {
const record2: RecordItem = model.clone(this.record);
record2.createdAt = new Date();
this.recordList.push(record2);
}
@Watch('recordList')
onRecordListChange() {
model.save(this.recordList);
}
}
</script>
<style lang="scss">
.layout-content {
display: flex;
flex-direction: column-reverse;
}
</style>
//custom.d.ts
type RecordItem = { //TS类型声明只写类型,JS类型声明写具体内容
tags: string[]
notes: string
type: string
amount: number
createdAt: Date
}
//model.ts
const localStorageKeyName = 'recordList';
const model = {
clone(data:RecordItem[]| RecordItem) {
return JSON.parse(JSON.stringify(data));
},
fetch() { //获取数据
return JSON.parse(window.localStorage.getItem('localStorageKeyName') || '[]') as RecordItem[];
},
save(data: RecordItem[]) {
window.localStorage.setItem('localStorageKeyName', JSON.stringify(data));
}
};
export default model;
本节中一个坑,要注意
- 所有model数据内容中涉及到
window.localStorage.setItem
,第一项参数,要注意不要有引号,应该是默认敲代码时候会自动加,这样会影响后面的开发体验,无法保存当前页面数据。应都改为如下代码:
//model.ts
fetch() { //获取数据
return JSON.parse(window.localStorage.getItem('localStorageKeyName') || '[]') as RecordItem[]; //此行为敲代码默认写法,是错误的
return JSON.parse(window.localStorage.getItem(localStorageKeyName) || '[]') as RecordItem[]; //此行为正确写法,去掉引号
},
save(data: RecordItem[]) {
window.localStorage.setItem('localStorageKeyName', JSON.stringify(data)); //此行为敲代码默认写法,是错误的
window.localStorage.setItem(localStorageKeyName, JSON.stringify(data)); //此行为正确写法,去掉引号
}