JS实现MVC、MVVM模型

71 阅读1分钟

MVC

image.png

// model
var myapp = {} // 创建应用对象

myapp.Model = function () {
    let val = 0

    this.add = function (v) {
        val += v
    }

    this.sub = function (v) {
        if (val > 0) val -= v
    }

    this.getVal = () => val

    /**观察者模式 */
    const _this = this
    const views = []

    this.register = (view) => views.push(view)

    this.notify = () => {
        for (let i = 0; i < views.length; i++) {
            views[i].render(_this)
        }
    }
}

myapp.View = (controller) => {
    // 视图上获取元素
    let $num = document.querySelector('#num'), 
        $incBtn = document.querySelector('#incBtn'), 
        $decBtn = document.querySelector('#decBtn')

    this.render = function (model) {
        $num.innerHTML = model.getVal() + '元'
    }
 

    $incBtn.addEventListener('click', controller.increase)
    $decBtn.addEventListener('click', controller.decrease)
}

myapp.Controller = function () {
    let model = null, view = null

    this.init = function () {
        // 初始化Model、View
        model = new myapp.Model()
        view = new myapp.View(this)

        model.register(view)
        model.notify()
    }

    this.increase = () => {
        model.add(1)
        model.notify()
    }

    this.decrease = () => {
        model.sub(1)
        model.notify()
    }
}


    // init
    (function () {
        const controller = new myapp.Controller()
        controller.init()
    })()

MVVM

image.png

// model
let data = {
  val: 0
}

// view
<div id="app">
  <div>
    <span>{{val}}元</span>
  </div>
  <div>
    <button v-on:click="sub(1)">-</button>
    <button v-on:click="add(1)">+</button>
  </div>
</div>

// controller
new Vue({
  el: '#app',
  data: data,
  methods: {
    add(v) {
      this.val += v;
    },
    sub(v) {
      this.val -= v;
    }
  }
})

严格来讲,vue和react都不是MVVM

React: ui = render(data) 单向数据流

Vue2: ref 直接操作真实dom,跳过了ViewModel

Vue3: 改进了ref直接操作真实dom,变为了给VDom增加ref属性去操作