vue实现动态数据绑定


Posted in Javascript onApril 28, 2017

实现的步骤:

1.监听对象属性的读取与变化

Object.defineProperty() 方法会直接在对象上定义一个新的的属性,或者已经存在的属性并且返回这个属性

语法是 Object.defineProperty(obj, prop, descript)

obj: 目标对象

prop: 需要定义或修改的属性的名字

descript: 将被定义或修改的属性的描述符

描述:

这个方法精确添加或修改对象的属性,我们添加的属性是可以枚举的属性(Object.keys()/ for...in)

对象里面存在是属性描述存在的形式是:

数据描述符:拥有可写入或不可以写入的属性(相当于口令密码)

存取描述符:由一对getter-setter 函数功能来描述的属性(方法)

注意:**描述符**必须是两种形式之一,不能同时是两者。

数据描述符和存取描述符均具有以下可选键值:

1.configurable:当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,也能够被删除。默认为 false

2.enumerable:当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false

数据描述符:

1.value:该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。

2.writable:当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false。

存取描述符同时具有以下可选键值:

1.get:一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。

2.set:一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。

示例:

创建属性

var o = {};
Object.defineProperty(o, "a", {value : 37,
                writable : true,
                enumerable : true,
                configurable : true});

console.log(o.a);
Object.defineProperty(o, "b", {get : function(){ /*console.log( bValue)*/ return value },
                set : function(newValue){ bValue = newValue; },
                enumerable : true,
                configurable : true});
o.b = 38;

修改属性

当属性特性(property attribute) writable 设置为false时,表示 non-writable,属性不能被修改。

var o = {}; // 创建一个新对象

Object.defineProperty(o, "a", { value : 37,
                writable : false });

console.log(o.a); // 打印 37
o.a = 25; // 没有错误抛出(在严格模式下会抛出,即使之前已经有相同的值)
console.log(o.a); // 打印 37, 赋值不起作用。

一般的setter 和 getters

var pattern = {
  get: function () {
    return 'I alway return this string,whatever you have assigned';
  },
  set: function () {
    this.myname = 'this is my name string';
  }
};
function TestDefineSetAndGet() {
  Object.defineProperty(this, 'myproperty', pattern);
}
var instance = new TestDefineSetAndGet();
instance.myproperty = 'test';

// 'I alway return this string,whatever you have assigned'
console.log(instance.myproperty);
// 'this is my name string'
console.log(instance.myname);

解题

function Observer(property) {
  this.data = {};
  this.recursion(data);
}

Observer.prototype.recursion = function(obj) {
  var val = null;
  for (key in obj) {
    if(obj.hasOwnProperty(key)) {
      val = obj[val];
      if(typeof val === 'object' && !!val) {
        new Observer(val);
      }
      this.access(key, val);
    }
  }
}

Observer.prototype.access = function(key, val) {
  Object.defineProperty(this.data, key, {
    enumerable: true,
    configurable: true,
    get: function () {
      console.log('你访问了' + key);
      return val
    },
    set: function (newVal) {
      console.log('你设置了' + key);
      console.log('新的' + key + ' = ' + newVal)
      if (newVal === val) return;
      val = newVal
    }
  })
}


let app1 = new Observer({
 name: 'youngwind',
 age: 25
});
let app2 = new Observer({
 university: 'bupt',
 major: 'computer'
});

// 要实现的结果如下:
app1.data.name // 你访问了 name
app1.data.age = 100; // 你设置了 age,新的值为100
app2.data.university // 你访问了 university
app2.data.major = 'science' // 你设置了 major,新的值为 science

多层级对象

当传入的对象是

let app1 = new Observer({
  user: {
    name: "liangshaofeng",
    age: "24"
  },
  address: {
    city: "beijing"
  }
});

递归解决问题!!

function Observer(data) {
  this.data = data;
  this.recursion(this.data);
}

Observer.prototype.recursion = function(obj) {
  var val = null;
  for (key in obj) {
    if(obj.hasOwnProperty(key)) {
      val = obj[key];
      if(typeof val === 'object' && !!val) {
        new Observer(val);
      }
      this.access(key, val);
    }
  }
}

Observer.prototype.access = function(key, val) {
  Object.defineProperty(this.data, key, {
    enumerable: true,
    configurable: true,
    get: function () {
      console.log('你访问了' + key);
      return val
    },
    set: function (newVal) {
      console.log('你设置了' + key);
      console.log('新的' + key + ' = ' + newVal)
      if (newVal === val) return;
      val = newVal
    }
  })
}

let app1 = new Observer({
  user: {
    name: "liangshaofeng",
    age: "24"
  },
   address: {
    city: "beijing"
  }
});


app1.data.user.name // 你访问了 name
app1.data.user.age = 100; // 你设置了 age,新的值为100

增加事件系统

// 事件系统
function Event() {
  this.events = {};
}

Event.prototype.emit = function(attr, val, newVal) {
  this.events[attr] && this.events[attr].forEach(function(item){
    item(val, newVal)
  })
}

Event.prototype.on = function(attr, callback){
 if(this.events[attr]){
  this.events[attr].push(callback);
 }else{
  this.events[attr] = [callback];
 }
}



function Observer(data) {
  this.data = data;
  this.recursion(this.data);
  this.eventsBus = new Event();
}

Observer.prototype.recursion = function(obj) {
  var val = null;
  for (key in obj) {
    if(obj.hasOwnProperty(key)) {
      val = obj[key];
      if(typeof val === 'object' && !!val) {
        new Observer(val);
      }
      this.access(key, val);
    }
  }
}

