前文
本文框架的实现参考了GitHub上的一个mvvm来实现,语法换成了es6的语法,并且添加了每一块代码我个人的一些理解,算是整理一下自己学习完了之后的一个思路,顺便方便上班摸鱼的人学习,本人也只是个工作3年的菜鸡,此文只用来分享,非以讲师身份教学,文章若有疏漏,可联系我修改,轻喷
原文链接:github.com/DMQ/mvvm
阅读之前:此文章默认大家熟悉es6的语法,对es6不做过多介绍,为了方便,将会大量使用es6
本文关键代码都会写出方便复制粘贴自己查看输出结果
数据代理
Object.defineProperty()
学习数据代理前首先我们需要先了解一个方法:Object.defineProperty(),该方法可以定义一个对象的属性,举个栗子
let demo = {
a:'a',
b:'b'
}
这里我们定义了一个demo对象,对象中有两个属性:a,b,如果我们需要demo里面有一个属性c,他的值是'a+b'的和,并且在a和b发生改变的时候c也对应的发生改变应该怎么做呢? 如果我们这样写:
let demo = {
a:'a',
b:'b',
c:this.a+this.b
}
我们来看一下输出结果:
可以看的到,这种方式定义的c的结果是完全不对的,这个时候我们就要用到Object.defineProperty()方法
备注:因为defineProperty的参数有很多,这里就不一一列举水字数了,可在mdn查看,附MDN地址: developer.mozilla.org/zh-CN/docs/…
举个栗子查看一下此方法
Object.defineProperty(demo,'c',{
get(){
return 12
}
})
/*
这里函数的前两个参数分别对应:往哪个对象里面添加属性,属性名是什么;
第三个参数是设置将被定义或修改的属性描述符,传递参数以对象的方式传递,因为里面参数较多,这里重点说一下get和set参数;
get参数是一个函数,此函数的含义是,当我在使用我使用defineProperty定义的属性时,会返回函数return的值;
比如上面这段代码,我向demo对象中定义了一个属性c,并且在它的属性描述符中添加了一个get方法,返回一个数字12,那么我此时如果去console一下demo.c,取得的值应该是12,执行一遍试一下
*/
console.log(demo.c);
get
可以看到,输出结果确实跟我们想的一样,输出的结果是一个get中return出来的数字12
那么,通过get的知识点,就可以解答我们上面的问题,如何定义一个属性c,使c的值等于demo.a+demo.b,请看代码
let demo = {
a:'a',
b:'b'
}
Object.defineProperty(demo,'c',{
get(){
return this.a+this.b
}
})
console.log(demo.c)
输出结果:
可以看到,demo.c的值确实是等于demo.a的值:'a'加上demo.b的值:'b',输出了'ab', 那么,我们这个时候再修改下demo.a的值看demo.c的值是否会自动修改
demo.a = 'change a'
console.log(demo.c);
可以看到,此时我们就完成了demo.c的动态自动更新
set
说完了get方法,我们再了解一下set方法,我们先从字面意思了解一下,get是获取,所以是在获取定义的属性的值的时候会被调用,同理推断一下,set的翻译是设置,那么是不是会在设置属性的值的时候会被调用呢,我们用代码来测试下
let demo = {
a:'a',
b:'b'
}
Object.defineProperty(demo,'c',{
set(value){
console.log(value)
}
})
demo.c = 12;
/*
set方法接受一个参数,此参数为你为定义的属性赋值时赋予的值具体是多少,
比如这里我设置demo.c = 12,那么set函数中的value就是12
*/
输出结果:
可以看到,确实执行了set中的方法,那么这个有什么用处呢,如果仅仅用来打印那就太浪费了,比如我们可以表面在修改c,其实是在修改a的值,上代码
let demo = {
a:'a',
b:'b'
}
Object.defineProperty(demo,'c',{
set(value){
this.a = value;
}
})
console.log(demo.a);
demo.c = 12;
console.log(demo.a);
可以看到,在我们修改demo.c的时候,demo.a的值还是a,在我们修改了demo.c的值的时候,实际上,是将demo.a的值修改为了12,这样就完成了一次隐式修改