Maison  >  Article  >  interface Web  >  Comment surveiller les changements de slot Vue ? Essayez cette astuce !

Comment surveiller les changements de slot Vue ? Essayez cette astuce !

青灯夜游
青灯夜游avant
2022-09-28 19:52:452700parcourir

Comment surveiller les changements de slot dans Vue ? L'article suivant vous expliquera comment surveiller les modifications dans les emplacements Vue. J'espère qu'il vous sera utile !

Comment surveiller les changements de slot Vue ? Essayez cette astuce !

Dernièrement, j'ai besoin de mettre à jour l'état d'un composant chaque fois que son contenu (emplacements, sous-composants, etc.) change. Pour le contexte, il s'agit d'un composant de formulaire qui garde une trace de l'état de validité de ses entrées.

L'extrait de code ci-dessous est écrit au format API Options, mais peut être utilisé dans Vue2 et Vue2, sauf indication contraire. [Recommandations associées : tutoriel vidéo vuejsOptions 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]

Démarrer

Commencez par contrôler l'état du formulaire, modifiez une classe en fonction de l'état et remplissez le contenu enfant avec 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>

Afin de mettre à jour l'attribut isInvalid, nous devons ajouter un événement déclenché. Vous pouvez utiliser l'événement sumit, mais je préfère utiliser le. Événement input.

🎜7 événements de formulaire : focus, flou, saisie, sélection, modification, réinitialisation, soumission, etc. Pour une explication détaillée, veuillez lire cet article : https://blog.csdn.net/qq_4379...🎜🎜
🎜 Les formulaires ne déclenchent pas d'événements input, mais nous pouvons utiliser des "délégués d'événement". Nous attachons l'écouteur à l'élément parent (ff9c23ada1bcecdd1a0fb5d5a0f18437) et lorsque l'événement se produit sur ses éléments enfants (d5fd7aea971a85678ba271703566ebfd, <select&gt ; , 4750256ae76b6b9d804861d8f69e79d3, etc.) sera déclenché. 🎜🎜Chaque fois que l'événement input est déclenché dans 58cb293b8600657fad49ec2c8d37b472 de ce composant, le formulaire capturera l'événement. 🎜rrreee🎜La logique de validation peut être simple ou complexe. À des fins de démonstration, cet article utilise une méthode simple pour utiliser l'API form.checkValidity() pour vérifier si le formulaire est valide en fonction des attributs de validation HTML. 🎜🎜Pour accéder à l'élément ff9c23ada1bcecdd1a0fb5d5a0f18437. Vous pouvez utiliser l'attribut refs ou $el. Pour plus de simplicité, cet article utilise $el. 🎜rrreee

Question

🎜Il y a un petit problème ici. Que se passe-t-il si le contenu du formulaire change ? Que se passe-t-il si un d5fd7aea971a85678ba271703566ebfd est ajouté au DOM lors du chargement du formulaire ? 🎜🎜Par exemple, nous appelons ce composant de formulaire "MyForm" Dans App, le contenu est le suivant : 🎜rrreee🎜Quand App.vue masque l'affichage via des conditions Là. Il existe certaines entrées que notre formulaire doit connaître. Dans ce cas, nous penserions à suivre la validité du contenu du formulaire lorsqu'il change, pas seulement sur l'événement input ou le hook de cycle de vie monté. Sinon, des informations incorrectes pourraient s'afficher. 🎜🎜Les amis qui connaissent les hooks de cycle de vie de Vue pourraient penser à utiliser update pour suivre les modifications. En théorie, cela semble génial. En pratique, cela crée une boucle infinie et le navigateur se bloque. 🎜

Solution

🎜Après quelques recherches et tests, la meilleure solution est d'utiliser l'API MutationObserver. Il s'agit d'une méthode intégrée au navigateur qui offre la possibilité de surveiller les modifications apportées à l'arborescence DOM. Cette API peut être avertie si des nœuds sont ajoutés ou supprimés, si des attributs sont modifiés ou si le contenu du texte est modifié. 🎜🎜C'est une méthode native, elle ne se limite donc pas aux frameworks. 🎜🎜Lors de son utilisation, utilisez d'abord le constructeur MutationObserver pour créer une nouvelle instance d'observateur et spécifiez la fonction de rappel de cette instance. Appelé après chaque changement du DOM, ce rappel est appelé. La fonction de rappel accepte deux paramètres, le premier est le tableau de changement et le second est l'instance d'observateur. Réécrivez notre composant form comme suit : 🎜rrreee🎜Vous devez également utiliser beforeUnmount ici événement de cycle de vie pour déconnecter l'<code>observateur, ce qui efface toute mémoire allouée par celui-ci. 🎜🎜Enfin, nous transmettons le statut isInvalid au slot du plugin du contenu auquel nous voulons accéder. C'est aussi appelé le slot du scope et c'est très utile. 🎜rrreee🎜Avec cette configuration, nous pouvons ajouter n'importe quel nombre de entrée à notre composant de formulaire et ajouter toute logique de rendu conditionnel dont il a besoin. Tant que l'input utilise l'attribut de validation HTML, le formulaire permettra de savoir s'il est dans un état valide. 🎜🎜 De plus, puisque nous utilisons des slots limités, nous fournissons l'état du formulaire au parent, afin que celui-ci puisse réagir aux changements de validité. 🎜🎜Par exemple, dans App.vue, nous voulons "désactiver" le bouton de soumission lorsque le formulaire n'est pas valide. Vous pouvez l'écrire comme ça🎜rrreee🎜nice~.🎜🎜J'espère que cet article. peut être utile à votre développement futur. 🎜

(Partage de vidéos d'apprentissage : Développement web front-end, Vidéo de programmation de base)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer