回顾设计之初
第(8)节
branch角色表
- 给五个字段,例如:first,second,third,fourth,fifth
这五个字段分别对应5个级别,first是最高级fifth就是角色(最低级了)
- 所有字段都以部门命名,当该字段需要角色时在下一级字段添加角色名,该部门可以前端定义为该部门负责人,获取接口时做数据处理
first: [{name:second,children:[]},{name:second}]
错误说明
这里的设计已经违背了数据库设计的三大范式;
- 第一范式:当关系模式R的所有属性都不能在分解为更基本的数据单位时,称R是满足第一范式的,简记为1NF。满足第一范式是关系模式规范化的最低要求,否则,将有很多基本操作在这样的关系模式中实现不了。
- 第二范式:如果关系模式R满足第一范式,并且R得所有非主属性都完全依赖于R的每一个候选关键属性,称R满足第二范式,简记为2NF。
- 第三范式:设R是一个满足第一范式条件的关系模式,X是R的任意属性集,如果X非传递依赖于R的任意一个候选关键字,称R满足第三范式,简记为3NF. 我最初的观点是上下级角色带权限,这里实际上是混淆了,拆分来看应该是:
而我将部门和角色甚至于职位都弄混淆了,放在一个表里,这也变向的导致了我复杂的数据处理。
项目总结
编程基础知识总结
1.类的概念
ECMAScript 标准定义的 10 种数据类型可以再划分为:
基本数据类型和引用数据类型
JS基本数据类型(7) | JS引用数据类型(...) |
---|---|
undefined | Object |
Number | Array |
String | Function |
Boolean | |
BigInt | |
Symbol | |
null |
基本数据类型:满足深拷贝的概念;即
const a = 10;
let b = a;
b = 20;
console.log(a,b) // 10 20
引用数据类型:深浅拷贝的发出者;即
class Student{
constructor(name) {
this.name = name;
}
}
let z = new Student('z');
let s = z;
s.name = 's'
console.log(z,s)//两个都为{name:'s'}
这里补充一下ts
class Student{
public school:string;
private name:string;
protected age:number;
constructor(school:string,name:string,age:number) {
this.school = school;
this.name = name;
this.age = age;
}
}
class Book extends Student{
constructor(school:string,name:string,age:number){
super(school,name,age)
}
public getInfo() {
return this.age;
}
}
let c = new Book('a','b',1);
let z = new Student('a','b',2);
let s = z;
s.school = 's' // s不能访问属性name和age属性但是c可以访问getInfo()
console.log(c.getInfo()) // 1
console.log(z,s) // 两个都为{school:'s',name:'b',age:3}
2.面向对象
面向对象的三个基本特征:封装、继承、多态
对象是什么?对象就是类的实例化。
// js
class Student{
name;
constructor(name) {
this.name = name;
}
}
const a = new Student('曹操')//a就是对象 constructor就是封装
用ts举例继承中接口跟类的区别
interface Name{
name:string;
}
interface Age{
age:number|string;
}
interface Person extends Name,Age{
sex:string;
}
let person = <Person>{};
person.name = '张三';
person.age = '14';
person.sex = '男';
console.log(person) // { name: '张三', age: '14', sex: '男' }
class Name{
name:string;
}
class Age{
age:number|string;
}
class Person extends Name{
sex:string;
}
let person = <Person>{};
person.name = '张三';
person.sex = '男';
console.log(person) // { name: '张三', sex: '男' }
为什么接口可以多个继承,而类却只能继承一个。 这里通过原型链看下
class Name{
name:string;
}
interface Sex{
sex:string;
}
interface Age{
age:number|string;
}
class People extends Name{
sex:string;
getAge(){
return 18;
}
}
class Person extends Name{
sex:string;
getAge(){
return 18;
}
}
interface Man extends Sex,Age{
name:string;
}
let people = new People;
let person = <Person>{};
let man = <Man>{};
people.name = '赵六';
people.sex = '女';
person.name = '张三';
person.sex = '男';
man.age = 18;
man.sex = '男';
man.name = '李四';
console.log(people);// People { name: '赵六', sex: '女' }
console.log(people.getAge()); // 18
console.log(person); // { name: '张三', sex: '男' }
console.log(person.getAge()); // 错误
console.log(man); // { age: 18, sex: '男', name: '李四' }
console.log('people-class',people instanceof Name); // true
console.log('people-obj',people instanceof Object); // true
console.log('person-class',person instanceof Name); // false
console.log('person-obj',person instanceof Object); // true
console.log('man-obj',man instanceof Object); // true
可以看到Man
的原型链对象是直接指向Object
的,而people
则先指向Name
再指向Object
,这里可以将对象看作是小孩、接口看作小孩的出生设置,类看作小孩的父亲。接口中的方法属性可以各种组合然后继承到一个接口中作为小孩的出生设置,小孩出生后可以后天的去实现接口中的方法改变其中的属性值;而类就好比小孩的父亲,小孩的属性都继承自父类,可以根据prototype
做亲子关系鉴定。如上代码所示,people
和person
两个类是一样的,但是因为创建方式不一样,造成的结果也不一样,这里我之前弄混淆了,首先看people
,直接new
了,代表people
类是实例化的,也就是类中的属性全部都是实现了的,而{}是类型断言了一个空对象,对象也是实例化的,但是他没有属性,后天去往空对象添加属性的时候需要满足Person
类的属性进行添加。
补充一下抽象类的概念
抽象类是一个特殊的类,
- 包含了抽象方法的类就是抽象类,抽象类不一定包含抽象方法。
- 抽象类不能直接实例化必须通过其派生类/子类进行实例化。
- 抽象类的派生类/子类必须要实现抽象类中的所有抽象方法才可以实例化,否则依旧是抽象类。
3.模块化开发
差异性:require表示的是运行时加载。而import表示的是编译时加载(效率更高)
CommonJS
整个后台部分还是通过CommonJS去进行开发的
- CommonJS三种写法
const fs = require('fs')
exports.fs = fs
module.exports = fs
- 传参模块的代码
const time = function(type){
const date = new Date();
Y = date.getFullYear();
M = date.getMonth()+1;
D = date.getDate();
h = date.getHours();
m = date.getMinutes();
s = date.getSeconds();
if(type === 1){
return Y+"-"+M+"-"+D+" "+h+":"+m+":"+s
}
if(type === 2){
return Y+"-"+M+"-"+D
}
}
exports.time = time
ES6 Module
// 选择性导出导入
import { Action } from '../components/index';
export default { Action };
// 整体重命名对象导出导入
import * as service from './service';
export function a(){}
export function b(){}
// 整体导出
import store from '@/store/index';
export default store
项目问题反馈
前端部分:
- 主要问题来源于接口对接,接口数据结构不满足要求需要自信进行数据处理。
- 次要问题来源于vue全家桶的掌握程度,细节部分离不开文档。
- 常见问题来源于字段和修改逻辑的耦合程度。 后端问题:
- 主要问题来源于前期设计逻辑思路,考虑不充分。
- 次要问题来源于数据格式未考虑充分。
- 常见问题来源于字段和修改逻辑的耦合程度。 解决方案:
- 方案一:培养良好的整体逻辑思维,测试思维
- 方案二:以一端为主另一端为辅合作性开发
项目技术架构
前端:vue全家桶+ElementUI+es6+sass
后台:node.js+es6+CommonJS+sequelize+koa2+mysql
部署:nginx+pm2
又了解到egg基于koa的后台框架有待学习