vue 動態數據綁定

動態數據綁定(一)

個人github iSAM2016git

實現的步驟:github

1.監聽對象屬性的讀取與變化

Object.defineProperty() 方法會直接在對象上定義一個新的的屬性,或者已經存在的屬性
而且返回這個屬性app

語法是 Object.defineProperty(obj, prop, descript)
obj: 目標對象
prop: 須要定義或修改的屬性的名字
descript: 將被定義或修改的屬性的描述符函數

描述:

這個方法精確添加或修改對象的屬性,咱們添加的屬性是能夠枚舉的屬性(Object.keys()/ for...in)this

對象裏面存在是屬性描述存在的形式是:
數據描述符:擁有可寫入或不能夠寫入的屬性(至關於口令密碼)
存取描述符:由一對getter-setter 函數功能來描述的屬性(方法)prototype

注意:**描述符**必須是兩種形式之一,不能同時是二者。

數據描述符和存取描述符具備如下可選鍵值:code

  1. configurable:當且僅當該屬性的 configurable 爲 true 時,該屬性描述符纔可以被改變,也可以被刪除。默認爲 false
  2. enumerable:當且僅當該屬性的 enumerable 爲 true 時,該屬性纔可以出如今對象的枚舉屬性中。默認爲 false

數據描述符:server

  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;
相關文章
相關標籤/搜索