Heim  >  Artikel  >  Web-Frontend  >  Wie kann ich Vue-Slot-Änderungen überwachen? Versuchen Sie diesen Trick!

Wie kann ich Vue-Slot-Änderungen überwachen? Versuchen Sie diesen Trick!

青灯夜游
青灯夜游nach vorne
2022-09-28 19:52:452700Durchsuche

Wie kann ich Slot-Änderungen in Vue überwachen? Im folgenden Artikel erfahren Sie, wie Sie Änderungen in Vue-Slots überwachen. Ich hoffe, dass er Ihnen weiterhilft!

Wie kann ich Vue-Slot-Änderungen überwachen? Versuchen Sie diesen Trick!

In letzter Zeit muss ich den Status einer Komponente aktualisieren, wenn sich ihr Inhalt (Slots, Unterkomponenten usw.) ändert. Im Kontext handelt es sich um eine Formularkomponente, die den Gültigkeitsstatus ihrer Eingaben verfolgt.

Der folgende Codeausschnitt ist im API-Format Options geschrieben, kann aber in Vue2 und Vue2 verwendet werden, sofern nicht anders angegeben. [Verwandte Empfehlungen: vuejs Video-TutorialOptions API格式编写的,但除了指定的地方外可以在Vue2 和 Vue2中使用。【相关推荐:vuejs视频教程

开始

先从控制表单状态开始,根据状态修改一个类,孩子内容使用38b537b6886351ac721d89624ba185ca填充:

<template>
  <form :class="{ &#39;--invalid&#39;: isInvalid }">
    <slot />
  </form>
</template>

<script>
export default {
  data: () => ({
    isInvalid: false,
  }),
};
</script>

为了更新isInvalid属性,我们需要添加一个触发的事件,可以使用 sumit 事件 ,但我更喜用 input 事件。

表单事件7个: focus, blur, input, select, change, reset, submit 等,具体详解看这篇文章:https://blog.csdn.net/qq_4379...

表单不会触发 input 事件,但我们可以使用 "事件委托"。我们将监听器附加到父元素(ff9c23ada1bcecdd1a0fb5d5a0f18437)上,当事件发生在它的子元素(d5fd7aea971a85678ba271703566ebfd221f08282418e2996498697df914ce4e4750256ae76b6b9d804861d8f69e79d3等)上时就会被触发。

任何时候在这个组件的58cb293b8600657fad49ec2c8d37b472中触发input事件,表单将捕获该事件。

<template>
  <form :class="{ &#39;--invalid&#39;: isInvalid }" @input="validate">
    <slot />
  </form>
</template>

<script>
export default {
  data: () => ({
    isInvalid: false,
  }),
  methods: {
    validate() {
      // 验证逻辑
    }
  }
};
</script>

验证逻辑可以是简单或复杂的。本文为了演示,用简单的方法,使用form.checkValidity() API 来查看表单是否基于HTML验证属性而有效。

为了访问ff9c23ada1bcecdd1a0fb5d5a0f18437元素。可以用refs$el属性。为了简单起见,本文使用$el

<template>
  <form :class="{ &#39;--invalid&#39;: isInvalid }" @input="validate">
    <slot />
  </form>
</template>

<script>
export default {
  data: () => ({
    isInvalid: false,
  }),
  methods: {
    validate() {
      this.isInvalid = !this.$el.checkValidity()
    }
  }
};
</script>

问题

这里有一点问题。如果表单的内容改变了,会发生什么?如果一个d5fd7aea971a85678ba271703566ebfd在表单加载被添加到DOM中,会发生什么?

举个例子,我们把这个表单组件称为 "MyForm",在 App 中,内容如下:

// App.vue
<template>
  <MyForm>
    <input
      v-model="showInput"
      id="toggle-name"
      name="toggle-name"
      type="checkbox"
    />
    <label for="toggle-name">显示其它 input</label> 

    <template v-if="showInput">
      <label for="name">Name:</label>
      <input id="name" name="name" required />
    </template>

    <button type="submit">提交</button>
  </MyForm>
</template>

<script>
import Form from "./components/form.vue";
export default {
  name: "App",
  components: {
    MyForm: Form,
  },
  data: () => ({
    showInput: false,
  }),
};
</script>

App.vue通过条件来隐藏显示某些 input,我们的表单需要知道。在这种情况下,我们会想到在表单内容发生变化时跟踪其有效性,而不仅仅是在 input 事件或mounted生命周期钩子上。否则,可能会显示不正确的信息。

熟悉 Vue的生命周期钩子小伙伴,这里可能会想到使用 update 来跟踪变化。理论上,这听起来不错。在实践中,它会创造一个无限的循环,然后浏览器挂了。

解决方法

经过一番研究和测试,最佳解决方案是使用MutationObserver API。它是浏览器内置的方法,提供了监视对DOM树所做更改的能力,如果节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。

它是原生的方法,所以不受限于框架。

使用时,首先使用MutationObserver构造函数,新建一个观察器实例,同时指定这个实例的回调函数。在每次 DOM 变动后调用,这个回调都被调用。该回调函数接受两个参数,第一个是变动数组,第二个是观察器实例,将我们的 form 组件改写成如下:

<template>
  <form :class="{ &#39;--invalid&#39;: isInvalid }" @input="validate">
    <slot />
  </form>
</template>

<script>
export default {
  data: () => ({
    isInvalid: false,
  }),
  mounted() {
    const observer = new MutationObserver(this.validate);
    observer.observe(this.$el, {
      childList: true,
      subtree: true,
    });
    this.observer = observer;
  },
  methods: {
    validate() {
      this.isInvalid = !this.$el.checkValidity();
    },
  },
  beforeUnmount() {
    this.observer.disconnect();
  },
};
</script>


<style scoped>
</style>

这里还需要使用 beforeUnmount生命周期事件来断开observer的连接,这会清除它所分配的任何内存。

最后,我们将isInvalid状态传递给要访问的内容的插件槽,这也称作用域的槽,它非常有用。

<template>
  <form :class="{ &#39;--invalid&#39;: isInvalid }" @input="validate">
    <slot v-bind="{ isInvalid }" />
  </form>
</template>

<script>
export default {
  data: () => ({
    isInvalid: false,
  }),
  mounted() {
    const observer = new MutationObserver(this.validate);
    observer.observe(this.$el, {
      childList: true,
      subtree: true,
    });
    this.observer = observer;
  },
  methods: {
    validate() {
      this.isInvalid = !this.$el.checkValidity();
    },
  },
  beforeUnmount() {
    this.observer.disconnect();
  },
};
</script>

通过这样的设置,可以在我们的表单组件中添加任意数量的 input,并添加任何它需要的条件渲染逻辑。只要input使用HTML验证属性,表单就会跟踪它是否处于有效状态。

此外,由于使用的是作用域槽,我们将表单的状态提供给父级,所以父级可以对有效性的变化做出反应。

例如,在 App.vue]

