Alpine.js en un ejemplo concreto

Es posible que ya haya oído hablar de Alpine.js. Si no, entonces esto es "Vue.js como mínimo". "Angular 1 para Millennials". Llámalo como quieras, lo principal que entiendes.


¿Por qué necesitamos otro marco? Bueno, Alpine encaja bien en su nicho. De hecho, es una alternativa a los grandes marcos para sitios donde estos grandes marcos no son necesarios. Por ejemplo, yo, un desarrollador web de moda, fui aprovechado para escribir un sitio de varias páginas. Necesito hacer un formulario elemental y cualquier otro interactivo. ¿Que haré? Tomaré jQuery: los amigos no entienden, en la escritura pura de JS, todo no está mal. Además, ya sé las reacciones, los ángulos y la vista, sé lo que es un enfoque basado en datos. ¿Cómo almaceno ahora los datos antes de enviarlos en HTML?


Aquí Alpine.js viene al rescate. Puede, por supuesto, atornillar Vue o React. Pero Reaccionar sin JSX nadie en su sano juicio escribiría, y Vue minified a través de CDN pesa 34 kB (frente a 8.1 kB para Alpine). Entonces resulta que la elección recae en Alpine.


Recientemente aquí en Habré ya había artículos de familiarización sobre Alpine.js . Además del hecho de que el sitio recortaba referencias a la etiqueta de la plantilla en todas partes, los artículos resultaron ser bastante buenos.


Para no repetirme, no volveré a contar la documentación , ya que es muy corta (el marco completo tiene 13 directivas y 6 propiedades mágicas) y pronto estará disponible en ruso (en el momento de la redacción, la traducción está bajo la aprobación del creador, pero ya está se puede leer en mi tenedor ).


Si está interesado y / o no está familiarizado con Vue, lo recomiendo encarecidamente. Para aquellos que están familiarizados con Vue, una breve descripción de las diferencias clave:


  • En cambio, v-usamos x-, es decir No v-model, pero x-model; No v-bind, pero x-bind¿por qué? Esta es tu tarea :)
  • x-if x-for template. Virtual DOM.
  • {{}} . x-text x-html, Vue.

.


, . . - ? – . – , , . – " , " .. ..


, , .


HTML, CDN Alpine


<!DOCTYPE html>
<html lang="ru">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>To-Do  Alpine.js</title>
    <script
      src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.3.5/dist/alpine.min.js"
      defer
    ></script>
  </head>
  <body></body>
</html>

Alpine , . .


, ? . x-data.


<div x-data="{ name: '' }">
  <p>, <span x-text="name"></span></p>
</div>

<div> , . name <div> .


, to-do. :


<div
  x-data="{ todos: [{id: 1, title: ' ', completed: false}, {id: 2, title: ' ', completed: false}, {id: 3, title: '  ', completed: false}, {id: 4, title: '  ', completed: false}] }"
>
  <h1>  :</h1>
  <ul>
    <template x-for="todo in todos" :key="todo.id">
      <li x-text="todo.title"></li>
    </template>
  </ul>
</div>

. , , CSS- .completed, x-bind:class ( {[ ]: []}). cursor: pointer li, .


<style>
  .completed {
    text-decoration: line-through;
  }

  li {
    cursor: pointer;
  }
</style>

<div
  x-data="{ todos: [{id: 1, title: ' ', completed: false}, {id: 2, title: ' ', completed: false}, {id: 3, title: '  ', completed: false}, {id: 4, title: '  ', completed: false}], toggleTodo: function(id) { var todo = this.todos.find((todo) => todo.id === id); todo.completed = !todo.completed; } }"
>
  <h1>  :</h1>
  <ul>
    <template x-for="todo in todos" :key="todo.id">
      <li
        x-text="todo.title"
        @click="toggleTodo(todo.id)"
        :class="{'completed': todo.completed}"
      ></li>
    </template>
  </ul>
</div>

, , . , x-data :


<div x-data="todos()">
  <h1>  :</h1>
  <ul>
    <template x-for="todo in todos" :key="todo.id">
      <li
        x-text="todo.title"
        @click="toggleTodo(todo.id)"
        :class="{'completed': todo.completed}"
      ></li>
    </template>
  </ul>
</div>

<script>
  function todos() {
    return {
      todos: [
        { id: 1, title: ' ', completed: false },
        { id: 2, title: ' ', completed: false },
        { id: 3, title: '  ', completed: false },
        { id: 4, title: '  ', completed: false },
      ],
      toggleTodo: function (id) {
        var todo = this.todos.find((todo) => todo.id === id);
        todo.completed = !todo.completed;
      },
    };
  }
</script>

… Vue.


input :


<div x-data="todos()">
  <!-- ... -->
  <div>
    <h4>  :</h4>
    <input type="text" x-model="inputValue" />
    <button @click="addTodo()"></button>
  </div>
</div>

<script>
  function todos() {
    return {
      // ...
      inputValue: '',
      addTodo: function () {
        if (!this.inputValue) {
          return;
        }

        this.todos.push({
          id: Date.now(),
          title: this.inputValue,
          completed: false,
        });
        this.inputValue = '';
      },
    };
  }
</script>

push() , Alpine , - .


– . <li> span: , – .


<ul>
  <template x-for="todo in todos" :key="todo.id">
    <li @click="toggleTodo(todo.id)" :class="{'completed': todo.completed}">
      <span x-text="todo.title"></span>
      <span @click="deleteTodo(todo.id)">&times;</span>
    </li>
  </template>
</ul>

<script>
  function todos() {
    return {
      // ...
      deleteTodo: function (id) {
        this.todos = this.todos.filter((todo) => todo.id !== id);
      },
    };
  }
</script>

.


, , , REST API. , JSON Placeholder. x-init.


<div x-data="todos()" x-init="fetchTodos()">
  <!-- ... -->
</div>

<script>
  function todos() {
    return {
      // ...
      todos: [],
      fetchTodos: function () {
        fetch('https://jsonplaceholder.typicode.com/todos')
          .then((response) => response.json())
          .then((data) => {
            this.todos = data.slice(0, 10);
          });
      },
    };
  }
</script>

x-init DOM ( created Vue). – , ( mounted).
, ?_limit=10, query , , .


. Alpine.js. . , . , , .


sandbox. , , .


PD: Para los angloparlantes, también quiero recomendar un screencast "casi completamente gratuito" del creador de Alpine.js. Es tan bueno que incluso un enlace es una pena compartirlo. Bien entonces . En él, el autor habla sobre cómo crear un marco como Alpine, y que no es tan difícil como parece.

All Articles