Observer.prototype.access = function(key, val) {
  var self = this;
  Object.defineProperty(this.data, key, {
    enumerable: true,
    configurable: true,
    get: function () {
      console.log('你访问了' + key);
      return val
    },
    set: function (newVal) {
      if (typeof newVal === 'object' && !!newVal) {
        new Observer(newVal);
      }
      console.log('你设置了' + key);
      console.log('新的' + key + ' = ' + newVal)
      self.eventsBus.emit(key, val, newVal);
      if (newVal === val) return;
      val = newVal
    }
  })
}
Observer.prototype.$watch = function(attr, callback){
 this.eventsBus.on(attr, callback);
}

let app1 = new Observer({
  user: {
    name: "liangshaofeng",
    age: "24"
  },
   address: {
    city: "beijing"
  }
});


app1.data.user.name // 你访问了 name
app1.data.user.age = 100; // 你设置了 age,新的值为100

app1.data.user.name = {
  lastName: 'liang',
  firstName: 'shaofeng'
 };
 app1.data.user.name.lastName;
 // 这里还需要输出 '你访问了 lastName '
 app1.data.user.name.firstName = 'lalala';
 // 这里还需要输出 '你设置了firstName, 新的值为 lalala'
 var app1 = new Observer({
  name: 'liujianhuan',
  age: 25,
  company: 'Qihoo 360',
  address: 'Chaoyang, Beijing'
})

app1.$watch('age', function(oldVal, newVal){
  console.log(`我的年龄变了,原来是: ${oldVal}岁,现在是:${newVal}岁了`)
})

app1.$watch('age', function(oldVal, newVal){
  console.log(`我的年龄真的变了诶,竟然年轻了${oldVal - newVal}岁`)
})

app1.data.age = 20;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js 页面执行时间计算代码
Mar 04 Javascript
javascript天然的迭代器
Oct 29 Javascript
鼠标滑上去后图片放大浮出效果的js代码
May 28 Javascript
jquery时间下拉框小例子
Apr 15 Javascript
JQuery调用WebServices的方法和4个实例
May 06 Javascript
详解addEventListener的三个参数之useCapture
Mar 16 Javascript
JavaScript使用Math.Min返回两个数中较小数的方法
Apr 06 Javascript
基于JavaScript实现文字超出部分隐藏
Feb 29 Javascript
JavaScript中对JSON对象的基本操作示例
May 21 Javascript
微信小程序 安全包括(框架、功能模块、账户使用)详解
Jan 16 Javascript
d3.js中冷门却实用的内置函数总结
Feb 04 Javascript
微信小程序实现上传图片裁剪图片过程解析
Aug 22 Javascript
Vue实现动态响应数据变化
Apr 28 #Javascript
解决浏览器会自动填充密码的问题
Apr 28 #Javascript
JS实现简单的天数计算器完整实例
Apr 28 #Javascript
jQuery实现jQuery-form.js实现异步上传文件
Apr 28 #jQuery
js实现移动端编辑添加地址【模仿京东】
Apr 28 #Javascript
angularjs中使用ng-bind-html和ng-include的实例
Apr 28 #Javascript
d3.js入门教程之数据绑定详解
Apr 28 #Javascript
You might like
全国FM电台频率大全 - 11 浙江省
2020/03/11 无线电
Base64在线编码解码实现代码 演示与下载
2011/01/08 PHP
使用PHP强制下载PDF文件示例
2014/01/17 PHP
图解找出PHP配置文件php.ini的路径的方法
2014/08/20 PHP
php广告加载类用法实例
2014/09/23 PHP
laravel orm 关联条件查询代码
2019/10/21 PHP
php屏蔽错误及提示的方法
2020/05/10 PHP
js实现运行代码需要刷新的解决方法
2007/08/18 Javascript
Javascript 函数对象的多重身份
2009/06/28 Javascript
JavaScript中Object和Function的关系小结
2009/09/26 Javascript
JavaScript中的全局对象介绍
2015/01/01 Javascript
在JavaScript中操作时间之getYear()方法的使用教程
2015/06/11 Javascript
Javascript实现快速排序(Quicksort)的算法详解
2015/09/06 Javascript
jQuery实现仿微软首页感应鼠标变化滑动窗口效果
2015/10/08 Javascript
JS库 Highlightjs 添加代码行号的实现代码
2017/09/13 Javascript
Node.js对MongoDB进行增删改查操作的实例代码
2019/04/18 Javascript
微信小程序--特定区域滚动到顶部时固定的方法
2019/04/28 Javascript
详解es6新增数组方法简便了哪些操作
2019/05/09 Javascript
Windows下实现Python2和Python3两个版共存的方法
2015/06/12 Python
PYTHON基础-时间日期处理小结
2018/05/05 Python
浅谈python 读excel数值为浮点型的问题
2018/12/25 Python
python虚拟环境完美部署教程
2019/08/06 Python
python rsync服务器之间文件夹同步脚本
2019/08/29 Python
django数据模型on_delete, db_constraint的使用详解
2019/12/24 Python
python输出pdf文档的实例
2020/02/13 Python
Python 实现图片转字符画的示例(静态图片,gif皆可)
2020/11/05 Python
世界上最大的汽车共享网站:Zipcar
2017/01/14 全球购物
俄罗斯香水和化妆品在线商店:Aroma-butik
2020/02/28 全球购物
TCP协议通讯的过程和步骤是什么
2015/10/18 面试题
《赵州桥》教学反思
2014/02/17 职场文书
2014年五四青年节活动方案
2014/03/29 职场文书
志愿者爱心公益活动策划方案
2014/09/15 职场文书
个人融资协议书范本两则
2014/10/15 职场文书
MySQL锁机制
2021/04/05 MySQL
Pytorch实现图像识别之数字识别(附详细注释)
2021/05/11 Python
Nginx实现负载均衡的项目实践
2022/03/18 Servers