MVVMデータプロキシの実装原理

https://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2FDMQ%2Fmvvm

1.データエージェント

(1)はじめに:データオブジェクトプロキシにプロキシデータは、VMによってオブジェクトのすべてのプロパティを操作しています。例えば、我々はデータVUEデータは、アクセスVUEの方法はvm.methods.getMsg()する必要がありますが、実際に我々が直接またはvm.getMsg()のデータにアクセスするために使用vm.msg vm.data.msgでなければなりませんアクセスしたいですメソッドまたはデータ。そのデータ剤
(2)実装の原理:すべてのプロキシオブジェクトの属性値がキーを横断するように、同じ名前のキー属性を取得し、動的に取得またはデータオブジェクトを変更するために設けられた一連の方法、Object.defineProperty VMによってオブジェクトに追加され

<script>
function MVVM (option) {
    //保存传入的配置
    this.$option = option
    //保存data对象
    var data = this._data = this.$option.data
    //遍历data中的所有key
    Object.keys(data).forEach(key => {
        //为vm添加与key相同属性,且配置相应的属性描述符
        Object.defineProperty(this,key,{
            configurable: false,//可重新定义
            enumerable: true,//可枚举
            get () {
                return this._data[key]
            },
            set (newVlue) {
                this._data[key] = newVlue
            }
        })
    })
}

//实例化
var vm = new MVVM({
    data: {
        msg:'Hello World'
    }
})

//vm.msg相当于调用get方法返回this._data[key]
console.log(vm.msg) //Hello World
//给vm.msg赋值相当于调用set方法,更新this._data[key]的值
vm.msg = "msg is change"
console.log(vm.msg) //msg is change
</script>

2.データハイジャック

データは、プロパティでそのモニタの変更を言って人気のハイジャックして、対応するコールバック関数をトリガします。データVUEテンプレートが変更されたとして、ページにも対応いたしますこのような、彼の原理は、データモニタを実現する変更が発生すると、コールバック関数でDOMを更新することです。

3があり、オブジェクトに属性を追加する方法は、我々はすでに2種類を学びました。

//初始化时添加属性
var person = {name:"谢耳朵"}
//点语法添加属性
person.age = 25

console.log(person) //{name: "谢耳朵", age: 25}

これら2つのプロパティを追加すること、のいずれかのプロパティ値または属性値の変更を取得する方法は、操作自体の目的です。第三の方法を使用して属性を追加するとき、GETおよびセット方法を含む一連の他の属性に構成されてもよいです。
構文:Object.defineProperty(OBJ、キー、オプション )

データハイジャックの実装の原則:
(1)あなたは無限ループで、その結果、getメソッドをトリガーするアクセス自体にgetメソッドを呼び出すときに、その値にアクセスしたいため、データエージェントは、自分自身を操作することはできません。プロパティの割り当ては、新しい値を設定する方法を自分自身に割り当てられている場合も同様で、また、無限ループが発生することができ、独自のsetメソッドをトリガーする、真である
(2)私は自分自身を動作させることができないので、それは属性ごとに別々の設定が必要になります変数。GETまたはsetメソッドは、無限ループを避けるために、操作変数とは無関係です。
(3)溶液:Object.definePropertyにはヴァルに渡されるパラメータとして、レイヤ機能のプロパティ値を包みました。そして、これは以前のvalの独立変数は、アクセスgetメソッドはvalを返すことができると言われています。トリガーヴァルの値を変更する方法を設定すると

<script>
//这个例子没有深度劫持
function proxyData(obj,key,val){
    //val作为一个中间变量,负责存储这个属性的值
    Object.defineProperty(obj, key, {
        configurable:false,
        enumerable:true,
        get(){
            //get方法返回这个val
            console.log('通过get方法获取了'+key+'属性的值')
            return val
        },
        set(newVal){
            //set方法修改这个val
            if(newVal === val){
                return
            }
            console.log(key+'属性的值发生了变化')
            console.log('可以在这个回调函数中做其他事件,例如更新页面dom等')
            val = newVal
        }
    })
}

var p = {name: 'kyo', age: 20}
//调用proxyData()进行数据劫持
Object.keys(p).forEach((key) => {
    var val = p[key]
    proxyData(p,key,val)
})

//获取属性值
var name = p.name
//修改属性值
p.age = 27
</script>

コンソールを印刷:

通过get方法获取了name属性的值
age属性的值发生了变化
可以在这个回调函数中做其他事件,例如更新页面dom等

オブジェクトは、マルチレイヤオブジェクト、あなたが再帰呼び出しを使用する必要があり、各レベルの属性データハイジャックの必要性が含まれている場合、オブジェクトの第1層のみのプロパティのための上記方法。
アイデア:彼のプロパティ値の型がオブジェクトである場合にハイジャックすべてのプロパティのデータは、このプロパティの値は、再帰呼び出しであります

<script>
//利用递归调用深度劫持
function proxyData(obj,key,val){
    //val作为一个中间变量,负责存储这个属性的值
    Object.defineProperty(obj, key, {
        configurable:false,
        enumerable:true,
        get(){
            //get方法返回这个val
            console.log('通过get方法获取了'+key+'属性的值')
            return val
        },
        set(newVal){
            //set方法修改这个val
            if(newVal === val){
                return
            }
            console.log(key+'属性的值发生了变化')
            console.log('可以在这个回调函数中做其他事件,例如更新页面dom等')
            val = newVal
        }
    })
    //判断属性值是否为object,如果是则对这个值进行递归调用
    if(val instanceof Object){
        Object.keys(val).forEach(key => {
            proxyData(val,key,val[key])
        })
    }
}

var data = {
    name: 'kyo',
    age: 20,
    skill: ['大蛇薙', '最终决战奥义“无式'],
    father: {
        name: '草薙柴舟',
        age: 50
    }
}
Object.keys(data).forEach((key) => {
    var val = data[key]
    proxyData(data,key,val)
})

//读取属性值
var fatherName = data.father.name
//修改属性值
data.father.age = 52
</script>

コンソールを印刷:

//data.father.name
通过get方法获取了father属性的值
通过get方法获取了name属性的值

//data.father.age = 52
通过get方法获取了father属性的值
age属性的值发生了变化
可以在这个回调函数中做其他事件,例如更新页面dom等

おすすめ

転載: www.cnblogs.com/OrochiZ-/p/11853585.html