美文网首页
谈谈js的双向绑定

谈谈js的双向绑定

作者: 文舞双全 | 来源:发表于2017-04-26 15:18 被阅读0次

实现的做法

  • 发布订阅者模式
  • 脏值检查
  • 数据劫持

先从一个简单的开始



letmvvm={};

Object.defineProperty(mvvm,'hello', {

get:function() {

returndocument.getElementsByTagName("input")[0].value;

},

set:function(val) {

document.getElementsByTagName("input")[0].value=val;

document.getElementsByTagName('span')[0].innerHTML=val;

console.log("set被调用了,参数是:", val)

}

})

document.getElementsByTagName("input")[0].addEventListener('keyup',function(e) {

mvvm.hello=e.target.value;

})

这里利用了Object.defineProperty()里的getter setter方法,在修改mvvm对象上的hello属性时候,我们可以做一些事情,当触发set的时候,把input,span的值都修改成新的val,然后在input上监听keyupevent, 触发keyup,将mvvm.hello设置为当前事件对象的value,同时触发了set,改变了input,span的值

问题来了

在上例中,我们只是监听了input的keyup事件,而且只是绑定了mvvm.如果有很多obj呢,如果不只是input呢,如果不只是input的keyup呢,所以我们需要做一个

通用的模式

Vue的数据绑定实现


Two-way data-binding

{{ text }}

function observe(obj, vm) {

Object.keys(obj).forEach(function(key) {

defineReactive(vm, key, obj[key]);

});

}

function defineReactive(obj, key, val) {

var dep=newDep();

Object.defineProperty(obj, key, {

get:function() {

// 添加订阅者watcher到主题对象Dep

if(Dep.target) dep.addSub(Dep.target);

returnval

},

set:function(newVal) {

if(newVal===val)return

val=newVal;

// 作为发布者发出通知

dep.notify();

}

});

}

function nodeToFragment(node, vm) {

var flag=document.createDocumentFragment();

var child;

while(child=node.firstChild) {

compile(child,vm);

flag.append(child);// 将子节点劫持到文档片段中

}

return flag;

}

function compile(node, vm) {

var reg=/\{\{(.*)\}\}/;

// 节点类型为元素

if(node.nodeType===1) {

var attr = node.attributes;

// 解析属性

for(vari=0;i

if(attr[i].nodeName=='v-model') {

varname=attr[i].nodeValue;// 获取v-model绑定的属性名

node.addEventListener('input',function(e) {

// 给相应的data属性赋值,进而触发该属性的set方法

vm[name]=e.target.value;

});

node.value=vm[name];// 将data的值赋给该node

node.removeAttribute('v-model');

}

};

newWatcher(vm,node,name, 'input');

}

// 节点类型为text

if(node.nodeType===3) {

if(reg.test(node.nodeValue)) {

varname=RegExp.$1;// 获取匹配到的字符串

name=name.trim();

newWatcher(vm, node, name,'text');

}

}

}

function Watcher(vm, node, name, nodeType) {

Dep.target=this;

this.name=name;

this.node=node;

this.vm=vm;

this.nodeType=nodeType;

this.update();

Dep.target=null;

}

Watcher.prototype = {

update:function() {

this.get();

if(this.nodeType=='text') {

this.node.nodeValue=this.value;

}

if(this.nodeType=='input') {

this.node.value=this.value;

}

},

// 获取data中的属性值

get:function() {

this.value=this.vm[this.name];// 触发相应属性的get

}

}

function Dep() {

this.subs=[]

}

Dep.prototype = {

addSub:function(sub) {

this.subs.push(sub);

},

notify:function() {

this.subs.forEach(function(sub) {

sub.update();

});

}

};

function Vue(options) {

this.data=options.data;

var data=this.data;

observe(data, this);

var id=options.el;

var dom=nodeToFragment(document.getElementById(id), this);

// 编译完成后,将dom返回到app中

document.getElementById(id).appendChild(dom);

}

var vm = new Vue({

el:'app',

data: {

text:'hello world'

}

});

相关文章

  • 谈谈js的双向绑定

    实现的做法 发布订阅者模式 脏值检查 数据劫持 先从一个简单的开始 这里利用了Object.definePrope...

  • js实现双向数据绑定

    js双向绑定几种方法的介绍 使用Object.defineProperty实现简单的js双向绑定剖析Vue原理&实...

  • Vue.js数据双向绑定实现

    目前的几种主流前端框架中,react是单向绑定,而angular.js和vue.js是双向绑定,实现双向绑定的方法...

  • JS双向数据绑定

    双向数据绑定简述 双向数据绑定,可以将JS对象的属性绑定到DOM节点上,实现JS对象跟DOM节点的同名属性的关联,...

  • Vue之表单双向数据绑定和组件

    三、表单双向数据绑定和组件 目录:双向数据绑定、组件 1.双向数据绑定 1)什么是双向数据绑定Vue.js是一个M...

  • 双向绑定和单向绑定

    Vue 的双向绑定(也是 Angular 的双向绑定)有这些功能: 只要 JS 改变了 view.number 或...

  • vue双向绑定原理

    Vue.js双向绑定的实现原理

  • 2 数据绑定

    1 通过以下代码体验Vue.js最核心的功能——数据的双向绑定 双向绑定v-mod...

  • Javascript 简单的双向绑定实现

    现代 JS 中数据双向绑定 (Two-way Data Binding) 已经是一个很常见的概念了,那么双向绑定是...

  • Vue框架基础

    原生js与Vue框架的区别 用原生实现双向数据绑定 用Vue实现双向数据绑定 Vue是一个javaScript框架...

网友评论

      本文标题:谈谈js的双向绑定

      本文链接:https://www.haomeiwen.com/subject/vswizttx.html