Bild
Bild.png

Vorwort

vue3Es stand seit seiner Veröffentlichung zwei Jahre lang im Rampenlicht und hat jetzt die Dynamik, die Welt mit React zu teilen. Wir wissen, dass es auf der Fähigkeit des Proxys basiert, Reaktionsfähigkeit zu erreichen, was einige vue2der verbleibenden Probleme gelöst hat Gleichzeitig hat es aufgrund der Eigenschaften des Proxys auch die Laufzeitleistung verbessert

Alles hat Vor- und Nachteile. proxyObwohl es unbesiegbar ist, hat es auch seine eigenen Einschränkungen, was meiner Meinung nach zu einigen Nachteilen führt (tatsächlich entspricht es nicht der natürlichen Schreibweise der js-Sprache, manche Leute denken, es sei etwas Besonderes Schreibweise, und er gehört nicht zu den Nachteilen)

  • 1. Die Implementierung des responsiven Systems von primitiven Werten führt dazu, dass es als Objekt gepackt und mittels zugegriffen .valuewerden
  • 2. ES6-Destrukturierung kann nicht beliebig verwendet werden. würde seine reaktionsschnelle Natur brechen

Getrieben von meiner Neugier recherchierte und grübelte ich darüber nach, warum er diese beiden Nachteile verursachte

Implementierung eines reaktiven Systems für primitive Werte

Bevor wir die Implementierung eines reaktiven Systems primitiver Werte verstehen, wollen wir uns zuerst die Fähigkeiten des Proxys ansehen!

const obj = {
  name'win'
}

const handler = {
  getfunction(target, key){
    console.log('get--', key)
    return Reflect.get(...arguments)  
  },
  setfunction(target, key, value){
    console.log('set--', key, '=', value)
    return Reflect.set(...arguments)
  }
}

const data = new Proxy(obj, handler)
data.name = 'ten'
console.log(data.name,'data.name22')

复制代码

Im obigen Code haben wir festgestellt, dass die Verwendung von Proxy selbst das Abfangen des Objekts new Proxyist und das Objekt obj durch den Rückgabewert von abgefangen wird

Auf diese Weise wird die getMethode , und wenn Sie den Wert im Objekt ändern, wird die setMethode ausgelöst

Aber was den ursprünglichen Wert angeht, hat er kein Interesse, was soll ich tun, es new proxykann nicht verwendet werden.

In der Verzweiflung können wir es nur einpacken, damit wir .valueZugriff auf die Verwendung haben

Werfen wir einen Blick auf die konkrete Implementierung

import { reactive } from "./reactive";
import { trackEffects, triggerEffects } from './effect'

export const isObject = (value) => {
    return typeof value === 'object' && value !== null
}

