当前位置:   article > 正文

深入代码理解MVC模式、MVP模式和MVVM模式

分析项目代码的mvc模式

作者: 麦乐

不知道看了多少遍有关三者区别的文章,每个都是有图有真相,但是当被问起三者的区别,还是觉得说不清楚,因为没有真正的理解。

MVC

如下图,View和Controler都可以访问Model,Model中数据流动方法都是双向的。也就是说V和C都可以改变数据,也可以获取数据。

8.png

上图在代码层面表现如下:

基本结构:

  1. function createMVC() {
  2. var MVC = {};
  3. MVC.model = function() {
  4. }
  5. MVC.view = function() {
  6. }
  7. MVC.controler = function() {
  8. }
  9. }

比如说要实现一个新闻列表模块,实现数据层:

  1. function createMVC() {
  2. var MVC = {};
  3. MVC.model = function() {
  4. var M = {}
  5. // 通常是从后端获取的
  6. M.data = {
  7. newsList = [
  8. {
  9. text: '新闻一',
  10. icon: '',
  11. url: 'https://www.baidu.com'
  12. },
  13. {
  14. text: '新闻二',
  15. icon: '',
  16. url: 'https://blog.csdn.net'
  17. }
  18. ]
  19. }
  20. M.config= {
  21. // 新闻动画控制数据
  22. }
  23. return {
  24. getData: function(key) {
  25. return M.data[key]
  26. },
  27. setData: function(key, value) {
  28. M.data[key] = value;
  29. return this;
  30. },
  31. getConfig: function(key) {
  32. return M.config[key]
  33. },
  34. setConfig: function(key, value) {
  35. M.config[key] = value;
  36. return this;
  37. }
  38. }
  39. }()
  40. MVC.view = function() {
  41. }
  42. MVC.controler = function() {
  43. }
  44. }

实现视图层,负责根据数据生产html模版:

  1. MVC.view = function() {
  2. var M = MVC.model;
  3. var V = {
  4. createNewsList: function() {
  5. var html = '';
  6. var data = M.getData('newsList');
  7. if(!(data && data.length)) return;
  8. // 创建视图容器
  9. var dom = $.create('div', {
  10. class: 'news-contanier'
  11. })
  12. // 创建视图容器模版
  13. var tp1 = {
  14. container: [
  15. '<ul class="news-content">{#content#}</ul>'
  16. ].join(''),
  17. item: [
  18. "<li class='news-item'>",
  19. "<a href='{#url#}'></a>",
  20. "<span>{#text}</span>",
  21. "</li>",
  22. ].join('')
  23. }
  24. for(var i = 0; i < data.length; i++) {
  25. html += $.formateString(tp1.item, data[i])
  26. }
  27. dom.html($.formateString(tp1.container, {content: html})).appendTo('body')
  28. }
  29. };
  30. return function(v) {
  31. V[v]()
  32. }
  33. }()

实现控制层,调用上一层的生产html功能,添加需要的业务逻辑:

  1. MVC.controler = function() {
  2. var newsListData = MVC.model.getData('newsList');
  3. var renderNewsList = MVC.view('createNewsList');
  4. var C = {
  5. initNewsList: function() {
  6. renderNewsList();
  7. $('li','news-list').on('mouseover', function() {
  8. // 处理逻辑交互
  9. this.addClass('show')
  10. })
  11. }
  12. }
  13. c.initNewsList()
  14. }()

这样很好的做到了数据层,试图层,控制层(业务逻辑)的分离。这就是经典的MVC模型,这么看是不是更好理解一些。

总结:

优点:

1.各施其职,互不干涉

在MVC模式中,三个层各施其职,所以如果一旦哪一层的需求发生了变化,就只需要更改相应的层中的代码而不会影响到其它层中的代码。

2.有利于开发中的分工

在MVC模式中,由于按层把系统分开,那么就能更好的实现开发中的分工。网页设计人员可以进行开发视图层中的JSP,对业务熟悉的开发人员可开发业务层,而其它开发人员可开发控制层。

3.有利于组件的复用

分层后更有利于组件的复用。如控制层可独立成一个能用的组件,视图层也可做成通用的操作界面。

缺点:

