Saltearse al contenido

Comparación con Vue/React

OWL, React y Vue tienen la misma característica principal: permiten a los desarrolladores crear interfaces de usuario declarativas. Para ello, todos estos frameworks utilizan un DOM virtual. Sin embargo, obviamente siguen existiendo muchas diferencias.

En esta página, intentamos destacar algunas de estas diferencias. Obviamente, se ha hecho un gran esfuerzo para ser justos. Sin embargo, si no estás de acuerdo con algunos de los puntos discutidos, no dudes en abrir un problema o enviar una solicitud de relaciones públicas para corregir este texto.

Tamaño

OWL está pensado para ser pequeño y funcionar a un nivel de abstracción ligeramente inferior al de React y Vue. Además, jQuery no es el mismo tipo de framework, pero es interesante compararlos.

FrameworkSize (minified, gzipped)
OWL18kb
Vue + VueX30kb
Vue + VueX + Vue Router39kb
React + ReactDOM + Redux40kb
jQuery30kb

Tenga en cuenta que estas comparaciones no son del todo justas, ya que no comparamos exactamente el mismo conjunto de características. Por ejemplo, VueX y Vue Router admiten casos de uso más avanzados.

Basado en clases

Ambos React y Vue se mudaron dejando de definir componentes con clases. Ellos prefieren un enfoque más funcional, en particular, con los nuevos mecanismos de hooks.

Esto tiene algunas ventajas y desventajas, pero el resultado final es que tanto React como Vue ofrecen múltiples formas diferentes de definir nuevos componentes. En cambio, Owl solo tiene un mecanismo: componentes basados ​​en clases. Creemos que los componentes Owl son lo suficientemente rápidos para todos nuestros casos de uso, y hacerlo lo más simple posible para los desarrolladores es más valioso (para nosotros).

Además, las funciones o los componentes basados ​​en clases son más que una simple sintaxis. Las funciones tienen una mentalidad de composición y las clases tienen que ver con la herencia. Claramente, ambos son mecanismos importantes para reutilizar el código. Además, uno no excluye al otro.

Sin duda, parece que el mundo de los frameworks de interfaz de usuario se está moviendo hacia la composición, por muchas y muy buenas razones. Owl todavía es bueno en composición (por ejemplo, Owl admite ranuras, que es el mecanismo principal para crear componentes genéricos reutilizables), pero también puede usar herencia (y esto es muy importante ya que las plantillas también se pueden heredar con transformaciones xpaths).

Paso de fabricación/construcción

OWL está diseñado para que sea fácil de usar de forma independiente. Por diversas razones, Odoo no quiere depender de herramientas web estándar (como webpack), y OWL se puede utilizar simplemente añadiendo una etiqueta de script a una página.

<script src="owl.min.js" />

En comparación, React fomenta el uso de JSX, que requiere un paso de compilación, y la mayoría de las aplicaciones Vue utilizan componentes de archivo único, que también requieren un paso de compilación.

Por otro lado, las herramientas externas pueden dificultar su uso en algunos casos, pero también aportan muchos beneficios. Y tanto React como Vue tienen un gran ecosistema.

Tenga en cuenta que, dado que Owl no depende de ninguna herramienta ni biblioteca externa, es muy fácil de integrar en cualquier cadena de herramientas de compilación. Además, dado que no podemos depender de herramientas adicionales, hicimos un gran esfuerzo para aprovechar al máximo la plataforma web.

Por ejemplo, Owl utiliza el analizador xml estándar que viene con todos los navegadores. Por eso, Owl no tuvo que escribir su propio analizador de plantillas. Otro ejemplo es la función auxiliar de la etiqueta xml, que utiliza literales de plantilla nativos para permitir de forma natural escribir plantillas xml directamente en el código javascript. Esto se puede integrar fácilmente con complementos de editor para tener autocompletado dentro de la plantilla.

Plantillas

OWL utiliza su propio motor QWeb, que compila plantillas en el frontend a medida que se necesitan. Esto resulta muy práctico para nuestro caso de uso, en particular porque las plantillas se describen en archivos XML y se pueden modificar mediante XPath. Dado que Odoo es, en esencia, una aplicación modular, esta es una característica importante para nosotros.

<div>
<button t-on-click="increment">Click Me! [<t t-esc="state.value"/>]</button>
</div>

En realidad, Vue es bastante similar. Su lenguaje de plantillas es bastante parecido a QWeb, con la “v” reemplazada por la “t”. Sin embargo, también tiene más funciones. Por ejemplo, las plantillas de Vue tienen ranuras o modificadores de eventos. Una gran diferencia es que la mayoría de las aplicaciones de Vue deberán compilarse con anticipación para compilar las plantillas en funciones de JavaScript. Tenga en cuenta que Vue tiene una compilación independiente que incluye el compilador de plantillas.

