Vue2 データ双方向バインディングの原理

vue2データの双方向バインディングを理解するには、手で入力するとよりよく理解できるようになります~

1. ページデータの一部

        データ双方向バインディングを実装する前に、まず使用する必要のあるデータを準備し、次にコード部分を実装します。

(1) ページ構成

ここでは、 vue の双方向データ バインディングの効果を実現するために、         v-model によってバインドされたデータとページ構造の補間式の値の間の相関関係を完了する必要があります。

<body id="app">
    <span>up主:{
   
   { name }}</span>
    <input type="text" v-model="name">
    <span>更多:{
   
   { more.like }}</span>
    <input type="text" v-model="more.like">
</body>

(2)スクリプト部

        スクリプト タグ部分を通じてインポートされた vue ファイルは、実際の vue ではありません。つまり、すぐに作成するコード部分です。

         el では、将来の便宜のために、HTML 部分の <body/> タグに ID を保存します。

<script src="./vue.js"></script>
<script>
    const vm = new Vue(
        {
            el: '#app',
            data: {
                name: 'kerwin',
                more: {
                    like: '点赞'
                }
            }
        }
    )
    console.log(vm);
</script>

2 つ目は、vue.js コード

(1) Vueインスタンスを作成する

        コード量が比較的多く、コンストラクターを使用する必要があるため、コンストラクターを作成するクラス class を選択します。

        まず、obj_instance がインスタンスの場合に渡されるオブジェクト。まずデータ属性をインスタンスの $dataに保存しますが、これは vue でも使用されます

class Vue {
    constructor(obj_instance) {
        this.$data = obj_instance.data
    }
}

(2) データハイジャックを実現

キーポイント:データハイジャックを実現するには Object.defineProperty        を使用する必要があります。これは vue2 の場合ですが、vue3 は少し異なります。vue2 を理解した後、vue3 を理解することは難しくありません。

     1. データハイジャック機能を作成する

        双方向バインディングに必要なのはデータ内のデータであるため、データを渡す必要があります。

class Vue {
    constructor(obj_instance) {
       // ....
       // 在构造函数中将data 传入
        Observer(this.$data)
    }
}

// 实现数据劫持
function Observer(data_instance) {


}

        2. データオブジェクトを走査し、データハイジャックを実装する

           理解:Object.defineProperty

            Object.defineProperty( 操作のオブジェクト, 操作のプロパティ, { } ) 

             { } オブジェクトを渡し、オブジェクト内でデータ監視を実装します。

            このメソッドは、オブジェクト内の既存のプロパティを変更できます。

// 数据劫持
function Observer(data_instance) {
    // 遍历对象中的每一个属性
    Object.keys(data_instance).forEach(key => {
        Object.defineProperty(data_instance, key, {
            // 设置属性描述符可以改变
            configurable: true,
            // 设置是否可枚举
            enumerable: true,
            get() {

            },
            set(newValue) {

            },
        })
    })
}

        3. セッターとゲッターを設定する

        設定前にコンソールでデータを確認できます

        ①ゲッター

        オブザーバーの前に vm を出力してみましょう。vm の属性値にアクセスすると、アクセス時に を取得しても返されないため、データが未定義であることがわかり、データが失われます。

        したがって、キーをトラバースするときは、まずデータを value 変数に保存し、それにアクセスすると get がトリガーされて値が返されるため、データは正常になります。

        ②セッター

        vm にデータを設定すると、set 関数がトリガーされ、その仮パラメータ (newValue) が設定したデータであるため、値を newValue として直接設定でき、この時点でデータは通常どおり変更できます。

// 数据劫持
function Observer(data_instance) {
    // 如果没有值或不为对象那么直接返回出去
    Object.keys(data_instance).forEach(key => {

++      let value = data_instance[key]

        Object.defineProperty(data_instance, key, {
            configurable: true,
            enumerable: true,

            get() {
++              console.log(`访问了${key}属性 -->  属性值为:${value}`);
++              return value // 将原本数据return出来
            },
            set(newValue) {
++              value = newValue
++              console.log(`修改了${key}属性值${value} --> 为${newValue}`);
            },
        })
    })
}

        4. データオブジェクト属性のオブジェクトを処理する

        設定した data 属性値にはオブジェクトも含まれているため、object.key を使用して最初のレイヤーのみを走査します。data 内のすべてのデータをハイジャックしたい場合は、再帰を使用する必要があります

        キーを走査するときは、まず再帰的に呼び出してオブジェクトとして値またはデータ型があるかどうかを確認し、存在する場合は再帰を続けてこの問題を解決します。

function Observer(data_instance) {

    // 如果没有值或不为对象那么直接返回出去
++  if (!data_instance || typeof data_instance !== 'object') return

    Object.keys(data_instance).forEach(key => {
        let value = data_instance[key]
        // 递归,内部属性
++      Observer(value)

        Object.defineProperty(data_instance, key, {
           // ....
        })
    })
}

        5. 新しいオブジェクトをプロパティに割り当てるハンドル

        プロパティをオブジェクトに再割り当てする場合、observ はすでに実行されているため再帰されません。そのため、セッターで再度 observ を呼び出す必要があります。

Object.defineProperty(data_instance, key, {
    // ...

    set(newValue) {
        // 递归
++      Observer(newValue)
        value = newValue
        return console.log(`修改了${key}属性值${value} --> 为${newValue}`);
    },
})

多すぎるので説明は省略します、後ほど追記します

詳細は gitee を参照して clone してください。アドレスは以下の通りです

Vue2 はデータの双方向バインディングを実装します: Vue2 のデータの双方向バインディング、v-model+input をカバーします

おすすめ

転載: blog.csdn.net/Kerwin__li/article/details/128741065