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 相关文章推荐
JavaScript窗口功能指南之在窗口中书写内容
Jul 21 Javascript
如何在标题栏显示框架内页面的标题
Feb 03 Javascript
基于jquery的button默认enter事件(回车事件)。
May 18 Javascript
javascript常用对话框小集
Sep 13 Javascript
jquery中获得元素尺寸和坐标的方法整理
May 18 Javascript
javascript制作网页图片上实现下雨效果
Feb 26 Javascript
jquery-tips悬浮提示插件分享
Jul 31 Javascript
鼠标点击input,显示瞬间的边框颜色,对之修改与隐藏实例
Dec 26 Javascript
JavaScript中常见的八个陷阱总结
Jun 28 Javascript
JS对象序列化成json数据和json数据转化为JS对象的代码
Aug 23 Javascript
vue路由传参三种基本方式详解
Dec 09 Javascript
vue登录页实现使用cookie记住7天密码功能的方法
Feb 18 Vue.js
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
Terran剧情介绍
2020/03/14 星际争霸
用PHP 快速生成 Flash 动画的方法
2007/03/06 PHP
PHP调用Linux的命令行执行文件压缩命令
2013/01/27 PHP
最常用的8款PHP调试工具
2014/07/06 PHP
php出现web系统多域名登录失败的解决方法
2014/09/30 PHP
php计算整个目录大小的方法
2015/06/19 PHP
android上传图片到PHP的过程详解
2015/08/03 PHP
整理一些JavaScript的IE和火狐的兼容性注意事项
2011/03/17 Javascript
JavaScript mapreduce工作原理简析
2012/11/25 Javascript
基于js disabled="false"不起作用的解决办法
2013/06/26 Javascript
jquery实现按Enter键触发事件示例
2013/09/10 Javascript
JavaScript Math.ceil() 函数使用介绍
2013/12/11 Javascript
详谈jQuery操纵DOM元素属性 attr()和removeAtrr()方法
2015/01/22 Javascript
JavaScript中的DSL元编程介绍
2015/03/15 Javascript
javascript巧用eval函数组装表单输入项为json对象的方法
2015/11/25 Javascript
JS控制静态页面之间传递参数获取参数并应用的简单实例
2016/08/10 Javascript
预防网页挂马的方法总结
2016/11/03 Javascript
微信小程序 详解页面跳转与返回并回传数据
2017/02/13 Javascript
详解Nodejs之静态资源处理
2017/06/05 NodeJs
BootStrap Select清除选中的状态恢复默认状态
2017/06/20 Javascript
Angular.js前台传list数组由后台spring MVC接收数组示例代码
2017/07/31 Javascript
基于jQuery实现的设置文本区域的光标位置
2018/06/15 jQuery
加快Vue项目的开发速度的方法
2018/12/12 Javascript
python中dir函数用法分析
2015/04/17 Python
利用numpy实现一、二维数组的拼接简单代码示例
2017/12/15 Python
python实现电子产品商店
2019/02/26 Python
Python实现二叉树前序、中序、后序及层次遍历示例代码
2019/05/18 Python
pytorch实现CNN卷积神经网络
2020/02/19 Python
Python存储读取HDF5文件代码解析
2020/11/25 Python
HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题
2021/01/19 HTML / CSS
留学生求职信
2014/06/03 职场文书
2014年节能工作总结
2014/12/18 职场文书
学雷锋主题班会教案
2015/08/13 职场文书
小学班级口号大全
2015/12/25 职场文书
python 通过使用Yolact训练数据集
2021/04/06 Python
5分钟教你docker安装启动redis全教程(全新方式)
2021/05/29 Redis