Vue: Ajouter des modificateurs de modèle v personnalisés

Créé le 13 sept. 2016  ·  52Commentaires  ·  Source: vuejs/vue

Nous avons .lazy , .number , .trim et .undef sont en route.

À part .lazy , ils fonctionnent tous comme des filtres bidirectionnels.

Étant donné que 2.0 ne prend pas en charge les filtres à 2 voies, il devrait y avoir une nouvelle API pour ajouter des modificateurs de modèle v personnalisés pour répondre au même besoin.

feature request

Commentaire le plus utile

Y a-t-il une chance que nous puissions rouvrir ce problème ? Un cas d'utilisation courant pour moi est la nécessité de formater automatiquement les données dans un champ au fur et à mesure qu'elles sont saisies. Quelque chose comme prendre '101216' et le transformer en '10/12/16'. Pouvoir créer un modificateur v-model personnalisé simplifierait considérablement mon code puisque je pourrais écrire v-model.date au lieu d'avoir à créer un composant d'entrée personnalisé avec des accessoires et des événements.

Tous les 52 commentaires

Les propriétés calculées @posva ne sont pas réutilisables.

Presque tout est réutilisable grâce à un mixin.
Vous pouvez utiliser une fonction qui génère un mixin. De cette façon, vous pouvez lier un
propriété calculée dynamiquement. Je ne peux pas mettre cet exemple sur un violon maintenant
mais je le ferais dès que possible.
Cependant, je suis d'accord que c'est un cas d'utilisation très courant pour les entrées d'avoir
transformations appliquées. Une API appropriée ou au moins une explication sur le
un guide est nécessaire

Le mar. 13 sept. 2016, 18:48 Francisco Lourenço, [email protected]
a écrit:

@posva https://github.com/posva les propriétés calculées ne sont pas réutilisables.


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/vuejs/vue/issues/3666#issuecomment -246746524, ou muet
le fil
https://github.com/notifications/unsubscribe-auth/AAoicf33lCvETQc9LBQ5GGZ93ExPcLS_ks5qptPegaJpZM4J7vQ0
.

Presque tout est réutilisable grâce à un mixin.
Vous pouvez utiliser une fonction qui génère un mixin. De cette façon, vous pouvez lier un
propriété calculée dynamiquement. Je ne peux pas mettre cet exemple sur un violon maintenant
mais je le ferais dès que possible.
Cependant, je suis d'accord que c'est un cas d'utilisation très courant pour les entrées d'avoir
transformations appliquées. Une API appropriée ou au moins une explication sur le
un guide est nécessaire

Autrement dit, les propriétés calculées ne sont pas réutilisables. Vous pouvez utiliser les fonctions d'usine + mixins comme solution de contournement , mais la convivialité et la lisibilité ne se comparent pas.

Pour mon projet, j'avais vraiment besoin de cette fonctionnalité, j'ai donc utilisé l'approche de saisie personnalisée recommandée :

InputCustom.js

define(function () {
  return Vue.extend({
    data: function () {
      return {
        focused: false
      };
    },
    template: '<input @focus="onFocus" @blur="onBlur" @input="onInput" @change="setDisplayValue">',
    props: ['value'],
    watch: {
      value: function () {
        if (!this.focused) {
          this.setDisplayValue();
        }
      }
    },
    mounted: function () {
      this.setDisplayValue();
    },
    methods: {
      onInput: function () {
        this.$emit('input', this.parse(this.$el.value));
      },
      onFocus: function () {
        this.focused = true;
      },
      onBlur: function () {
        this.focused = false;
        this.setDisplayValue();
      },
      setDisplayValue: function () {
        this.$el.value = this.format(this.value);
      }
    }
  });
});

InputText.js

define(['js/InputCustom'], function (InputCustom) {
  return InputCustom.extend({
    methods: {
      parse: function (val) {
        val = val.trim();
        return val === '' ? null : val;
      },
      format: function (val) {
        return val === null ? '' : val;
      }
    }
  });
});

À mon avis, cette approche est très pratique et j'ai décidé de ne pas utiliser de modificateurs de modèle v, y compris .lazy .