1.视图和控制器联系紧密,耦合性比较大,没有控制器就无法生成视图。视图的大部分交互也都在控制层实现。

2.数据流向难以控制,视图层和控制层都可以获取数据,改变数据。

3.增加了结构复杂度。

MVP

View层不直接访问数据层,而是通过对Presenter(管理器层)实现对Model数据的访问。 D.png

基本结构:

  1. (function(window) {
  2. var MVP = function() {};
  3. MVP.model = function() {};
  4. MVP.view = function() {};
  5. MVP.presenter = function() {};
  6. // MVP入口
  7. MVP.init = function() {};
  8. // 可以全局访问
  9. window.MVP = MVP;
  10. })(window)

数据层跟MVC中类似:

  1. MVC.model = function() {
  2. var M = {}
  3. // 通常是从后端获取的
  4. M.data = {
  5. newsList = [
  6. {
  7. text: '新闻一',
  8. icon: '',
  9. url: 'https://www.baidu.com'
  10. },
  11. {
  12. text: '新闻二',
  13. icon: '',
  14. url: 'https://blog.csdn.net'
  15. }
  16. ]
  17. }
  18. M.config= {
  19. // 新闻动画控制数据
  20. }
  21. return {
  22. getData: function(key) {
  23. return M.data[key]
  24. },
  25. setData: function(key, value) {
  26. M.data[key] = value;
  27. return this;
  28. },
  29. getConfig: function(key) {
  30. return M.config[key]
  31. },
  32. setConfig: function(key, value) {
  33. M.config[key] = value;
  34. return this;
  35. }
  36. }
  37. }()

view层跟原来大不一样,不再直接访问数据,而是根据管理层传递进来的字符串转化为需要的模版,再暴露给管理器:

  1. MVP.view = function() {
  2. return function(str) {
  3. // 此处省略N行代码html
  4. return html
  5. }
  6. }();

上面返回函数的功能就是将类似这样的参数:

'li.news-item>a[href=@url]+span{@text}'

转化为类似这样的模版:

  1. [
  2. "<li class='news-item'>",
  3. "<a href='{#url#}'></a>",
  4. "<span>{#text}</span>",
  5. "</li>",
  6. ].join('')

大致实现一下管理层:

  1. MVP.presenter = function() {
  2. var V = MVP.view;
  3. var M = MVP.model;
  4. var C = {
  5. new: function(M, V) {
  6. var data = M.getData();
  7. var tp1 = V('li.news-item>a[href=@url]+span{@text}');
  8. $.create('ul', {
  9. class: 'news-ul'
  10. }).html(
  11. A.formartString(tp1,data)
  12. ).appendTo('#container')
  13. }
  14. }
  15. return {
  16. init: function() {
  17. for(var key in C) {
  18. C[key] && C[key](M, V, key)
  19. }
  20. },
  21. add: function(key, fun) {
  22. C[key] = fun;
  23. return this;
  24. }
  25. }
  26. }();

优点:

1)降低耦合度

(2)模块职责划分明显

(3)代码复用

(4)代码灵活性

MVP的缺点:

由于对视图的渲染放在了Presenter中,所以视图和Presenter的交互会过于频繁。如果Presenter过多地渲染了视图,往往会使得它与特定的视图的联系过于紧密。一旦视图需要变更,那么Presenter也需要变更了。

MVVM

3A0.png

这种模式为试图层定做了一套视图模型(ViewModel),并在视图模型中创建属性和方法,为视图层绑定数据并实现交互。上面所说的控制器或者管理器就是MVVM模型中的ViewModel。

Model层依然是服务端返回的数据模型。而ViewModel充当了一个UI适配器的角色,也就是说View中每个UI元素都应该在ViewModel找到与之对应的属性。除此之外,从Controller抽离出来的与UI有关的逻辑都放在了ViewModel中,这样就减轻了Controller的负担。

把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。

优点:

  • 低耦合:解耦视图和逻辑
  • 独立开发
  • 数据双向绑定,保证了数据的一致性
  • 简单易学

缺点:

  • 数据的双向绑定导致View不容易复用
  • 模块比较大的话占用的内存也比较大
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/581038
推荐阅读
相关标签
  

闽ICP备14008679号