Start

Beginnen Sie mit der Steuerung des Formularstatus, ändern Sie eine Klasse entsprechend dem Status und füllen Sie den untergeordneten Inhalt mit 38b537b6886351ac721d89624ba185ca:

<template>
  <MyForm>
    <template slot:default="form">
      <label for="name">Name:</label>
      <input id="name" name="name" required>

      <button
        type="submit"
        :class="{ disabled: form.isInvalid }"
      >
        Submit
      </button>
    </template>
  </MyForm>
</template>

Um das Attribut isInvalid zu aktualisieren, müssen wir ein ausgelöstes Ereignis hinzufügen. Sie können das Ereignis sumit verwenden, aber ich verwende lieber das input-Ereignis.

🎜7 Formularereignisse: Fokus, Unschärfe, Eingabe, Auswählen, Ändern, Zurücksetzen, Senden usw. Eine ausführliche Erklärung finden Sie in diesem Artikel: https://blog.csdn.net/qq_4379...🎜🎜
🎜 Formulare lösen keine Eingabeereignisse aus, aber wir können "Ereignisdelegierte" verwenden. Wir hängen den Listener an das übergeordnete Element an (ff9c23ada1bcecdd1a0fb5d5a0f18437) und wenn das Ereignis an seinen untergeordneten Elementen auftritt (d5fd7aea971a85678ba271703566ebfd, <select&gt ; , 4750256ae76b6b9d804861d8f69e79d3 usw.) werden ausgelöst. 🎜🎜Jedes Mal, wenn das input-Ereignis in 58cb293b8600657fad49ec2c8d37b472 dieser Komponente ausgelöst wird, erfasst das Formular das Ereignis. 🎜rrreee🎜Validierungslogik kann einfach oder komplex sein. Zu Demonstrationszwecken wird in diesem Artikel eine einfache Methode zur Verwendung der API form.checkValidity() verwendet, um anhand von HTML-Validierungsattributen zu überprüfen, ob das Formular gültig ist. 🎜🎜Um auf das ff9c23ada1bcecdd1a0fb5d5a0f18437-Element zuzugreifen. Sie können das Attribut refs oder $el verwenden. Der Einfachheit halber verwendet dieser Artikel $el. 🎜rrreee