Pour les cas d'utilisation plus personnalisés que les modificateurs intégrés ne peuvent pas prendre en charge, ce que @ecmel a mentionné est l'approche recommandée. Nous documenterons cela plus en détail dans le guide officiel.

L'idée de cette proposition de fonctionnalité est de tirer parti de la directive v-model existante, qui fonctionne déjà avec chaque élément input . Pour économiser le travail d'écriture de _InputCustom.js_ dans chaque projet, car cela a déjà été fait dans v-model , n'ayant qu'à écrire l'équivalent de _InputText.js_ dans un modificateur personnalisé, qui contient toute la logique nécessaire pour être modifié la plupart du temps. Le fait que v-model déjà livré avec des modificateurs prouve qu'il s'agit d'un modèle intuitif et souhaitable. Il est naturel de faciliter la création de modificateurs personnalisés, d'économiser le travail de création d'éléments personnalisés et d'avoir à implémenter manuellement la liaison dom/model.

Si cela a du sens du point de vue de l'API, il serait intéressant de savoir quelles sont les limitations techniques qui motivent la décision de ne pas implémenter cette fonctionnalité.

Y a-t-il une chance que nous puissions rouvrir ce problème ? Un cas d'utilisation courant pour moi est la nécessité de formater automatiquement les données dans un champ au fur et à mesure qu'elles sont saisies. Quelque chose comme prendre '101216' et le transformer en '10/12/16'. Pouvoir créer un modificateur v-model personnalisé simplifierait considérablement mon code puisque je pourrais écrire v-model.date au lieu d'avoir à créer un composant d'entrée personnalisé avec des accessoires et des événements.

Après avoir utilisé vue js pendant un moment dans mon projet, je pense que ce problème devrait en effet être rouvert.

Au moins, nous avons besoin d'un modificateur undef .

Je suis d'accord que ce sujet devrait être rouvert. Je ne sais pas ce que undef était censé faire, mais j'aimerais un modificateur v-model qui définit ma variable sur null au cas où la valeur coupée de l'entrée serait une chaîne vide.

J'aimerais pouvoir le faire moi-même de manière simple.

Des fonctionnalités plus redondantes que cela ont été ajoutées par exemple avec https://github.com/vuejs/vue/issues/5194 . De l'extérieur, Vue semble lentement compromettre certains de ses principes en faveur des conventions et pratiques promues par la communauté de réaction. Légèrement déviant des qualités qui l'ont fait ressortir en premier lieu. Il serait intéressant de savoir s'il s'agit d'une décision consciente avec l'intention de faciliter la migration de la réaction, ou simplement d'une coïncidence.

L'écriture de composants personnalisés est acceptable, mais si vous souhaitez utiliser un composant personnalisé tiers comme https://github.com/text-mask/text-mask/tree/master/vue#readme , il n'y a pas de moyen simple de désinfecter le masque. entrée dans les valeurs du modèle, sauf à l'aide de propriétés calculées.

Donc, je veux juste utiliser un champ d'entrée standard HTML [type = date] pour modifier un type de date dans mon modèle et ce cadre merveilleusement puissant et extensible ne peut pas le faire par défaut ? Impossible de lire la date dans le champ, remplacez ma date par une chaîne dans mes données après avoir sélectionné une date. Cette solution pourrait être écrite sur deux lignes avec des filtres bidirectionnels ou avec modificateur.

Mais la meilleure solution serait de le supporter nativement comme ils le font pour les cases à cocher et autres champs de saisie standard, pourquoi la "date" est-elle une chose spéciale?

+1 pour les modificateurs personnalisés. Cela semble être une évidence, à moins qu'il n'y ait une bonne raison de ne pas le faire ?

Masquer l'entrée et analyser la valeur pour l'utilisation de l'application est une pratique très courante, et faire du "sucre syntaxique" comme v-model.lazy.currency="amount" serait incroyable !

1+ pour les modificateurs personnalisés.
J'ai une simple entrée radio avec des valeurs true|false qui correspondent à des chaînes - mais j'en ai besoin en tant que booléen - les propriétés calculées ne seront pas intelligentes dans ce cas car je dois réimplémenter une propriété calculée pour chaque entrée radio. Par exemple, avoir 100 entrées radio se traduira par 100 propriétés calculées

+1 pour les modificateurs personnalisés mais je suis d'accord avec tobei -- input[type=date] devrait fonctionner automatiquement.

+1 pour les modificateurs personnalisés.

Je viens d'un milieu angulaire, et je viens de commencer avec vue, et j'ai vu ce fil.

Je pense que cela aiderait vraiment à avoir quelque chose comme les analyseurs et les formateurs d'Angular, également dans Vue. Si je pouvais faire quelque chose comme v-model.dateFormat et aboutir à quelque chose comme mm/jj/aaaa, ce serait vraiment cool.

EDIT : on dirait qu'il a réitéré ce que @restored18 a dit. +1 à toi aussi

+1 pour les modificateurs de modèle en V personnalisés.

Dans mon cas, je boucle sur quelques objets imbriqués récupérés dans JSON et j'utilise un seul modèle HTML (plutôt qu'un modèle par objet). Dans ce cas, je crois que les propriétés calculées ne fonctionnent pas ?

Je mets actuellement en place des méthodes de conversion personnalisées entre le format de serveur et le format v-model lors de la récupération et de l'envoi de données, mais j'aimerais quelque chose de juste "intégré" auquel je pourrais transmettre les fonctions.

+1 à ça. Il était disponible avant la version 2.2. Vous pouvez accéder à la propriété par,

this.$vnode.data.directives

Il a été supprimé avec l'ajout de valeurs d'entrée de modèle personnalisées, mais était une fonctionnalité très utile et devrait être de retour dans le cadre.

+1 pour ça.

Des modificateurs de modèle en V personnalisés seraient formidables !

Moi aussi

+1 en 2018 aussi...

+1 C'est une fonctionnalité nécessaire pour le code DRY à mon avis. En ce moment, je dois créer 10 observateurs qui font la même chose pour un formulaire avec beaucoup d'entrées. Un modificateur personnalisé résoudrait tout.

+1 Je viens de commencer vue et j'ai déjà besoin de ce type de filtres bidirectionnels ...

+1 absolument nécessaire

+1

Vous pouvez créer des assistants comme celui -ci pour la plupart des cas d'utilisation IMO

@nickmessing qui ne couvre pas le cas d'utilisation (vraiment utile) décrit ici, qui est la modification sur place du texte d'entrée. Si vous avez une zone de saisie que vous souhaitez toujours formater comme un téléphone, vous auriez <input v-model.phone="some_data"> . Lorsque l'utilisateur saisit du texte, il le formatera automatiquement.

Cela semble être une fonctionnalité de base et c'est plus difficile qu'il ne devrait l'être en ce moment. Le comportement existe déjà dans le framework, mais pour une raison quelconque, il est limité au code du framework uniquement. Nous voulons pouvoir ajouter un modificateur personnalisé qui ferait cela, qui soit réutilisable dans tous les composants et projets, tout comme les filtres et les directives le sont actuellement.

@bbugh totalement d'accord, j'ai un cas similaire avec le formatage des IBAN et ce serait une façon tellement agréable et déclarative de simplement mettre v-model.iban="payment.iban" là-dedans...

@franciscolourenco peut-être que quelqu'un pourrait expliquer pourquoi cela ne devrait pas être pris en charge par le cadre afin que cela devienne plus évident.

+1 pour les modificateurs personnalisés, il existe de nombreux cas d'utilisation qui pourraient être réalisés avec cette fonctionnalité

Dans notre application, il y a peu d'entrées différentes pour formater les devises, nous stockons toujours le montant en cents dans le modèle, mais affichons des montants en dollars bien formatés dans les entrées (donc 123456 dans le modèle affiché comme 1 234,56 $) <input v-model.dollars="cents" />