// 将对象转化为响应式的
function toReactive(value{
    return isObject(value) ? reactive(value) : value
}

class RefImpl {
    public _value;
    public dep = new Set// 依赖收集
    public __v_isRef = true// 是ref的标识
    // rawValue 传递进来的值
    constructor(public rawValue, public _shallow) {
        // 1、判断如果是对象 使用reactive将对象转为响应式的
        // 浅ref不需要再次代理
        this._value = _shallow ? rawValue : toReactive(rawValue);
    }
    get value() {
        // 取值的时候依赖收集
        trackEffects(this.dep)
        return this._value;
    }
    set value(newVal) {
        if (newVal !== this.rawValue) {
            // 2、set的值不等于初始值 判断新值是否是对象 进行赋值
            this._value = this._shallow ? newVal : toReactive(newVal);
            // 赋值完 将初始值变为本次的
            this.rawValue = newVal
            triggerEffects(this.dep)
        }
    }
}

复制代码

Der obige Code stellt das Packen des Originalwerts dar. Er wird als Objekt gepackt, und auf den Originalwert wird über die Methoden get valueund zugegriffen, was zu der erforderlichen Operation führt, die eigentlich eine hilflose Wahl ist.set value.value

相当于两瓶毒药,你得选一瓶Man kann nicht Fisch und Bärentatze haben

Warum ES6 destrukturiert und nicht in der Lage ist, es zu verwenden, wird seine reaktionsschnellen Funktionen zerstören

Die erste Frage ist endlich verstanden, also schauen wir uns die zweitwichtigste Frage an,为什么结构赋值,会破坏响应式特性

Proxy-Hintergrund

Bevor wir beginnen, lassen Sie uns diskutieren, warum die Änderung响应式方案

Vue2 basiert auf Object.defineProperty   , hat aber viele Mängel, wie z. B. die  Unfähigkeit, die Änderung des Arrays basierend auf Indizes zu überwachen, und Mängel wie Map, Set, WeakMap und WeakSet werden nicht unterstützt  .

Tatsächlich verzögern diese unsere Entwicklung nicht, vue2 ist immer noch der Mainstream,

Mein Verständnis ist 与时俱进, dass 新一代的版本,一定要紧跟语言的特性,一定要符合新时代的书写风格, obwohl proxyes viele Verbesserungen im Vergleich zu Object.defineProperty gibt, es nicht ohne Mängel ist.不兼容IE

Wie kann es auf der Welt etwas Perfektes geben?

Dein großer Mut liegt darin, ein bisschen von der Gegenwart aufzugeben, um eine Zukunft aufzubauen!

Ausführungsprinzip

Nachdem wir den Hintergrund verstanden haben, lassen Sie uns das Prinzip in einem gefälschten Modus überprüfen proxy, obwohl dies alles faul ist.

Worauf sollten Sie jedoch beim Schreiben von Hydrologie achten: zwei Wörter - Kohärenz

Bild
Bild.png
        const obj = {
            count1
        };
        const proxy = new Proxy(obj, {
            get(target, key, receiver) {
                console.log("这里是get");
                return Reflect.get(target, key, receiver);
            },
            set(target, key, value, receiver) {
                console.log("这里是set");
                return Reflect.set(target, key, value, receiver);
            }
        });
        
        console.log(proxy)
        console.log(proxy.count)
复制代码

Der obige Code stellt die spezifische Art der Verwendung von Proxy dar. Durch die Zusammenarbeit mit Reflect kann das Abfangen von Objekten realisiert werden.

Bild
Bild.png

Mit einer solchen Abhängigkeit können Sie Reaktionsfähigkeit erreichen.Sie können feststellen, dass das gesamte Objekt dieses Objekts abgefangen wird, aber Sie stellen fest, dass das Objekt eine Ebene tiefer verschachtelt ist.

zum Beispiel:


    const obj = {
            count1,
            b: {
                c2
            }
        };
        
        
     console.log(proxy.b)
     console.log(proxy.b.c)
复制代码

Er kann nicht abfangen, wir müssen packen

    const obj = {
            a: {
                count1
            }
        };
        
        function reactive(obj{
            return new Proxy(obj, {
                get(target, key, receiver) {
                    console.log("这里是get");
                    // 判断如果是个对象在包装一次,实现深层嵌套的响应式
                    if (typeof target[key] === "object") {
                        return reactive(target[key]);
                    };
                    return Reflect.get(target, key, receiver);
                },
                set(target, key, value, receiver) {
                    console.log("这里是set");
                    return Reflect.set(target, key, value, receiver);
                }
            });
        };
        const proxy = reactive(obj);
复制代码

Nun, das Prinzip ist erledigt, lasst es uns formell studieren

Um nun einige mir bekannte Situationen aufzulisten, in denen die Reaktionsfähigkeit verloren geht:

  • 1. Dekonstruieren Sie das  props Objekt, weil es seine Reaktionsfähigkeit verliert
  • 2. Direkte Zuweisung reactivevon reaktiven Objekten
  • 3. vuexMittlere Kombination API-Zuweisung

Destrukturieren von  props Objekten, weil es die Reaktionsfähigkeit verliert

       const obj = {
            a: {
                count1
            },
            b1
        };
            
            //reactive 是上文中的reactive
           const proxy = reactive(obj);
        const {
            a,
            b
        } = proxy;
        console.log(a)
        console.log(b)
        console.log(a.count)
        
复制代码
Bild
Bild.png

Im obigen Code finden wir, dass die destrukturierende Zuweisung, b 不会触发响应式, a如果你访问的时候, die Antwort auslöst

Warum ist das?

Keine Sorge, lass es uns nacheinander erklären?

Lassen Sie uns zuerst diskutieren, warum die Destrukturierung der Zuweisung die Reaktionsfähigkeit verliert?

Wir kennen die destrukturierende Zuweisung, die Unterscheidung zwischen der Zuweisung von primitiven Typen und der Zuweisung von Referenztypen,

原始类型的赋值相当于按值传递,引用类型的值就相当于按引用传递

ist äquivalent zu

   // 假设a是个响应式对象
  const a={ b:1}
  // c 此时就是一个值跟当前的a 已经不沾边了
  const c=a.b

// 你直接访问c就相当于直接访问这个值 也就绕过了 a 对象的get ,也就像原文中说的失去响应式
复制代码

Warum areagiert es also?

Da aes sich um einen Referenztyp handelt, erinnern wir uns an ein Urteil im obigen Code. Wenn er ein objectist, verpacken Sie ihn als reaktiv

Wenn es sich um einen Referenztyp handelt, verlieren Sie formal aufgrund der aktuellen Funktion nicht die Reaktionsfähigkeit, wenn Sie auf seinen Inhalt zugreifen

  // 假设a是个响应式对象
 const a={ b:{c:3}}
 // 当你访问a.b的时候就已经重新初始化响应式了,此时的c就已经是个代理的对象
 const c=a.b

// 你直接访问c就相当于访问一个响应式对象,所以并不会失去响应式
复制代码

Das Obige erklärt grob, warum eine destrukturierende Zuweisung die Reaktionsfähigkeit verlieren kann. Ich schätze, das Dokument ist zu faul, um den Grund zu erklären, also stelle ich einfach eine Regel auf, Sie!

Verwenden Sie es nicht, speichern Sie die Fehler, die Sie für vuewahr halten, und ändern Sie die Nutzungsgewohnheiten des Benutzers im Voraus! nicht gewohnt

Direkte Zuweisung reactivevon reaktiven Objekten

Als wir vue3 zum ersten Mal verwendet haben, haben wir angegeben, dass der folgende Code geschrieben werden würde

 const vue = reactive({ a1 })
 vue = { b2 }

复制代码

Und dann Fragen zu stellen, reactiveist es nicht reaktionsschnell? Warum verschwand seine Reaktionsfähigkeit, nachdem ich den Wert zugewiesen hatte, und dann schrie er, Müll vue

Tatsächlich liegt dies daran, dass Sie das Konzept von js native nicht klarstellen, tatsächlich haben 尤大Sie die größten Anstrengungen unternommen, um Fehler zu vermeiden

Beispielsweise verbietet er aufgrund des Problems der destrukturierenden Zuweisung direkt die reaktive destrukturierende Zuweisung

Bild
Bild.png

Wenn Sie die destrukturierende Zuweisungsoperation verwenden, wird sie direkt deaktiviert

Dann fragte jemand wieder, 为啥props 不给禁用了呢?

因为你的props 的数据可能不是响应式的啊,不是响应式的,我得能啊, insbesondere kann er die Verwendung der neuen Syntax durch den Benutzer nicht stören.

Es ist also derselbe Satz: 框架现在的呈现,其实充满了取舍„Manchmal sind es wirklich zwei Flaschen Gift, nimm eine!

Zurück zum Thema, sprechen wir über native js-Syntax

Als erstes ist zu bestätigen, dass die Zuordnung des Referenztyps des nativen js tatsächlich auf der Referenzadresse basiert!

 // 当reactive 之后返回一个代理对象的地址被vue 存起来,
 // 用一个不恰当的比喻来说,就是这个地址具备响应式的能力
 const vue = reactive({ a1 })
 
 //  而当你对于vue重新赋值的时候不是将新的对象赋值给那个地址,而是将vue 换了个新地址
 // 而此时新地址不具备响应式,可不就失去响应式了吗
 vue = { b2 }

复制代码

Das Obige ist reactivedie Erklärung für den Verlust der Reaktionsfähigkeit, daher ist dies auch der Grund, warum viele Benutzer fluchen.不符合他的使用习惯了,这都是被vue2 培养起来的一代

Hier möchte ich ein faires Wort für dich sagen, Da 人家又没收你钱,还因为他,你有口饭吃,

Du selbst kannst nicht mit der Zeit gehen und dich auf Neues einlassen, das bist du 能耐,

das ist typisch端起碗吃肉,放下筷子骂娘

vuexAPI-Zuweisung für mittlere Zusammensetzung

Die Verwendung von Zuweisungen in vuex kann auch die Reaktionsfähigkeit beeinträchtigen


import { computed } from 'vue'
import { useStore } from 'vuex'

export default {
  setup () {
    const store = useStore()
    return {
      // 在 computed 函数中访问 state
      count: computed(() => store.state.count),

      // 在 computed 函数中访问 getter
      double: computed(() => store.getters.double)
    }
  }
}

复制代码

Im obigen Code haben wir festgestellt, dass das mit umschlossen store.getters.doublewerden muss computed. Tatsächlich ist der Grund derselbe und es ist auch der Grund für die Variablenzuweisung. Wir werden sie hier nicht wiederholen!

zu guter Letzt

Dieser Artikel enthält im Prozess der Verwendung von vue3 einige Erfahrungen und Erkundungen nach dem Mining. Ich hoffe, er wird Ihnen hilfreich sein, damit Sie eine Beförderung und Gehaltserhöhung bei der Arbeit erhalten!

Abschließend möchte ich meine vue-Quellcodeanalyse fördern. Die Analyse ist vielleicht nicht sehr gut, aber es wird alles Zeile für Zeile gelesen. Vielleicht fällt Ihnen nach dem Lesen ein Satz oder ein Satz ein, was hilfreich ist!

Quellcode-Analyseadresse [1]

Willkommen Stern

Über diesen Artikel

Autor: Lao Ji Bauer

https://juejin.cn/post/7114596904926740493

Das Ende

Wenn Sie diese Inhalte inspirierend finden, möchte ich Sie bitten, mir drei kleine Gefallen zu tun:
1. Klicken Sie  auf „Beobachten“ , damit mehr Personen diesen Inhalt sehen können
2. Folgen Sie der offiziellen Website  https://muyiy.cn , lassen Sie uns eine langfristige Beziehung eingehen
3. Achten Sie auf das offizielle Konto „Advanced Front-End Advanced“ und antworten  Sie auf „Gruppe hinzufügen“ im Hintergrund des offiziellen Kontos  . Schließen Sie sich uns an, um zu lernen, und senden Sie Ihnen gut organisierte Fragen für erweiterte Front-End-Interviews.

》》Die Fragendatenbank, die Interviewer verwenden, kommen Sie und sehen Sie 《


Liken am Ende nicht vergessen!Bild

Viel Glück im Jahr 2022! Gewaltige Schönheit! Heftig dünn!