Vue: Agregue modificadores de modelo v personalizados

Creado en 13 sept. 2016  ·  52Comentarios  ·  Fuente: vuejs/vue

Tenemos .lazy , .number , .trim y .undef está en camino.

Aparte de .lazy , todos funcionan como filtros de dos vías.

Dado que 2.0 no admite filtros bidireccionales, es posible que deba haber una nueva API para agregar modificadores de modelo v personalizados para satisfacer la misma necesidad.

feature request

Comentario más útil

¿Hay alguna posibilidad de que podamos reabrir este problema? Un caso de uso común para mí es la necesidad de formatear automáticamente los datos en un campo a medida que se escriben. Algo así como tomar '101216' y convertirlo en '10/12/16'. Ser capaz de crear un modificador de modelo v personalizado simplificaría enormemente mi código, ya que podría escribir v-model.date en lugar de tener que crear un componente de entrada personalizado con accesorios y eventos.

Todos 52 comentarios

Las propiedades calculadas de @posva no son reutilizables.

Casi todo es reutilizable a través de un mixin.
Puede usar una función que genera un mixin. De esta manera puedes enlazar un
propiedad calculada dinámicamente. No puedo poner ese ejemplo en un violín ahora
pero lo haría lo antes posible.
Sin embargo, estoy de acuerdo en que es un caso de uso muy común que las entradas tengan
transformaciones aplicadas. Una API adecuada o al menos una explicación sobre el
la guía es necesaria

El martes, 13 sep 2016, 18:48 Francisco Lourenço, [email protected]
escribió:

Las propiedades computadas de @posva https://github.com/posva no son reutilizables.


Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/vuejs/vue/issues/3666#issuecomment -246746524, o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AAoicf33lCvETQc9LBQ5GGZ93ExPcLS_ks5qptPegaJpZM4J7vQ0
.

Casi todo es reutilizable a través de un mixin.
Puede usar una función que genera un mixin. De esta manera puedes enlazar un
propiedad calculada dinámicamente. No puedo poner ese ejemplo en un violín ahora
pero lo haría lo antes posible.
Sin embargo, estoy de acuerdo en que es un caso de uso muy común que las entradas tengan
transformaciones aplicadas. Una API adecuada o al menos una explicación sobre el
la guía es necesaria

Dicho de otra manera, las propiedades calculadas no son reutilizables. Puede usar funciones de fábrica + mixins como solución alternativa , pero la facilidad de uso y la legibilidad no se comparan.

Para mi proyecto, necesitaba urgentemente esta función, así que utilicé el enfoque de entrada personalizado recomendado:

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;
      }
    }
  });
});

En mi opinión, este enfoque es muy conveniente y decidí no usar ningún modificador de modelo v, incluido .lazy .

Para casos de uso más personalizados que los modificadores integrados no pueden admitir, lo que mencionó @ecmel es el enfoque recomendado. Lo documentaremos con más detalles en la guía oficial.

La idea de esta propuesta de función es aprovechar la directiva v-model existente, que ya funciona con cada elemento input . Para ahorrar el trabajo de escribir _InputCustom.js_ en cada proyecto, porque eso ya se ha hecho en v-model , teniendo solo que escribir el equivalente de _InputText.js_ en un modificador personalizado, que contiene toda la lógica que necesita modificarse la mayoría de las veces. El hecho de que v-model ya venga con modificadores demuestra que es un patrón intuitivo y deseable. Es natural facilitar la creación de modificadores personalizados, ahorrar el trabajo de crear elementos personalizados y tener que implementar el enlace dom/model manualmente.

Si tiene sentido desde la perspectiva de la API, sería interesante saber cuáles son las limitaciones técnicas que están impulsando la decisión de no implementar esta característica.

¿Hay alguna posibilidad de que podamos reabrir este problema? Un caso de uso común para mí es la necesidad de formatear automáticamente los datos en un campo a medida que se escriben. Algo así como tomar '101216' y convertirlo en '10/12/16'. Ser capaz de crear un modificador de modelo v personalizado simplificaría enormemente mi código, ya que podría escribir v-model.date en lugar de tener que crear un componente de entrada personalizado con accesorios y eventos.

