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 相关文章推荐
Jquery 高亮显示文本中重要的关键字
Dec 24 Javascript
jQuery 拖动层(在可视区域范围内)
May 24 Javascript
Javascript实现可旋转的圆圈实例代码
Aug 04 Javascript
js实现的彩色方块飞舞奇幻效果
Jan 27 Javascript
解决JS组件bootstrap table分页实现过程中遇到的问题
Apr 21 Javascript
微信小程序 增、删、改、查操作实例详解
Jan 13 Javascript
React Native第三方平台分享的实例(Android,IOS双平台)
Aug 04 Javascript
基于webpack 实用配置方法总结
Sep 28 Javascript
浅析js中mvvm模式实现的原理
Oct 06 Javascript
vue实现固定位置显示功能
May 30 Javascript
Vue Element UI + OSS实现上传文件功能
Jul 31 Javascript
vue中使用element ui的弹窗与echarts之间的问题详解
Oct 25 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
htm调用JS代码
2007/03/15 Javascript
js简单实现让文本框内容逐个字的显示出来
2013/10/22 Javascript
JS获取当前日期和时间的简单实例
2013/11/19 Javascript
javascript闭包入门示例
2014/04/30 Javascript
js实现div闪烁原理及实现代码
2014/06/24 Javascript
Javascript中this的用法详解
2014/09/22 Javascript
jQuery中clearQueue()方法用法实例
2014/12/29 Javascript
jquery中JSON的解析方式
2015/03/16 Javascript
javascript表格的渲染组件
2015/07/03 Javascript
jQuery实现二级下拉菜单效果
2016/01/05 Javascript
jQuery设置聚焦并使光标位置在文字最后的实现方法
2016/08/02 Javascript
让编辑器支持word复制黏贴、截屏的js代码
2016/10/17 Javascript
Bootstrap栅格系统学习笔记
2016/11/25 Javascript
前端JS面试中常见的算法问题总结
2016/12/23 Javascript
node.js利用socket.io实现多人在线匹配联机五子棋
2018/05/31 Javascript
解决iview多表头动态更改列元素发生的错误的方法
2018/11/02 Javascript
使用webpack4编译并压缩ES6代码的方法示例
2019/04/24 Javascript
Python中replace方法实例分析
2014/08/20 Python
python中类的一些方法分析
2014/09/25 Python
对Python中画图时候的线类型详解
2019/07/07 Python
python matplotlib折线图样式实现过程
2019/11/04 Python
在python中使用pyspark读写Hive数据操作
2020/06/06 Python
Python之字符串的遍历的4种方式
2020/12/08 Python
Amara德国:家居饰品、设计师品牌和豪华礼品
2019/05/20 全球购物
Tenstickers法国:墙贴和装饰贴纸
2019/08/26 全球购物
CSS代码检查工具stylelint的使用方法详解
2021/03/27 HTML / CSS
资产经营总监岗位职责范文
2013/12/01 职场文书
消防器材管理制度
2014/01/28 职场文书
知名企业招聘广告词大全
2014/03/18 职场文书
股东合作协议书范本
2014/04/14 职场文书
大学专科自荐信
2014/06/17 职场文书
组织生活会发言材料
2014/12/15 职场文书
2015年家长学校工作总结
2015/04/22 职场文书
2015年幼儿园中班开学寄语
2015/05/27 职场文书
《夜莺的歌声》教学反思
2016/02/22 职场文书
2016孝老爱亲模范事迹材料
2016/02/26 职场文书