双方向データ バインディングの実装方法 (インタビューの質問)

双方向データ バインディングの実装方法 (インタビューの質問)

双方向バインディングを実装するには、次の 2 つの方法があります。

  1. Object.definedProperty( ) [オブジェクト監視のために vue2 で使用される Object.definedProperty( )]
  2. Proxy(プロキシオブジェクト)【vue3以降はProxyで実現】

上記の 2 つの方法で実現するには、簡単に言えば、データのハイジャックです. オブジェクトのプロパティにアクセスまたは変更する場合、これらの 2 つの方法でインターセプトされ、さらに操作すると結果が返されます。

1. Object.defineProperty() を使用して、双方向のデータ バインディングを実現します。

  • Data -> view Object.defineProperty は object プロパティの値変更を乗っ取り、set メソッドでビューに影響を与える
  • 表示 -> データ監視入力/変更イベント、変数に値を代入
<body>
    <div class="box">
        <h4>当控制台中的值发生改变,input框中的内容随之发生改变</h4>
        数据影响视图:
        <input type="text" id="inp">
    </div>

    <div class="box">
        <h4>当input框中内容发生改变,控制台中的值发生改变</h4>
        视图影响数据:
        <input type="text" id="inp2">
    </div>

    <script>
        // data对象
        let data = {
      
      
            msg: '初始值'
        }

        //definedProperty()方法  vue2 

        // txt 实例
        let txt = {
      
      };
        let txt1 = {
      
      };

        // 1. 变量  =》 视图   使用Object.definedProperty定义对象中新属性或修改原有的属性(也就是检测对象属性值的变化)
        // ----Object.definedProperty语法
        // -------defineProperty(属性所在对象,属性名,描述符对象(value))

        // (1):给txt添加同名的属性(影子)
        Object.defineProperty(txt, 'msg', {
      
      
            set(val) {
      
       //给txt的msg属性赋值,就会触发set方法(val就是给txt.msg赋予的值)
                data['msg'] = val;
                // (2): set中影响对应视图
                document.getElementById('inp').value = val;
            },
            get() {
      
       //获取txt的msg的值
                return data['msg']
            }
        })

        // // 2. 视图  =》  变量  (依赖于oninput/onchange事件)
        inp2.oninput = function() {
      
      
            txt1.msg = this.value
        }

    </script>
</body>

画像.png

双方向データバインディング (definedProperty)

2. Proxy (プロキシ) を使用して、データの双方向バインディングを実現します。

  • オブジェクトのプロキシ オブジェクトを作成し、プロキシ オブジェクトのメソッドを変更します。
<body>
    <div class="box">
        <h4>当控制台中的值发生改变,input框中的内容随之发生改变</h4>
        数据影响视图:
        <input type="text" id="inp">
    </div>

    <div class="box">
        <h4>当input框中内容发生改变,控制台中的值发生改变</h4>
        视图影响数据:
        <input type="text" id="inp2">
    </div>

    <script>
        // data对象
        let data = {
      
      
            msg: '初始值'
        }

        // Proxy(代理对象) vue3
        let txt = new Proxy(data, {
      
      
            set: function(target, prop, val) {
      
      
                data['msg'] = val;
                document.getElementById('inp').value = val;
                return Reflect.set(target, prop, val);
            },
            get: function(target, prop) {
      
      
                return Reflect.get(target, prop);
            }
        })

        let txt1 = new Proxy(data, {
      
      
            set: function(target, prop, val) {
      
      
                data['msg'] = val;
                return Reflect.set(target, prop, val)
            },
            get: function(target, prop) {
      
      
                return Reflect.get(target, prop)
            }
        })

        inp2.oninput = function() {
      
      
            txt1.msg = this.value;
        }
    </script>
</body>

画像.png

双方向のデータ バインディング (プロキシ)

3. Object.definedProperty( ) と Proxy (プロキシ) の違い

(1) Proxy は Object.defineProperty よりもはるかに便利です。

(2) Proxy はオブジェクト全体をプロキシし、Object.defineProperty はオブジェクトのプロパティのみをプロキシします。

(3) vue では、Proxy は呼び出し時に再帰的であり、Object.defineProperty は最初はすべて再帰的であり、Proxy のパフォーマンスは Object.defineProperty よりも優れています。

(4) オブジェクトに新しいプロパティが定義されると、Proxy はそれを監視できますが、Object.defineProperty は監視できません。

(5) 配列が追加、削除、または変更されると、Proxy はそれを監視できますが、Object.defineProperty は監視できません。

(6) Proxy は IE と互換性がなく、Object.defineProperty は IE8 以下と互換性がありません。

4. まとめ:

(1) ビューの変更を変数に同期する方法は?

  • ビューは oninput/onchange イベントをバインドし、値を取得して変数に割り当てます

(2) オブジェクト内の属性の値の変化を検出する方法は?

  • Object.defineProperty データの乗っ取り、set と get の書き換え

(3) いつ設定され、いつトリガーされますか?

  • プロパティに値を割り当てるとセットがトリガーされ、値を取得すると取得がトリガーされます

おすすめ

転載: blog.csdn.net/SH744/article/details/126999990