以前學過ThinkPHP,在初學的時候,幾乎沒有任何基礎。當時被這種MVC分離的框架搞暈了,都不知道數據是怎麼在各層之間傳遞的。
後來發現,搞懂MVC的關鍵,就是理解數據流。當時我還作了一張很大的圖片,記錄了MVC和數據庫之間傳值的方式和CRUD的過程。(因爲這張圖片是好久之前製做的,可能不徹底正確)
數據庫
當把數據流融會貫通之時,就是開悟之日。瀏覽器
先從總體上分析瀏覽器、先後臺、數據庫之間的數據流:服務器
上圖只是爲了搞清楚數據在各個部門間的傳遞過程,圖中的前臺代碼和後臺代碼實際上都是MVC,只是爲了方便理解,在圖中簡化了。框架
接下來,展開它們:post
用文字來解釋一下上圖的數據流:學習
對以上過程的一些說明:this
//定義請求地址url const url = 'http://localhost:8080/Klass'; //定義須要請求的對象 const klass = new Klass(undefined, this.name.value, this.teacher ); //執行http請求,並訂閱 //使用觀察者模式,若是成功或失敗,則執行對應的代碼 this.httpClient.post(url, klass) .subscribe(() => { console.log('保存成功'); this.router.navigateByUrl('/klass', {relativeTo: this.route}); }, (response) => { console.log(`向${url}發起的post請求發生錯誤` + response); });
//V層代碼 <td>{{student.name}}</td>
//C層代碼 username: string; //V層代碼 <input type="text" id="username" name="username" [(ngModel)]="username">
//C層代碼 public onSubmit(): void { } //V層代碼 <form id="teacherAddForm" (ngSubmit)="onSubmit()"> </form>
//C層代碼 onDelete(klass: Klass): void { } //V層代碼 <button (click)="onDelete(klass)">刪除</button>
//StudentService(服務層) Student save(Student student); //StudentServiceImpl(接口的具體實現) public Student save(Student student) { return this.studentRepository.save(student); } //StudentController(C層,調用M層Save()) public Student save(@RequestBody Student student) { return studentService.save(student); }
//StudentServiceImpl (服務層接口的具體實現) public Page<Student> findAll(Pageable pageable) { return this.studentRepository.findAll(pageable); } //StudentRepository (倉庫:執行請求數據庫的動做) default Page findAll(String name, String sno, Klass klass, @NotNull Pageable pageable) { Assert.notNull(pageable, "傳入的Pageable不能爲null"); Specification<Student> specification = StudentSpecs.containingName(name) .and(StudentSpecs.startWithSno(sno)) .and(StudentSpecs.belongToKlass(klass)); return this.findAll(specification, pageable); }
對於這些MVC分離或者先後臺分離的框架,理解它們的關鍵,就在於搞明白數據從哪來到哪去。這是站在一個宏觀的總體的角度去看待問題。url
若是不理解數據流,只關注代碼自己,那麼代碼就只會是一個個片斷,而沒法在思惟中連成總體。spa
從我一個小白的角度來看,搞明白數據流,是學習如何使用框架的良好開端。code