Después de usar vue js por un tiempo en mi proyecto, creo que este problema debería reabrirse.

Al menos necesitamos un modificador undef .

Estoy de acuerdo en que este tema debe ser reabierto. No estoy seguro de qué se supone que debe hacer undef , pero me gustaría un modificador v-model que establezca mi variable en null en caso de que el valor recortado de la entrada sea una cadena vacía.

Me encantaría poder hacerlo yo mismo de una manera sencilla.

Se ha agregado una funcionalidad más redundante que esta, por ejemplo, con https://github.com/vuejs/vue/issues/5194 . Desde el exterior, Vue parece estar comprometiendo lentamente algunos de sus principios a favor de las convenciones y prácticas promovidas por la comunidad de reacción. Ligeramente desviándose de las cualidades que lo hicieron destacar en primer lugar. Sería interesante saber si se trata de una decisión consciente con la intención de facilitar la migración de reaccionar, o simplemente una coincidencia.

Escribir componentes personalizados está bien, pero si desea utilizar un componente personalizado de terceros como https://github.com/text-mask/text-mask/tree/master/vue#readme , no hay una forma directa de desinfectar el enmascarado. entrada a los valores del modelo, excepto el uso de propiedades calculadas.

Entonces, solo quiero usar un campo de entrada estándar HTML [tipo = fecha] para editar un tipo de fecha en mi modelo y este marco maravillosamente poderoso y extensible no puede hacer eso de inmediato. No puedo leer la fecha en el campo, sobrescribo mi fecha con una cadena en mis datos después de seleccionar una fecha. Esta solución podría escribirse en dos líneas con filtros de dos vías o con modificador.

Pero la mejor solución sería admitirlo de forma nativa como lo hacen para la casilla de verificación y otros campos de entrada estándar, ¿por qué la "fecha" es algo especial?

+1 para modificadores personalizados. Parece una obviedad, a menos que haya una buena razón para no hacerlo.

Enmascarar la entrada y analizar el valor para el uso de la aplicación es una práctica muy común, ¡y hacer algo de "azúcar sintático" como v-model.lazy.currency="amount" sería increíble!

1+ para modificadores personalizados.
Tengo una entrada de radio simple con valores verdaderos | falsos que se evalúan como cadenas, pero los necesito como booleanos, las propiedades calculadas no serán inteligentes en este caso, ya que necesito volver a implementar una propiedad calculada para cada entrada de radio. Por ejemplo, tener 100 entradas de radio dará como resultado 100 propiedades calculadas

+1 para modificadores personalizados, pero estoy de acuerdo con tobei: la entrada [tipo = fecha] debería funcionar automáticamente.

+1 para modificadores personalizados.

Vengo de un fondo Angular, y acabo de empezar con vue, y vi este hilo.

Siento que realmente ayudaría tener algo como los analizadores y formateadores de Angular, también en Vue. Si pudiera hacer algo como v-model.dateFormat y resultar en algo como mm/dd/yyyy, sería genial.

EDITAR: parece que reiteró lo que dijo @restored18 . +1 para ti también

+1 para modificadores de modelo v personalizados.

En mi caso, recorro algunos objetos anidados recuperados en JSON y uso una sola plantilla HTML (en lugar de una plantilla por objeto). En este caso, creo que las propiedades calculadas no funcionan.

Actualmente estoy implementando métodos de conversión personalizados entre el formato del servidor y el formato v-model al buscar y enviar datos, pero me encantaría tener algo "incorporado" al que pudiera pasar las funciones.

+1 a esto. Solía ​​estar disponible antes de la 2.2. Puede acceder a la propiedad a través de,

this.$vnode.data.directives

Se eliminó con la adición de valores de entrada de modelos personalizados, pero era una característica muy útil y debería volver al marco.

+1 por esto.

¡Los modificadores de modelo v personalizados serían geniales!

Yo también

+1 en 2018 también...

+1 En mi opinión, es una característica necesaria para el código DRY. En este momento, tengo que crear 10 observadores que hagan lo mismo para un formulario con muchas entradas. Un modificador personalizado lo solucionaría todo.

+1 Acabo de empezar con vue y ya necesito este tipo de filtros bidireccionales...

