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批量设置样式的三种方法不推荐使用with
Feb 25 Javascript
兼容ie、firefox的图片自动缩放的css跟js代码分享
Aug 12 Javascript
Jquery 动态生成表格示例代码
Dec 24 Javascript
jquery获取当前日期的方法
Jan 14 Javascript
Javascript基础教程之定义和调用函数
Jan 18 Javascript
Node.js v8.0.0正式发布!看看带来了哪些主要新特性
Jun 02 Javascript
vue服务端渲染的实例代码
Aug 28 Javascript
Parcel 打包示例(React HelloWorld)
Jan 16 Javascript
vue-cli基础配置及webpack配置修改的完整步骤
Oct 20 Javascript
原生js实现随机点餐效果
Dec 10 Javascript
JS+HTML实现自定义上传图片按钮并显示图片功能的方法分析
Feb 12 Javascript
Nuxt默认模板、默认布局和自定义错误页面的实现
May 11 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
php上传功能集后缀名判断和随机命名(强力推荐)
2015/09/10 PHP
Yii框架数据模型的验证规则rules()被执行的方法
2016/12/02 PHP
PHP生成图片验证码功能示例
2017/01/12 PHP
tp5递归 无限级分类详解
2019/10/18 PHP
js防止页面被iframe调用的方法
2014/10/30 Javascript
Javascript基础教程之函数对象和属性
2015/01/18 Javascript
通过JS判断联网类型和连接状态的实现代码
2015/04/01 Javascript
jQuery实现的背景动态变化导航菜单效果
2015/08/24 Javascript
JavaScript基础知识及常用方法总结
2016/01/10 Javascript
promise和co搭配生成器函数方式解决js代码异步流程的比较
2018/05/25 Javascript
Layui组件Table绑定行点击事件和获取行数据的方法
2018/08/19 Javascript
解决node-sass偶尔安装失败的方法小结
2018/12/05 Javascript
JS重学系列之聊聊new操作符
2019/03/04 Javascript
微信小程序实现的绘制table表格功能示例
2019/04/26 Javascript
React组件对子组件children进行加强的方法
2019/06/23 Javascript
Vue触发隐藏input file的方法实例详解
2019/08/14 Javascript
JS实现水平移动与垂直移动动画
2019/12/19 Javascript
vue用elementui写form表单时,在label里添加空格操作
2020/08/13 Javascript
[52:57]2014 DOTA2国际邀请赛中国区预选赛 LGD-CDEC VS HGT
2014/05/21 DOTA
Python中操作MySQL入门实例
2015/02/08 Python
解决Python requests 报错方法集锦
2017/03/19 Python
Python3+PyInstall+Sciter解决报错缺少dll、html等文件问题
2019/07/15 Python
python爬虫之爬取百度音乐的实现方法
2019/08/24 Python
pycharm下配置pyqt5的教程(anaconda虚拟环境下+tensorflow)
2020/03/25 Python
Anconda环境下Vscode安装Python的方法详解
2020/03/29 Python
python实现控制台输出彩色字体
2020/04/05 Python
用Python进行websocket接口测试
2020/10/16 Python
Superdry极度干燥美国官网:英国制造的服装品牌
2018/11/13 全球购物
波兰品牌鞋履在线商店:Eastend.pl
2020/01/11 全球购物
美国购买韩国护肤和美容产品网站:Althea Korea
2020/11/16 全球购物
基层党组织公开承诺书
2014/03/28 职场文书
教师产假请假条范文
2014/04/10 职场文书
村居抓节水倡议书
2014/05/19 职场文书
放假通知怎么写
2015/08/18 职场文书
2016学校元旦晚会经典开场白台词
2015/12/03 职场文书
python中pandas对多列进行分组统计的实现
2021/06/18 Python