Crear reactividad sin dependencias es posible. Aquí verás cómo integrar JavaScript Proxy para observar accesos a propiedades, validar errores de uso y mantener un comportamiento por defecto en tu mini framework. La clave: diseñar un handler con trampas como get.
¿Cómo hacer reactividad con JavaScript proxy en un mini framework?
El patrón es simple: origen → proxy (trampas) → destino. El origen es tu objeto de estado; el destino es el mismo objeto, pero interceptado por trampas que controlan la lectura y escritura. Con esto puedes observar accesos, evitar errores silenciosos y preparar la reactividad.
¿Cómo se define el origen y el destino con proxy?
El origen es un objeto con tus datos base.
El destino es el resultado de crear un new Proxy(origen, handler).
El handler es un objeto con trampas como get, set o has.
// Origen: el estado base.const origen ={titulo:"Hola",descripcion:"Estado inicial",};// Destino: el mismo objeto, pero con trampas.const data =newProxy(origen,{get(target, name){console.log('Acceso a propiedad:', name);if(name in target){// Comportamiento por defecto.return target[name];}// Validación y experiencia de uso mejorada.console.warn(`La propiedad "${String(name)}" no existe.`);return"";// Evitar undefined en el template.},});
¿Qué estructura tiene la trampa get?
Parámetros: target (el objeto origen) y name (propiedad solicitada).
Lógica: decidir qué devolver al leer una propiedad.
Resultado: puedes mantener el comportamiento por defecto o personalizar la respuesta.
¿Qué hace la trampa get y por qué aparece undefined?
Cuando interceptas con get, modificas la lectura de propiedades. Si no devuelves nada, obtendrás undefined en el template. Eso ocurrió al principio al solo imprimir en consola el target y el name.
¿Por qué tu template muestra undefined?
Porque la trampa get no retornaba un valor.
JavaScript asume undefined si no hay retorno.
El template refleja ese undefined al pintar la UI.
¿Cómo mantener el comportamiento por defecto?
Devuelve la propiedad del target cuando existe.
Ejemplo: return target[name];.
Si quieres respuestas personalizadas (por ejemplo, siempre "Platzi"), devuélvelo explícitamente.
// Retorno personalizado (ejemplo exploratorio):const data =newProxy(origen,{get(target, name){return"Platzi";// Siempre devuelve este string.}});
// Comportamiento por defecto con validación:const data =newProxy(origen,{get(target, name){if(name in target)return target[name];console.warn(`La propiedad "${String(name)}" no existe.`);return"";}});
¿Qué habilidades y conceptos clave aplicarás con proxys?
Trabajar con proxys te permite controlar la lectura y escritura del estado con una sintaxis directa y extensible. Esto sienta las bases de la reactividad y mejora la DX de tu mini framework.
¿Qué habilidades técnicas practicas?
Definir un origen y un destino con new Proxy.
Implementar trampas como get para observar accesos.
Mantener el comportamiento por defecto con target[name].
Validar propiedades inexistentes y evitar undefined retornando "".
Comunicar errores de uso con console.warn.
¿Qué keywords y conceptos debes recordar?
Proxy: clase interna de JavaScript para interceptar operaciones.
Handler: objeto con trampas como get, set, has.
Trampa get: se ejecuta al leer una propiedad.
Target y name: referencias al objeto origen y a la propiedad solicitada.
Template: capa que dispara lecturas y muestra valores.
Clon interceptado: el destino es "lo mismo" que el origen, pero con trampas.
¿Te gustaría ver ejemplos con otras trampas como set y has, o aplicar estas validaciones en tu componente PText? Comparte cómo lo usarías y qué casos te gustaría cubrir.
Muy buena profe, como sugerencia: Poner las letras de Visual Studio Code un poquito mas grande.
le quitaría el poquito, y pondría , mucho mas grande .
Así durante el curso
a mi no se me mostraban los cambios T.T q hacia dentro del get(){}
si les pasa eso ctrl + f5
Aquí se puede ver cómo un proxy actúa como intermediario (tal como lo dije en una clase pasada), son similares a los getters y setters de una clase, con la diferencia de que, en lugar de tener que llamar a un método, se llama directamente a la propiedad y el proxy la intercepta.
.
Los getters y otras trampas de los proxys se ejecutan justo en el momento en el que se intenta acceder a una propiedad, en este caso, justo cuando dentro de pText accedemos mediante target[name], recordemos que el parámetro target contiene la referencia en memoria de this.$data (nuestro proxy), es por eso que funciona.
.
Les dejo en enlace a mi repositorio de esta clase ^^:
.
https://github.com/RetaxMaster/mini-vue/tree/c18944ae9a6699fbd8e704f1a70a5c636b57eb07
Muchas gracias, tus aportes me han ayudado mucho a entender mejor las clases y comprenderlas desde conceptos con los que estoy más relacionada!
Qué interesante, yo en lo personal para buscar si un elemento posee una propiedad utilizo Object.prototype.hasOwnProperty() y es sencillamente porque le pregunto si directamente posee esa propiedad y no tanto a la cadena de herencia del _property_.
En cuanto a performance, se optimiza la búsqueda a lo largo del objeto además es considerada una buena práctica JavaScript Patterns
¿Por qué data tiene un signo $ adelante?
Muchas gracias.
Buscando rápidamente encontré que no significa algo extra, es solo un carácter más, que se puede usar en los nombres de las variables, así como cualquier otro carácter como "A" o "_". Veo que la pregunta lleva tiempo, estoy apenas haciendo el curso, pero si me estoy equivocado por favor dime, o alguien más que sepa y vea esta duda.
Wow muy interesante clase
Yo vine a aprender Vue, no a aprender a hacer Frameworks :/
Es muy importante tener los conceptos de base claros, para cuando se presente un error o algo en la vida cotidiana, sea facil identificar el por que y como solucionarlo
a ver si comprendí
este target hace referencia al objeto que esta en this.origen no?
this.$data=newProxy(this.origen,{get(target, propKey){//objeto y propif(propKey in target){return target[propKey];}console.warn("La propiedad", name,"no existe");return"";}})
En tu ejemplo "name" no está definido, tendrías que cambiarlo por "propKey" como lo pusiste en los parámetros del getter o cambiar el "propKey" por "name". Solo para mantener consistencia y ahorrarte algún error de ejecución por eso
Si.
No se me mostraban los cambios, ya que no había realizado el cambio en mount del this.origen por this.$data
Entiendo que cuando se hace Reflect.get() se ejecuta la trampa definida en el proxy. Ahora, al hacer esto dentro de la trampa del proxy, ¿no entraría en un bucle?
Puede parecer así a primera vista, pero en realidad lo que sucede cuando hacemos Reflect.get para acceder a la trampa del proxy (get) es que dentro del proxy el target al que estamos haciendo Reflect.get es el objeto original, no el objeto que tiene la trampa puesta.