+1 definitivamente necesario

+1

Puede crear ayudantes como este para la mayoría de los casos de uso IMO

@nickmessing que no cubre el caso de uso (realmente útil) que se describe aquí, que es la modificación en el lugar del texto de entrada. Si tiene un cuadro de entrada que desea que siempre tenga el formato de un teléfono, tendría <input v-model.phone="some_data"> . Cuando el usuario ingresaba texto, automáticamente lo formateaba.

Esto parece una característica tan básica y es más difícil de lo que debería ser en este momento. El comportamiento ya existe en el marco, pero por alguna razón está restringido al código solo del marco. Queremos poder agregar un modificador personalizado que haga esto, que sea reutilizable entre componentes y proyectos, al igual que los filtros y las directivas en este momento.

@bbugh totalmente de acuerdo, tengo un caso similar con el formato de los IBAN y sería una forma agradable y desestimatoria simplemente poner v-model.iban="payment.iban" allí...

@franciscolourenco tal vez alguien podría explicar por qué esto no debería ser compatible con el marco para que se vuelva más obvio.

+1 para modificadores personalizados, hay muchos casos de uso que podrían lograrse con esta característica

En nuestra aplicación, hay pocas entradas diferentes para dar formato a las monedas, siempre almacenamos la cantidad de centavos en el modelo, pero mostramos cantidades de dólares con un formato agradable en las entradas (por lo que 123456 en el modelo se muestra como $1,234.56) <input v-model.dollars="cents" />

Otro caso de uso es desinfectar y eliminar los campos html para evitar ataques XSS (el modelo almacena " A &amp; B " mientras que la entrada muestra " A & B ") <input v-model.html="text" />

+1

+1

+1 para modificadores personalizados.
Me sorprendió mucho que no pueda hacer algo como v-model.trim.uppercase=...

+1

+1

+1

+1
Los modificadores de entrada v-model nativos serían una gran característica. Como la gente menciona aquí, hay muchos casos de uso. Necesitaba modificadores de fecha y moneda para todos los proyectos en los que he estado trabajando.

¿Deberíamos abrir un problema aquí? https://github.com/vuejs/rfcs

ya hice +1 en esto, pero quiero enviar una nota para las personas que necesitan algo "ahora"

mientras que el modificador es mucho más eficiente, he podido lograr el mismo efecto usando una entrada/componente transparente con un campo getter/setter calculado.

puedo compartir un ejemplo si alguien lo necesita

No implementamos esto porque hay muchas cosas a considerar en esta característica aparentemente fácil:

  • Los modificadores incorporados son, de hecho, sugerencias en tiempo de compilación que generan diferentes códigos compilados. Es probable que los modificadores personalizados deban definirse mediante una configuración de tiempo de ejecución, que es un mecanismo diferente.

  • Para la configuración de tiempo de ejecución, ¿qué tipo de API deberíamos exponer para esto?

  • Teníamos filtros de dos vías en el pasado. Una transformación de valor bidireccional requiere que el usuario implemente una lógica impecable para que el enlace bidireccional pueda estabilizarse. De lo contrario, corre el riesgo de poner toda su aplicación en un bucle infinito para casos extremos.

    • La razón por la que tenemos .number y .trim es porque, de hecho, son transformaciones unidireccionales (solo se aplican al sincronizar el valor DOM con los datos del componente) y, por lo tanto, se garantiza que se estabilizarán.
  • ¿Cómo deben comportarse los modificadores personalizados cuando se usa v-model en un componente?

  • ¿Cómo deben comportarse los modificadores personalizados en los tipos de entrada que no son de texto, por ejemplo, radio , checkbox y, lo que es más importante, <select> ?

Todas estas preguntas no tienen respuesta y hacen que la solicitud sea más compleja de lo que parece. Es por eso que estoy de acuerdo en que sería un buen candidato para un RFC adecuado que cubra todo esto si alguien realmente quiere esta función. Hasta entonces, más +1 no lo hace avanzar de ninguna manera.

@rkingon Ya hay un ejemplo en https://github.com/vuejs/vue/issues/3666#issuecomment -249583603, pero si el suyo es diferente/mejor, simplemente publíquelo. Puede ser útil para los novatos.

@Gotterbild me perdí esa muestra, pero es muy complicada en versiones posteriores de Vue (que podría haber sido soporte de componentes pretransparente)

aquí hay uno muy simple que solo convierte un porcentaje a decimal (es decir: 4.5 -> .045) y viceversa (valor de "vista" y valor de "modelo")

<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>

esto es más simple que lo anterior ya que no tiene que volver a especificar todo el enfoque/desenfoque/etc.

@ yyx990803 gracias por brindar más información básica sobre este tema.

para mis casos de uso, no "necesito" modificadores personalizados. es solo que desde la perspectiva de los consumidores, tendría sentido que vue tenga una forma de construir la suya propia. básicamente tiene eso para todo, excepto modificadores 😄

Si bien podría encontrar formas de crear algo que encapsule adecuadamente mi lógica de transformación y que pueda reutilizar, creo que tener una API adecuada para tales casos de uso abriría una forma mucho más amplia de compartir código común a través de una colección de "mejores- modificadores de práctica".

Vine aquí porque estaba buscando hacer un modificador para convertir cadenas a mayúsculas
Quería crearlo como v-model.uppercase="username"

Terminé usando directiva personalizada

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

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

Las directivas personalizadas deberían ser suficientes para una alternativa.
¿O hay algo que solo es posible con el modificador de modelo v personalizado?

@Christhofernatalius considerando que v-model es simplemente una directiva, ¿no podría eliminar el v-model a favor de la directiva personalizada? ¿De esta manera no estás actualizando dos veces?

@Christhofernatalius considerando que v-model es simplemente una directiva, ¿no podría eliminar el v-model a favor de la directiva personalizada? ¿De esta manera no estás actualizando dos veces?

@rkingon ¿Se está actualizando dos veces?
Entonces, si no uso v-model, ¿entonces también necesito agregar enlace y desvincular enlace para el oyente de entrada y actualizar el valor del nombre de usuario?

EDITAR: ¿No se está usando computado con setter y getter también actualizándose dos veces?
EDIT 2: Intenté registrar en la consola el observador y la directiva, cada uno solo imprime una vez por cada pulsación de tecla.

No lo he probado, simplemente especulación: supongo que la idea de dos directivas para actualizar un valor me parece un poco divertida, pero si lo comprobó, no veo nada malo en ello.

la solución de mi componente también tiene limitaciones, por lo que todavía estoy a favor de un modificador, es decir, requiere un elemento, más tiempo de procesamiento y solo funciona como un componente en la forma en que se define ese componente (es decir, un campo de entrada ) frente a poder usarlo simplemente en algún componente/elemento arbitrario que es el poder de una directiva.

dos formas de despellejar al gato, es bueno tener opciones :)

¿Hay un RFC para esto?

No lo creo

Podría crearlo, pero ¿solo significa agregar un problema en ese repositorio RFC o algo más?

https://github.com/vuejs/rfcs#what -the-process-is responde esto a su pregunta?

¿Se puede reabrir esto, por favor? Una directiva personalizada puede funcionar en algunos casos, pero el comportamiento puede ser divertido, por ejemplo:

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

Si agrega esta directiva (junto con un modelo v) y escribe letras muy rápido cada dos pulsaciones de teclas v-model se desincronizará con el.value . Y dado que no puede modificar el objeto vinculante que recibe, no hay forma de "reimplementar" el modelo v dentro de esta directiva

@jeankvd Sé que se siente como una exageración, pero un componente contenedor será el más confiable (vea el ejemplo anterior).

un componente contenedor también le permitirá "hacer más". En su ejemplo de "número", idealmente, el modelo v en realidad se convierte en Number . En su enfoque, sigue siendo un String .

¿Qué sucede si desea personalizar el valor vacío? ¿Cuerda vacía? ¿Nulo? ¿Indefinido? -- puede pasar un accesorio por emptyValue y configurarlo como tal.

Si bien una vez abogué por esto, me di cuenta poco después de que los modificadores tienen demasiadas limitaciones y solo tener un componente es muy superior (al menos en mi opinión).

¿Fue útil esta página
0 / 5 - 0 calificaciones