vue 动态数据绑定
动态数据绑定(一)
我的github iSAM2016
实现的步骤:
1.监听对象属性的读取与变化
Object.defineProperty() 方法会直接在对象上定义一个新的的属性,或者已经存在的属性
并且返回这个属性
语法是 Object.defineProperty(obj, prop, descript)
obj: 目标对象
prop: 需要定义或修改的属性的名字
descript: 将被定义或修改的属性的描述符
描述:
这个方法精确添加或修改对象的属性,我们添加的属性是可以枚举的属性(Object.keys()/ for...in)
对象里面存在是属性描述存在的形式是:
数据描述符:拥有可写入或不可以写入的属性(相当于口令密码)
存取描述符:由一对getter-setter 函数功能来描述的属性(方法)
注意:**描述符**必须是两种形式之一,不能同时是两者。
数据描述符和存取描述符均具有以下可选键值:
- configurable:当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,也能够被删除。默认为 false
- enumerable:当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false
数据描述符:
- value:该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
- writable:当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false。
存取描述符同时具有以下可选键值:
- get:一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。
- 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 动态数据绑定的更多相关文章
- Vue.js 数据绑定语法详解
Vue.js 数据绑定语法详解 一.总结 一句话总结:Vue.js 的模板是基于 DOM 实现的.这意味着所有的 Vue.js 模板都是可解析的有效的 HTML,且通过一些特殊的特性做了增强.Vue ...
- Vue动态添加v-model绑定及获取其返回数据
从数据库拿到的动态数据绑定到页面对应的v-model或者v-bind上,并且根据对页的操作获取到返回的值: 1.首先在data里定义一个数据 timeTip 为一个空数组 data () { retu ...
- RDLC报表系列(一) 简单的动态数据绑定和配置
RDLC系列链接 RDLC报表系列(一) 简单的动态数据绑定和配置 RDLC报表系列(二) 行分组 RDLC报表系列(三) 总计和折叠 RDLC报表系列(四) 矩阵 RDLC报表系列(五) 简单的图 ...
- Vue动态组件
前面的话 让多个组件使用同一个挂载点,并动态切换,这就是动态组件.本文将详细介绍Vue动态组件 概述 通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,可以实现动 ...
- vue 双向数据绑定的实现学习(二)- 监听器的实现
废话:上一篇https://www.cnblogs.com/adouwt/p/9928278.html 提到了vue实现的基本实现原理:Object.defineProperty() -数据劫持 和 ...
- vue 双向数据绑定的实现学习(一)
前言:本系列学习笔记从以下几个点展开 什么是双向数据绑定 双向数据绑定的好处 怎么实现双向数据绑定 实现双向数据数据绑定需要哪些知识点 数据劫持 发布订阅模式 先看看我们要实现的目标是什么,如下动图: ...
- vue双向数据绑定的简单实现
vue双向数据绑定的简单实现 参考教程:链接 <!DOCTYPE html> <html lang="en"> <head> <meta ...
- vue动态class——实现tag的选中状态
vue动态class——实现tag的选中状态 <template> <div class="common-nav"> <div class=" ...
- Vue双向数据绑定原理分析(转)
add by zhj: 目前组里使用的是前端技术是jQuery + Bootstrap,后端使用的Django,Flask等,模板是在后端渲染的.前后端没有分离,这种做法有几个缺点 1. 模板一般是由 ...
随机推荐
- C#连接Mongo报Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1错的解决方案
---恢复内容开始--- 最近做一个基于ABP的.net Core的项目,数据库选了MongoDB,但是返现无法给数据库设置认证,只要设置了账号密码连接就报错 连接串如下: mongodb://roo ...
- 利用Python进行数据分析:【Matplotlib】
一.简单介绍Matplotlib 1.Matplotlib是一个强大的Python绘图和数据可视化的工具包2.安装方法:pip install matplotlib 3.引用方法:import mat ...
- QT两个窗口相互切换
信号(signals)与槽(slots)是QT重要机制,例子使用了C++11 lambda表达式进行了信号与槽的连接. 实现两个窗口通过点击按钮完成互相切换,注意子窗口只能发送信号,不能处理,所有信号 ...
- shell管道与重定向
输出重定向 $ ls -l > lsoutput 这条命令将ls命令执行后的结果输入出到lsoutput文件中. 在linux shell中使用符号 > ,< 来完成输入输出的重定向 ...
- 06-border
边框 border:边框,描述盒子的边框 边框的三要素:粗细 线性样式 颜色 例如:border:1px solid red: 如果颜色不写,默认是黑色:如果粗细不写,不显示边框:如果只写线性样式,默 ...
- php基础——语法、变量
一.php语法: 1.php语言需要写在<?php ?>标签里面 2.php语言每行结束需要使用:作为结束符 3.php是一门弱语言,不要求先声明变量 4.可嵌套在HTML和js语言中 ...
- 同时支持EF+Dapper的混合仓储,助你快速搭建数据访问层
背景 17年开始,公司开始向DotNet Core转型,面对ORM工具的选型,当时围绕Dapper和EF发生了激烈的讨论.项目团队更加关注快速交付,他们主张使用EF这种能快速开发的ORM工具:而在线业 ...
- 编程小技巧之 Linux 文本处理命令
合格的程序员都善于使用工具,正所谓君子性非异也,善假于物也.合理的利用 Linux 的命令行工具,可以提高我们的工作效率. 本文简单的介绍三个能使用 Linux 文本处理命令的场景,给大家开阔一下思路 ...
- 最清晰的RESTFUL理解
Restful理解 API(Application Programming Interface),顾名思义:是一组编程接口规范,客户端与服务端通过请求响应进行数据通信.REST(Representat ...
- 【CV现状-3.3】特征提取与描述
#磨染的初心--计算机视觉的现状 [这一系列文章是关于计算机视觉的反思,希望能引起一些人的共鸣.可以随意传播,随意喷.所涉及的内容过多,将按如下内容划分章节.已经完成的会逐渐加上链接.] 缘起 三维感 ...