Un autre cas d'utilisation consiste à nettoyer et à supprimer les champs html afin d'empêcher les attaques XSS (le modèle stocke " A &amp; B " tandis que l'entrée affiche " A & B ") <input v-model.html="text" />

+1

+1

+1 pour les modificateurs personnalisés.
J'ai été vraiment surpris de ne pas pouvoir faire quelque chose comme v-model.trim.uppercase=...

+1

+1

+1

+1
Les modificateurs d'entrée natifs v-model seraient une excellente fonctionnalité. Comme les gens le mentionnent ici, il existe de nombreux cas d'utilisation. J'avais besoin de modificateurs de date et de devise pour tous les projets sur lesquels je travaillais.

doit-on ouvrir un sujet ici ? https://github.com/vuejs/rfcs

j'ai déjà +1 ceci, mais je veux lancer une note pour les personnes qui ont besoin de quelque chose "maintenant"

alors que le modificateur est bien plus efficace, j'ai pu obtenir le même effet en utilisant une entrée/composant transparent avec un champ getter/setter calculé.

je peux partager un exemple si quelqu'un en a besoin

Nous ne l'avons pas implémenté car il y a beaucoup de choses à prendre en compte dans cette fonctionnalité apparemment simple :

  • Les modificateurs intégrés sont en fait des conseils de compilation qui génèrent un code compilé différent. Les modificateurs personnalisés doivent probablement être définis à l'aide d'une configuration d'exécution, qui est un mécanisme différent.

  • Pour la configuration d'exécution, quel type d'API devrions-nous exposer pour cela ?

  • Nous avions des filtres à double sens dans le passé. Une transformation de valeur bidirectionnelle nécessite que l'utilisateur implémente une logique impeccable afin que la liaison bidirectionnelle puisse se stabiliser. Sinon, vous risquez de mettre toute votre application dans une boucle infinie pour les cas extrêmes.

    • La raison pour laquelle nous avons .number et .trim est qu'il s'agit en fait de transformations unidirectionnelles (uniquement appliquées lors de la synchronisation de la valeur DOM avec les données du composant) et donc garanties pour se stabiliser.
  • Comment les modificateurs personnalisés doivent-ils se comporter lorsque v-model est utilisé sur un composant ?

  • Comment les modificateurs personnalisés doivent-ils se comporter sur les types d'entrée non textuels, par exemple radio , checkbox et surtout, <select> ?

Toutes ces questions restent sans réponse et rendent la demande plus complexe qu'il n'y paraît. C'est pourquoi je suis d'accord que ce serait un bon candidat pour une RFC appropriée qui couvre tout cela si quelqu'un veut vraiment cette fonctionnalité. Jusque-là, plus de +1 ne le font en aucun cas avancer.

@rkingon Il y a déjà un exemple dans https://github.com/vuejs/vue/issues/3666#issuecomment -249583603, mais si le vôtre est différent/meilleur, postez-le. Cela peut être utile pour les novices.

@Gotterbild j'ai raté cet échantillon, mais il est largement trop compliqué dans les versions ultérieures de Vue (cela aurait pu être un support de composant pré-transparent)

en voici une très simple qui convertit simplement un pourcentage en décimal (c'est-à-dire: 4,5 -> .045) et vice versa (valeur "vue" et valeur "modèle")

<template>
    <input type="number" v-on="listeners" v-model="innerValue">
</template>

<script>

    export default {
        props: ['value'],
        computed: {
            listeners () {
                const { input, ...listeners } = this.$listeners
                return listeners
            },
            innerValue: {
                get () {
                    return (this.value) ? `${(this.value * 100)}` : ''
                },
                set (_val) {
                    const val = (_val) ? (_val / 100) : ''
                    this.$emit('input', val)
                }
            }
        }
    }

</script>

c'est plus simple que ce qui précède puisque vous n'avez pas à respécifier tout le focus/blur/etc

@ yyx990803 merci d'avoir donné plus d'informations sur ce sujet.

pour mes cas d'utilisation, je n'ai pas "besoin" de modificateurs personnalisés. c'est juste que du point de vue des consommateurs, il serait logique que vue ait un moyen de créer le vôtre. il a fondamentalement ça pour tout, sauf les modificateurs 😄

alors que je pourrais trouver des moyens de créer quelque chose qui encapsule correctement ma logique de transformation et que je pourrais réutiliser, je pense qu'avoir une API appropriée pour de tels cas d'utilisation ouvrirait un moyen beaucoup plus large de partager du code commun à travers une collection de "meilleur- modificateurs de pratique ».

Je suis venu ici parce que je cherchais à créer un modificateur pour convertir une chaîne en majuscule
Je voulais le créer comme v-model.uppercase="username"

J'ai fini par utiliser la directive personnalisée

Vue.directive('uppercase', {
    update (el) {
        el.value = el.value.toUpperCase()
    },
})

<input type="text" v-model="username" v-uppercase>

Les directives personnalisées devraient suffire pour une alternative.
Ou y a-t-il quelque chose qui n'est possible qu'avec un modificateur de modèle v personnalisé?

@Christhofernatalius considérant v-model est simplement une directive, ne pourriez-vous pas éliminer le v-model en faveur de la directive personnalisée ? de cette façon, vous ne mettez pas à jour deux fois ?

@Christhofernatalius considérant v-model est simplement une directive, ne pourriez-vous pas éliminer le v-model en faveur de la directive personnalisée ? de cette façon, vous ne mettez pas à jour deux fois ?

@rkingon Est-il mis à jour deux fois ?
Donc, si je n'utilise pas v-model, je dois également ajouter un hook bind et unbind pour l'écouteur d'entrée et mettre à jour la valeur du nom d'utilisateur?

EDIT: N'utilise-t-il pas le calcul avec le setter et le getter également mis à jour deux fois?
EDIT 2: j'ai essayé de connecter l'observateur et la directive à la console, chacune n'imprimant qu'une seule fois pour chaque frappe.

Je ne l'ai pas essayé, simplement de la spéculation - je suppose que l'idée de deux directives pour mettre à jour une valeur me semble un peu drôle, mais si vous l'avez vérifié, je ne vois rien de mal à cela.

ma solution de contournement de composant a également des limites, c'est pourquoi je suis toujours en faveur d'un modificateur - c'est-à-dire: il nécessite un élément, plus de temps de rendu, et ne fonctionne que comme un composant dans la façon dont ce composant est défini (c'est-à-dire: un champ de saisie ) vs pouvoir même simplement l'utiliser sur un composant/élément arbitraire qui est le pouvoir d'une directive.

deux façons de dépecer le chat, c'est bien d'avoir des options :)