Frage

🎜Hier gibt es ein kleines Problem. Was passiert, wenn sich der Inhalt des Formulars ändert? Was passiert, wenn beim Laden des Formulars ein d5fd7aea971a85678ba271703566ebfd zum DOM hinzugefügt wird? 🎜🎜Zum Beispiel nennen wir diese Formularkomponente "MyForm". In der App lautet der Inhalt wie folgt: 🎜rrreee🎜Wenn App.vue die Anzeige durch Bedingungen verbirgt sind bestimmte Eingabens, die unser Formular kennen muss. In diesem Fall würden wir daran denken, die Gültigkeit des Formularinhalts zu verfolgen, wenn er sich ändert, und nicht nur am input-Ereignis oder am mount-Lebenszyklus-Hook. Andernfalls können falsche Informationen angezeigt werden. 🎜🎜Freunde, die mit den Lebenszyklus-Hooks von Vue vertraut sind, denken vielleicht darüber nach, update zu verwenden, um Änderungen zu verfolgen. Theoretisch klingt das großartig. In der Praxis entsteht eine Endlosschleife und der Browser hängt sich auf. 🎜

Lösung

🎜Nach einigen Recherchen und Tests ist die beste Lösung die Verwendung der MutationObserver-API. Es handelt sich um eine integrierte Methode des Browsers, die die Möglichkeit bietet, Änderungen am DOM-Baum zu überwachen. Diese API kann benachrichtigt werden, wenn Knoten hinzugefügt oder entfernt werden, sich Attribute ändern oder Textinhalte geändert werden. 🎜🎜Es handelt sich um eine native Methode, daher ist sie nicht auf Frameworks beschränkt. 🎜🎜Wenn Sie es verwenden, verwenden Sie zunächst den Konstruktor MutationObserver, um eine neue Beobachterinstanz zu erstellen und die Rückruffunktion dieser Instanz anzugeben. Dieser Rückruf wird nach jeder DOM-Änderung aufgerufen. Die Rückruffunktion akzeptiert zwei Parameter, der erste ist das Änderungsarray und der zweite ist die Beobachterinstanz. Schreiben Sie unsere form-Komponente wie folgt um: 🎜rrreee🎜Sie müssen hier auch beforeUnmount lifecycle-Ereignis, um den <code>Observer zu trennen, wodurch der gesamte von ihm zugewiesene Speicher gelöscht wird. 🎜🎜Abschließend übergeben wir den Status isInvalid an den Plugin-Slot des Inhalts, auf den wir zugreifen möchten. Dies wird auch als Scope-Slot bezeichnet und ist sehr nützlich. 🎜rrreee🎜Mit diesem Setup können wir unserer Formularkomponente eine beliebige Anzahl von Eingabens hinzufügen und jede benötigte bedingte Rendering-Logik hinzufügen. Solange die Eingabe das HTML-Validierungsattribut verwendet, verfolgt das Formular, ob es sich in einem gültigen Zustand befindet. 🎜🎜 Da wir außerdem bereichsbezogene Slots verwenden, stellen wir dem übergeordneten Element den Status des Formulars zur Verfügung, sodass das übergeordnete Element auf Änderungen der Gültigkeit reagieren kann. 🎜🎜Zum Beispiel möchten wir in App.vue die Schaltfläche „Senden“ deaktivieren, wenn das Formular ungültig ist. Sie können es so schreiben🎜rrreee🎜schön~.🎜🎜Ich hoffe, dieser Artikel kann für Ihre zukünftige Entwicklung hilfreich sein. 🎜

(Teilen von Lernvideos: Web-Frontend-Entwicklung, Grundlegendes Programmiervideo)

Das obige ist der detaillierte Inhalt vonWie kann ich Vue-Slot-Änderungen überwachen? Versuchen Sie diesen Trick!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen