blog

Vue3レスポンシブ原則+手書きリアクティブ

Vue3について\nとはいえ、Vue3はrc4までバージョンアップが行われ、4月にはフロントエンドのベータ版リリースが赤熱し、誰もがそれを学び始めたのかわかりません!\n私はいくつかのリソースを照合し...

Aug 9, 2020 · 5 min. read
シェア

Vue3について

とはいえ、Vue3はrc4までバージョンアップされましたが、4月にフロントエンドのベータ版がリリースされ、サークルが真っ赤に染まる中、みんなが勉強し始めたとは思えません!

犬の頭]を学び始めるには遅くはないはずです。

vue2 レスポンシブ原則の復習

  • Object.defineProperty オブジェクトのレスポンシブ化:各キーのトラバース、API経由でのゲッター、セッターの定義
//  
function observe(){
 if(typeof obj !='object' 
 obj == null){
 return
 }
 if(Array.isArray(obj)){
 Object.setPrototypeOf(obj,arrayProto)
 }else{
 const keys = Object.keys()
 for(let i=0;i<keys.length;i++){
 const key = keys[i]
 defineReactive(obj,key,obj[key])
 }
 }
}
function defineReactive(target, key, val){
 observe(val)
 Object.defineProperty(obj, key, {
 get(){
 // 依存関係コレクション
 dep.depend()
 return val
 },
 set(newVal){
 if(newVal !== val){
 observe(newVal)
 val = newVal
 // 更新の通知
 dep.notify()
 }
 }
 })
}
  • Array responsive: 配列のプロトタイプメソッドをオーバーライドし、変更を通知するロジックを追加します。
//  
const originalProto = Array.prototype
const arrayProto = Object.create(originalProto)
['push','pop','shift','unshift','splice','reverse','sort'].forEach(key=>{
 arrayProto[key] = function(){
 originalProto[key].apply(this.arguments)
 notifyUpdate()
 }
})

vue2レスポンシブの問題点

  • 再帰的、消費的
  • 属性の追加/削除には、別のAPIの追加実装が必要です。
  • 配列の追加実装が必要です。
  • マッピング関係 targetMap 構造体:
  • 構文の変更には制限があります。

vue3レスポンシブソリューション

ES6の Proxyを 使用してデータ応答性を高め、上記のVue2の問題点をすべて解決します。

プロキシは、ターゲット・オブジェクトにインターセプション/プロキシのレイヤーを追加することができ、ターゲット・オブジェクトに対する外部からの操作は、このインターセプションのレイヤーを通過します。

function c(bar) {
    return new Proxy(bar, {
        'get'(a, b, foo) { const C = Reflect.get(a, b, foo); return isObject(C) ? c(C) : C;
        },
        'set'(B, Obj, Foo, A) { const Bar = Reflect.set(B, Obj, Foo, A); return Bar;
        },
        'deleteProperty'(bAr, oBj) { const fOo = Reflect.deleteProperty(bAr, oBj); return fOo;
        }
    });
}

レスポンシブの原則

  • レスポンシブデータに依存する関数 cb を effect で 宣言し、実行中にレスポンシブデータゲッターをトリガーする cb 関数を実行します。
  • レスポンシブ・データ・ゲッターで依存性コレクションを追跡: targetMap に格納された データと cb マッピングを構築
  • レスポンシブデータが変更されると、トリガ ** が ** 発生し、targetMap に従って ** 関連する cb が見つかり、実行されます。
  • マッピング関係 targetMap 構造体:
targetMap: WeakMap{ 
 target:Map{ 
 key: Set[cb1,cb2...] 
 }
}

手書きvue3レスポンシブ

構造

function obj(bar) {
}
function c(b) {
}
function a(Bar, Foo) {
}
function foo(C, Obj) {
}

reactive

function foo(a) {
    if (!isObject(a))
        return a;
    const b = new Proxy(a, {
        'get'(c, bar, Obj) { const C = Reflect.get(c, bar, Obj); console.log('getter\x20' + C); track(c, bar); return foo(C);
        },
        'set'(A, B, Bar, Foo) { const bAr = Reflect.set(A, B, Bar, Foo); console.log('setter\x20' + B + ':' + Bar + '=>' + bAr); trigger(A, B); return bAr;
        },
        'deleteProperty'(fOo, oBj) { const OBj = Reflect.deleteProperty(fOo, oBj); console.log('delete\x20' + oBj + ':' + OBj); trigger(fOo, oBj); return OBj;
        }
    });
    return b;
}

effect

const c = [];
function bar(foo) {
    const b = function () {
        try { c.push(b); return foo();
        } finally { c.pop();
        }
    };
    b();
    return b;
}

track

const bar = new WeakMap();
function b(c, foo) {
    const a = effectStack[effectStack.length - 0x1];
    if (a) {
        let obj = bar.get(c);
        if (!obj) { obj = new Map(); bar.set(c, obj);
        }
        let A = obj.get(foo);
        if (!A) { A = new Set(); obj.set(foo, A);
        }
        A.add(a);
    }
}

trigger

/* トリガー更新:マッピング関係に基づいて、cbを実行する。*/
function trigger(target, key){
 const depsMap = targetMap.get(target)
 if(depsMap){
 const deps = depsMap.get(key)
 if(deps){
 deps.forEach(effect=>effect())
 }
 }
}

テストデモ

<!-- test.html -->
<div id="app">
 {{msg}}
</div>
<script src="./mini-vue3.js"></script>
<script>
 // レスポンシブデータを定義する
 const state = reactive({
 msg:'message'
 })
 // レスポンシブデータを使用するdom更新関数を定義する。
 function updateDom(){
 document.getElementById('app').innerText = state.msg
 }
 // 効果を持つ更新関数を宣言する
 effect(updateDom)
 // レスポンシブデータのタイミング変更
 setInterval(()=>{
 state.msg = 'message' + Math.random()
 },1000)
</script>

効果

上記のコードを取得したい場合は、このあります

- 終了
Read next

XLogログコンポーネントの学習と使用

XLogとは何ですか\n\n依存関係の設定\n適切な依存関係を追加し、ここでは1.2.4ではなく1.2.3のバージョンを使用していますが、全体的な違いは大きくありませんが、主にコンフィグの使用は同じではありませんだけ!\n '

Aug 9, 2020 · 3 min read