vue.js 雙向數據綁定的實現

vue.js 雙向數據綁定的實現javascript

1.首先定義構造函數html

var Vue = function (params) { 
  this.el = document.getElementById(params.el) 
  this.data = params.data 
  this.init() 
} 
Vue.prototype = { 
  init: function () { 
    this.updateView() 
    this.bindData() 
    this.bindModel() 
  } 
} 

 

2.在初始化方法中先定義一個視圖的更新方法。這樣一個簡單的單向綁定就已經實現了。vue

Vue.prototype.updateView = function () {
  // v-text 視圖更新
  var doms = this.el.querySelectorAll('[v-text]')
  for (var i = 0; i < doms.length; i++) {
    var bindName = doms[i].getAttribute('v-text')
    doms[i].innerHTML = this.data[bindName]
  }
  // v-model 視圖更新
  var modelDoms = this.el.querySelectorAll('[v-model]')
  for (var i = 0; i < modelDoms.length; i++) {
    var modelBindName = modelDoms[i].getAttribute('v-model')
    modelDoms[i].value = this.data[modelBindName] || ''
  }
}

 

3.而後要創建數據層到視圖層的單向聯繫。java

Vue.prototype.bindData = function () {
  var data = this.data
  for (var key in data) {
    this.defineObject(data, key, data[key])
  }
}
Vue.prototype.defineObject = function (obj, prop, value) {
  var value = value || ''
  var _that = this
  Object.defineProperty(obj, prop, {
    get: function () {
      return value
    },
    set: function (newVal_) {
      value = newVal_
      _that.updateView()
    }
  })
}

 

4.創建視圖層到數據層的聯繫。也就是v-model的實現。
 dom

// model數據綁定
Vue.prototype.bindModel = function () {
  var data = this.data
  var _that = this
  var doms = this.el.querySelectorAll('[v-model]')
  for (var i = 0; i < doms.length; i++) {
  var bindName = doms[i].getAttribute('v-model')
    doms[i].value = data[bindName] || ''
    if (document.addEventListener) {
      doms[i].addEventListener('keyup', function (event) {
        e = event || window.event
        data[bindName] = e.target.value
      }, false)
    } else {
      doms[i].attachEvent('onkeyup', function (event) {
        e = event || window.event
        data[bindName] = e.target.value
      }, false)
    }
  }
}

 

至此一個簡單的雙向數據綁定就已經實現了。函數

詳細demo。測試

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <div id="vueTest">
        <input type="text" name="cc" v-model="test1">
        <div v-text="test1"></div>
        <div v-text="test1"></div>
        <div v-text="test2"></div>
    </div>
</body>
    <script type="text/javascript">
        var Vue = function (params) {
            this.el = document.getElementById(params.el)
            this.data = params.data
            this.init()
        }

        Vue.prototype = {
            init: function () {
                this.updateView()
                this.bindData()
                this.bindModel()
            },
            // 更新視圖
            updateView: function () {
                // v-text 視圖更新
                var doms = this.el.querySelectorAll('[v-text]')
                for (var i = 0; i < doms.length; i++) {
                    var bindName = doms[i].getAttribute('v-text')
                    doms[i].innerHTML = this.data[bindName]
                }
                // v-model 視圖更新
                var modelDoms = this.el.querySelectorAll('[v-model]')
                for (var i = 0; i < modelDoms.length; i++) {
                    var modelBindName = modelDoms[i].getAttribute('v-model')
                    modelDoms[i].value = this.data[modelBindName] || ''
                }
            },
            // 數據綁定
            bindData: function () {
                var data = this.data
                for (var key in data) {
                    this.defineObject(data, key, data[key])
                }
            },
            // model數據綁定
            bindModel: function () {
                var data = this.data
                var _that = this
                var doms = this.el.querySelectorAll('[v-model]')
                for (var i = 0; i < doms.length; i++) {
                    var bindName = doms[i].getAttribute('v-model')
                    doms[i].value = data[bindName] || ''
                    if (document.addEventListener) {
                        doms[i].addEventListener('keyup', function (event) {
                            e = event || window.event
                            data[bindName] = e.target.value
                        }, false)
                    } else {
                        doms[i].attachEvent('onkeyup', function (event) {
                            e = event || window.event
                            data[bindName] = e.target.value
                        }, false)
                    }
                }
            },
            // 數據劫持
            defineObject: function (obj, prop, value) {
                var value = value || ''
                var _that = this
                Object.defineProperty(obj, prop, {
                    get: function () {
                        return value
                    },
                    set: function (newVal_) {
                        value = newVal_
                        _that.updateView()
                    }
                })
            },
        }

        var vue = new Vue({
            el: 'vueTest',
            data: {
                test1: 'this is a test',
                test2: 'this is a test2'
            }
        })

        // 測試用
        setTimeout(function () {
            vue.data.test1 = '5 second delay'
        }, 5000)
    </script>
</html>

 

相關文章
相關標籤/搜索