Por el contrario, la mayoría de las aplicaciones React no utilizan un lenguaje de plantillas, sino que escriben código JSX, que se precompila en JavaScript simple mediante un paso de compilación. Este ejemplo se realizó con el sistema de clases React (algo anticuado):

class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}

Esto tiene la ventaja de contar con todo el poder de Javascript, pero es menos estructurado que un lenguaje de plantillas. Tenga en cuenta que las herramientas son bastante impresionantes: ¡hay un resaltador de sintaxis para jsx aquí en github!

A modo de comparación, aquí está el componente Owl equivalente, escrito con el asistente de etiqueta xml:

class Clock extends Component {
static template = xml`
<div>
<h1>Hello, world!</h1>
<h2>It is {props.date.toLocaleTimeString()}.</h2>
</div>
`;
}

Renderización asíncrona

En realidad, esta es una gran diferencia entre OWL y React/Vue: los componentes en OWL son totalmente asincrónicos. Tienen dos ganchos asincrónicos en su ciclo de vida:

  • willStart (antes de que el componente comience a renderizarse)
  • willUpdateProps (antes de que se establezcan nuevas propiedades)

Ambos métodos se pueden implementar y devolver una promesa. La representación esperará a que se completen estas promesas antes de aplicar un parche al DOM. Esto es útil para algunos casos de uso: por ejemplo, un componente puede querer obtener una biblioteca externa (un componente de calendario puede necesitar una biblioteca de representación de calendario especializada) en su gancho willStart.

class MyCalendarComponent extends owl.Component {
...
willStart() {
return utils.lazyLoad('static/libs/fullcalendar/fullcalendar.js');
}
...
}

Esto puede ser peligroso (detener la representación mientras se espera a la red), pero también es extremadamente poderoso, como lo demuestra el cliente web de Odoo.

Obviamente, es posible cargar bibliotecas estáticas de forma diferida con React/Vue, pero es más complicado. Por ejemplo, en Vue, es necesario utilizar una palabra clave de importación dinámica que debe transpilarse en el momento de la compilación para que el componente se cargue de forma asincrónica (consulte la documentación).

Reactividad

React tiene un modelo simple: cada vez que cambia el estado, se reemplaza por un nuevo estado (a través del método setState). Luego, se aplica un parche al DOM. Es un proceso simple, eficiente y un poco complicado de escribir.

Vue es un poco diferente: reemplaza mágicamente las propiedades del estado por métodos get/setters. Con eso, puede notificar a los componentes cuando se modifique el estado que leen.

Owl se parece más a vue: también rastrea mágicamente las propiedades del estado, pero solo incrementa un contador interno cada vez que cambia. Tenga en cuenta que se realiza con un “Proxy”, lo que significa que es totalmente transparente para los desarrolladores. Se admite la adición de nuevas claves. Una vez que se ha cambiado cualquier parte del estado, se programa una representación en el siguiente tic de microtarea (cola de promesas).

Hooks

Los Hooks se han apoderado recientemente del mundo de React. Resuelven muchos problemas aparentemente inconexos: adjuntar un comportamiento reutilizable a un componente de forma componible, extraer lógica con estado de un componente o reutilizar lógica con estado entre componentes sin cambiar la jerarquía de componentes.

Aquí hay un ejemplo del gancho useState de React:

import React, { useState } from "react";
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}

Debido a la forma en que React diseñó la API de hooks, estos solo funcionan para componentes funcionales. Pero en ese caso, son realmente poderosos. Todas las bibliotecas principales de React están en proceso de rediseñar su API con hooks (por ejemplo, Redux).

Vue 2 no tiene ganchos, pero el proyecto Vue está trabajando en su próxima versión, que contará con su nueva API de composición. Este trabajo se basa en las nuevas ideas introducidas por los ganchos de React.

Por la forma en que React y Vue presentan sus ganchos, puede parecer que los ganchos no son compatibles con los componentes de clase. Sin embargo, este no es el caso, como lo demuestra Owl hooks. Están inspirados tanto en React como en Vue. Por ejemplo, el gancho useState lleva el nombre de React, pero su API es más parecida al gancho reactive de Vue.

Así es como se ve el ejemplo ‘Contador’ anterior en Owl:

import { Component, Owl } from "owl";
import { xml } from "owl/tags";
class Example extends Component {
static template = xml`
<div>
<p>You clicked {count.value} times</p>
<button t-on-click="increment">Click me</button>
</div>`;
count = useState({ value: 0 });
increment() {
this.state.value++;
}
}

Dado que el framework Owl tenía ganchos desde el principio, sus API principales están diseñadas para interactuar con ganchos desde el principio. Por ejemplo, la abstracción Context.