动态数据绑定(一)

我的github iSAM2016

实现的步骤:

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;

vue 动态数据绑定的更多相关文章

  1. Vue.js 数据绑定语法详解

    Vue.js 数据绑定语法详解 一.总结 一句话总结:Vue.js 的模板是基于 DOM 实现的.这意味着所有的 Vue.js 模板都是可解析的有效的 HTML,且通过一些特殊的特性做了增强.Vue ...

  2. Vue动态添加v-model绑定及获取其返回数据

    从数据库拿到的动态数据绑定到页面对应的v-model或者v-bind上,并且根据对页的操作获取到返回的值: 1.首先在data里定义一个数据 timeTip 为一个空数组 data () { retu ...

  3. RDLC报表系列(一) 简单的动态数据绑定和配置

    RDLC系列链接 RDLC报表系列(一) 简单的动态数据绑定和配置  RDLC报表系列(二) 行分组 RDLC报表系列(三) 总计和折叠 RDLC报表系列(四) 矩阵 RDLC报表系列(五) 简单的图 ...

  4. Vue动态组件

    前面的话 让多个组件使用同一个挂载点,并动态切换,这就是动态组件.本文将详细介绍Vue动态组件 概述 通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,可以实现动 ...

  5. vue 双向数据绑定的实现学习(二)- 监听器的实现

    废话:上一篇https://www.cnblogs.com/adouwt/p/9928278.html 提到了vue实现的基本实现原理:Object.defineProperty() -数据劫持 和  ...

  6. vue 双向数据绑定的实现学习(一)

    前言:本系列学习笔记从以下几个点展开 什么是双向数据绑定 双向数据绑定的好处 怎么实现双向数据绑定 实现双向数据数据绑定需要哪些知识点 数据劫持 发布订阅模式 先看看我们要实现的目标是什么,如下动图: ...

  7. vue双向数据绑定的简单实现

    vue双向数据绑定的简单实现 参考教程:链接 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  8. vue动态class——实现tag的选中状态

    vue动态class——实现tag的选中状态 <template> <div class="common-nav"> <div class=" ...

  9. Vue双向数据绑定原理分析(转)

    add by zhj: 目前组里使用的是前端技术是jQuery + Bootstrap,后端使用的Django,Flask等,模板是在后端渲染的.前后端没有分离,这种做法有几个缺点 1. 模板一般是由 ...

随机推荐

  1. 2019windows上安装Mac OS 10.14过程详细截图

    之前VMware12里面的Mac OS10.10升级后,键盘鼠标就用不了了.试了几次都这样,只能重装VMware14, 安装Mac OS 10.14系统.把步骤截下图,分享一下. 一.材料准备 1.虚 ...

  2. asp.net core mvc 之 DynamicApi

    这段时间闲赋在家,感觉手痒,故想折腾一些东西. 由于之前移植了一个c#版本的spring cloud feign客户端(https://github.com/daixinkai/feign.net), ...

  3. Spring MVC-从零开始-view-向页面传递data(ModelAndView与ModelMap的区别)

    1.ModelMap的用法 package com.jt; import org.springframework.stereotype.Controller; import org.springfra ...

  4. QT两个窗口相互切换

    信号(signals)与槽(slots)是QT重要机制,例子使用了C++11 lambda表达式进行了信号与槽的连接. 实现两个窗口通过点击按钮完成互相切换,注意子窗口只能发送信号,不能处理,所有信号 ...

  5. java @postconstruct初始化注解使用

    1.从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解(Annotion):@PostConstruct和@PreDestroy.这两个注解被用来修饰一个非静态的 ...

  6. Mybatis基础知识点

    1. Mybatis框架优缺点 优点: 1. 易于上手和掌握. 2. sql写在xml里,便于统一管理和优化. 3. 解除sql与程序代码的耦合. 4. 提供映射标签,支持对象与数据库的orm字段关系 ...

  7. 解决Git报错:error: You have not concluded your merge (MERGE_HEAD exists).

    Git fetch和git pull的区别, 解决Git报错:error: You have not concluded your merge (MERGE_HEAD exists). 2017年02 ...

  8. PHP5.5 mysqli如何连接MySQL数据库和读取数据

    在学习 1. 开启PHP的API支持 (1)首先修改您的php.ini的配置文件.查找下面的语句:;extension=php_mysqli.dll将其修改为:extension=php_mysqli ...

  9. 夯实Java基础系列17:一文搞懂Java多线程使用方式、实现原理以及常见面试题

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  10. mui中判断是点击还是滑动

    判断和滑动是两种触发方式 滑动分为四种,上下左右(swipeup,swipedown,swipeleft,swiperight) 点击分为两种,点击和双击,一般用单机(tap) 根据自己不同的需求进行 ...