您的位置:首页 > Web前端 > Vue.js

实现一个简单的类 Vue 框架(二) —— 数据的绑定之修改可监听的数据绑定方法

2019-05-17 19:32 627 查看

Vue是MVVM框架,也就是M(数据)的变化能够驱动V(模板)的变化,所以数据修改可响应的实现是一个关键点。实现数据变化可响应的方法很多,事件驱动,广播,订阅等方法,而Vue使用的是js的原生API  Object.defineProperty。这种实现方法的优点是:实现简单。缺点是:只能兼容到IE9以上。

 

针对上一篇文章:https://blog.csdn.net/SunShinessx/article/details/90293626,本篇用Object.defineProperty实现修改可监听的数据驱动:

[code]/* 修改可监听的数据绑定 */
function Sue(options) {
initData(this,options)
if (typeof options.ready === 'function') {
options.ready.call(this)
}
}

function initData (vm,options) {
var data = options.data;
data = typeof data === 'function' ? data() : data || {};
for (let key in data) {
if (data.hasOwnProperty(key)) {
let value = data[key]
Object.defineProperty(vm,key,{
enumerable: true,
configurable: true,
get() {
console.log(`get ${key}`);
return value
},
set(newVal) {
if(value !== newVal){
value = newVal
console.log(`set ${key}`);
}
}
})
}
}
}

var sue =  new Sue({
data(){
return {
name:'ssx',
age:18
}
},
ready(){
console.log("name",this.name);
console.log("age",this.age);
this.name = 'lili'
this.age = 19
}
})
console.log(sue.name);
console.log(sue.age);

存在的问题:如果data是一个对象,对对象的修改将不能监听到。

解决方法:遍历data对象,然后对data对象的属性也做 Object.defineProperty处理。

[code]/* 修改可监听的数据绑定---data的属性是对象 */
function Sue(options) {
initData(this,options)
if (typeof options.ready === 'function') {
options.ready.call(this)
}
}

function initData (vm,options) {
var data = options.data;
data = typeof data === 'function' ? data() : data || {};
_each(vm,data)
}

function _each(obj,sourceObj) {
bindData(obj,sourceObj)
for (let key in sourceObj) {
if(typeof sourceObj[key] == 'object'){
bindData(sourceObj[key],sourceObj[key])
}

}
}

function bindData(obj,sourceObj) {
for (let key in sourceObj) {
if (sourceObj.hasOwnProperty(key)) {
let value = sourceObj[key]
Object.defineProperty(obj,key,{
enumerable: true,
configurable: true,
get() {
console.log(`get ${key}`);
return value
},
set(newVal) {
if(value !== newVal){
value = newVal
console.log(`set ${key}`);
}
}
})
}
}
}

var sue =  new Sue({
data(){
return {
info:{
name:'ssx',
age:18
}
}
},
ready(){
console.log("name",this.info.name);
console.log("age",this.info.age);
this.info.name = 'lili'
this.info.age = 19
}
})

存在问题:如果info的属性在开发过程中新增加了,是不能检测到的。

解决方法:vue.$set方法就是解决这个问的。简化后的$set方法可以这样实现:

[code]/* 修改可监听的数据绑定---data对象属性随意增加也可以监听到 */
function Sue(options) {
this.initData(this,options)
if (typeof options.ready === 'function') {
options.ready.call(this)
}
}

Sue.prototype = {
constructor:Sue,
$set(obj,key,value){
Object.defineProperty(obj,key,{
enumerable: true,
configurable: true,
get() {
console.log(`get ${key}`);
return value
},
set(newVal) {
if(value !== newVal){
value = newVal
console.log(`set ${key}`);
}
}
})
},
initData (vm,options) {
var data = options.data;
data = typeof data === 'function' ? data() : data || {};
this._each(vm,data)
},
_each(obj,sourceObj) {
this.bindData(obj,sourceObj)
for (let key in sourceObj) {
if(typeof sourceObj[key] == 'object'){
this.bindData(sourceObj[key],sourceObj[key])
}

}
},
bindData(obj,sourceObj) {
for (let key in sourceObj) {
if (sourceObj.hasOwnProperty(key)) {
let value = sourceObj[key]
Object.defineProperty(obj,key,{
enumerable: true,
configurable: true,
get() {
console.log(`get ${key}`);
return value
},
set(newVal) {
if(value !== newVal){
value = newVal
console.log(`set ${key}`);
}
}
})
}
}
}
}

var sue =  new Sue({
data(){
return {
info:{
name:'ssx',
age:18
}
}
},
ready(){
console.log("name",this.info.name);
console.log("age",this.info.age);
this.info.name = 'lili'
this.info.age = 19
}
})
sue.$set(sue.info,'school','福大')
console.log("school",sue.info.school)

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