ITPub博客

首页 > 应用开发 > > javascript前端开发:原生JS模拟vue的双向绑定

javascript前端开发:原生JS模拟vue的双向绑定

作者:飘絮絮絮丶 时间:2019-10-29 09:14:55 0 删除 编辑

现在mvvm框架火得不行,小编我最近也开始研究vue,相比jquery框架,vue的面向数据编程的确可以让我们摆脱操作dom的痛苦专注逻辑本身。


javascript

无论学什么框架,我都喜欢研究底层的东西,vue最核心的功能就是双向绑定,经过几天研究,同javascript实现了一个双向绑定功能。

双向数据绑定底层的思想非常的基本,分为三个步骤:

1.需要一个方法来识别哪个UI元素被绑定了相应的属性

2.需要监视属性和UI元素的变化

3.需要将所有变化传播到绑定的对象和元素

方法一:利用发布订阅模式,订阅数据变更

Html代码:

javascript代码

function DataBinder(object_id) {

//创建一个简单地PubSub对象

var pubSub = {

callbacks: {},

on: function (msg, callback) {

this.callbacks[msg] = this.callbacks[msg] || [];

this.callbacks[msg].push(callback);

},

publish: function (msg) {

this.callbacks[msg] = this.callbacks[msg] || [];

for (var i = 0, len = this.callbacks[msg].length; i < len; i++) {

this.callbacks[msg][i].apply(this, Array.prototype.slice.call(arguments, 1));

}

}

};

var data_attr = "data-bind-" + object_id,

view_attr = 'data-' + object_id,

message = object_id + ":change";

var changeHandler = function (e) {

var target = e.target || e.srcElemnt, //IE8兼容

prop_name = target.getAttribute(data_attr);

if (prop_name && prop_name !== "") {

pubSub.publish(message, target, prop_name, target.value);

}

};

//监听变化事件并代理到PubSub

if (document.addEventListener) {

document.addEventListener("keyup", changeHandler, false);

} else {

//IE8使用attachEvent而不是addEventListener

document.attachEvent("keyup", changeHandler);

}

//PubSub将变化传播到所有绑定元素

pubSub.on(message, function (event, prop_name, new_val) {

var elements = document.querySelectorAll("[" + view_attr + "=" + prop_name + "]"), tag_name;

for (var i = 0, len = elements.length; i < len; i++) {

tag_name = elements[i].tagName.toLowerCase();

if (tag_name === "input" || tag_name === "textarea" || tag_name === "select") {

elements[i].value = new_val;

} else {

elements[i].innerHTML = new_val;

}

}

});

return pubSub;

}

DataBinder('id');

方法二:数据劫持 。

html代码:

借助 Object.defineProperty 方法, Object.defineProperty 方法可以为任何已存在的属性重新定义get与set方法。

(function(window, undefined) {

var addEvent = (function () {

if(window.addEventListener) {

return function (el, type, fn) {

if(el && el.nodeName || el === window) {

el.addEventListener(type, fn, false)

}else if(el.length) {

for(var item of el) {

addEvent(item, type, fn);

}

}

}

}else {

return function (el, type, fn) {

if(el && el.nodeName || el === window) {

el.attachEvent('on' + type, function () {

return fn.call(el, event);

})

}else if(el.length) {

for(var item of el) {

addEvent(item, type, fn);

}

}

}

}

})();

var Hue = function(opt) {

var el = document.querySelector(opt.el);

var data = opt.data || {};

this.el = el;

this.data = data;

this.bindText();

this.bindModel();

return this;

};

Hue.prototype = {

constructor: Hue,

// **前端数据劫持**

defineObj: function(obj, prop, value) {

var _value = value || '', _this = this;

try {

Object.defineProperty(obj, prop, {

get: function() {

return _value;

},

set: function(newVal) {

_value = newVal;

_this.bindText();

},

enumerable: true,

configurable: true

});

} catch (error) {

// IE8+ 才开始支持defineProperty,这也是Vue.js不支持IE8的原因

console.log("Browser must be IE8+ !");

}

},

bindModel: function() {

var modelDOMs = this.el.querySelectorAll('[h-model]'), lenModel = modelDOMs.length;

var _this = this, i, propModel;

for (i = 0; i < lenModel; i++) {

propModel = modelDOMs[i].getAttribute('h-model');

//init value

modelDOMs[i].value = this.data[propModel] || '';

// 前端数据劫持

this.defineObj(this.data, propModel);

}

addEvent(modelDOMs, 'keyup', function (e) {

_this.data[propModel] = e.target.value;

})

},

bindText: function() {

var textDOMs = this.el.querySelectorAll('[h-text]'),

lenText = textDOMs.length,

prppText,

j;

for (j = 0; j < lenText; j++) {

propText = textDOMs[j].getAttribute('h-text');

textDOMs[j].innerHTML = this.data[propText] || '';

}

}

};

window.Hue = Hue;

})(window);

// test...

new Hue({

el: '.app',

data: {

demo: 'Kenny'

}

});

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3167967/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: YashanDB 简介
请登录后发表评论 登录
全部评论

注册时间:2019-09-09

  • 博文量
    2646
  • 访问量
    42234