Existe-t-il une RFC pour cela ?

je ne pense pas

Je pourrais le créer, mais cela signifie-t-il simplement ajouter un problème dans ce référentiel RFC ou autre chose ?

https://github.com/vuejs/rfcs#what -the-process-is cela répond-il à votre question ?

Cela peut-il être rouvert s'il vous plaît ? Une directive personnalisée peut fonctionner dans certains cas, mais le comportement peut être amusant, par exemple :

Vue.directive('number', {
  update: function(el, binding, vnode) {
    el.value = el.value.replace(/[^\d.]/g, '');
  },
});

Si vous ajoutez cette directive (avec un modèle en V) et tapez des lettres très rapidement toutes les autres frappes, le v-model sera désynchronisé avec el.value . Et puisque vous ne pouvez pas modifier l'objet de liaison que vous recevez, il n'y a aucun moyen de "réimplémenter" v-model dans cette directive

@jeankvd Je sais que cela semble exagéré, mais un composant wrapper sera le plus fiable (voir l'exemple ci-dessus).

un composant wrapper vous permettra également de "faire plus". Dans votre exemple "nombre", idéalement, le modèle en V devient en fait un Number . Dans votre approche, c'est toujours un String .

Et si vous souhaitez personnaliser la valeur vide ? Chaîne vide? Nul? Indéfini? -- vous pouvez passer un accessoire pour emptyValue et le définir comme tel.

Bien qu'autrefois un défenseur de cela, j'ai réalisé peu de temps après que les modificateurs avaient beaucoup trop de limitations et que le simple fait d'avoir un composant était de loin supérieur (au moins imo).

Cette page vous a été utile?
0 / 5 - 0 notes