MVC与MVVM的特性和理解

413 阅读6分钟

MVC

Model 数据层

  • 主要是操作数据库的 CRUD,职能单一,仅仅针对数据库或者文件数据
    • C: create
    • R: read
    • U: update
    • D: delete
  • 简单的来说这货就是个看管数据的弟弟,上面大佬打个电话过来说要什么数据,这个弟弟想尽办法把数据搞到立马交给大佬Controller,大佬说要修改哪个数据,删除哪个数据都是这样,屁颠颠跑去干,干完就会把结果交给大佬。

View 视图层

  • 每当用户操作了界面,如果需要进行业务处理,都会通过网络请求,去请求后端的服务器,此时,我们通过这个请求,就会被后端的 app.js 监听到,
  • 简单的说就是一个简单的 HTML 页面,你肉眼能看到的那种,举个例子就是一个透明玻璃的商店,透过玻璃,用户可以看到商店里面首页数据。当然这些数据怎么放,放多少都是大佬自己去摆放的

Controller 业务逻辑 处理层

  • 用户在 View 页面的请求,在 app.js 中通过 app.use(XXXX.routes()) 监听的路由,被相应的 router.js 所监听。
  • 这里为了保证路由模块的职能单一, router.js 只负责分发路由,不负责具体的业务逻辑
  • 如果涉及到业务处理操作,router.js 就无能为力了,只能交给 Controller.js 模块去操作。
  • Conteoller 模块封装了业务逻辑的处理代码,但是,也是为了保证职责单一,此模块只负责处理业务,不负责处理数据的 CRUD ,如果涉及到了数据的 CRUD 就需要调用 Model层
  • Controller 就像个大佬一样的老板 站在透明玻璃商店的小门口中,用户想要干什么都只能跟大佬说,比如用户想看“美食”的页面,就跟大佬说:“我想要看美食页面-----", 提前设置好的暗号就是"/get/dilicious",大佬看到后立马一个电话打给小弟 Model 层叫它把“美食”的数据搞到手,到手后大佬马上一一按照自己的想法摆放好,摆在哪,摆多少

MVVM

Model 数据

这里的M指的是每个页面中单独的数据。以Vue为例就是每个 components 中的单独的各个 data () { return }

View 前端视图

这里跟上面一样,前端 HTML 页面

VM ViewModel 层,也可以说双向数据绑定层

  • ViewModel用来放置用户交互验证逻辑;视图显示逻辑;发起网络请求和其他代码。
  • 双向绑定就是把每个单独的 data 数据绑定到对应的 HTML 页面上,如果在页面运行过程中,data 的数据发生改变,因为绑定的关系,这个 data 里面对应的数据就会刷新到相应的 HTML 页面中
  • 同理,每个存有单独数据的 HTML 页面,如果对数据进行增删改查,因为绑定的原因,操作的数据会直接修改 data 里面的数据。

举个例子

在 MVC 思想下

  • 比如在某个 View 前端页面,用户想要修改自己的账号昵称,输入结果后点击保存。这个时候保存按钮就会向服务器发出请求,并且是带着请求体过去的,比如/updataUser。请求体的内容是{id: 23423432, name: 张三李四}, 然后 View 视图层就不管了,就这样撇手了,但是这个请求不能直接发给 Model 数据层,所以View就只能发给 Controller 业务逻辑处理层, 他看到是 post 请求过来的,而且请求地址是/updataUser,请求体有ID值,有姓名,就知道是要更新用户数据,然后就会下命令给 Model 数据层叫他把 id=23423432 的用户的 name 改为张三李四。
  • 这里还有一个点,比如用户点击了 我的音乐 按钮,这个时候 View 就会向服务器发出请求要他给页面传回来这个用户的音乐啊什么的,这个时候 Controller 听到了这个请求,一看是 get 请求方式,请求 /mymusic?id=23423432,Controller 就知道了是要音乐数据,然后他就下命令给 Model 层叫他拿 id=23423432 用户的音乐数据出来,然后就不管拉,这里的不管跟 View 一样,命令/请求我已经发出去了,你赶紧把我要的给我就行了。你怎么拿数据不关我的事,反正 Model 数据层就是要通过 本地数据库/网络数据库/普通file文件/json文件等到找到这个数据返回给 Controller,所以Controller 要做的不是去关心 Model 数据层 怎么拿的数据,而是发出命令后,等 Model 层把数据发回来,Controller 就把这个数据发回给 View。
  • 这里我们可以换一种角度去看,当用户查看或者修改某个 View 页面的数据,View 都应该呈现最新的 Model 层的数据给用户看,特别是当用户在 View 的页面中对数据有 CRUD 的操作的化,View 页面应该马上反馈最新的页面数据(最新的 Model 数据)给用户,就是说,View 层的来源于 Model 层的数据一定两种共同变化的。

在 MVVM 思想下

参考这个-写的很好:www.jianshu.com/p/ea9d556d6…

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <form id="form">
    <input type="text" name="student" value="学生" id="student">
    <input type="text" name="age" value="年龄" id="age">
  </form>
  
  <script>
    let form = document.getElementById('form')

    let person = {
      data: {
        student: '张三',
        age: '23'
      }
    }
    // 给 person 绑定一个新属性 student 
    // 绑定的这个属性有 6个东西可以选
    // 数据描述符:value,writable;  值
    // 存取描述符:get,set;         方法
    // 两者皆可共存:configurable,enumerable;    布尔

    // 这个构造函数更多有监听的感觉,下面的给输入框绑定事件可以让 person 里面的 student的值发生的改变的时候,先是输入框事件,person[student] = 修改值, 然后因为 person[student]的值改变了,就调用 set 方法,把person[student]的值 传入进去 data: {student: ''}里面,
    // 所以到这里可以知道 Vue 的模板渲染了,在表单的值中 加入{{ student }},然后会自动触发 get方法,会把data里面事先设置好的值返回过去。渲染在表单中,例如上面设置好的张三
    Object.defineProperty(person, 'student', {
      get () {
        console.log('student被点击了')
        return person.data.student
        console.log(person)
        let student = document.getElementById('student')
      },
      
      // 这个 set 方法 实际上就是把 person 里面的 student 属性跟 data:{student:'张三'}这个属性互相绑定,只要 person[student]发生变化,页面的value也变化,data里面的 student也变化,
      // 又因为
      set (value) {
        console.log('student 开始修改')
        person.data.student = value
        console.log(person)
         let student = document.getElementById('student')
         student.value = value
      }
    })

    // 给所有输入框绑定一个监听事件
    form.addEventListener('input', (e) => {
      // 这个输入框的值
      let value = e.target.value
      
      // 这个输入框的name属性是啥,比如student、age、email等等
      let name = e.target.getAttribute('name')
      
      // 给person这个对象的Student、age、email属性赋值
      person[name] = value
    })
  </script>
</body>
</html>