You may already have heard of Alpine.js. If not, then this is "Vue.js at the minimum." "Angular 1 for Millennials." Call it what you want, the main thing that you understand.
Why do we need another framework? Well, Alpine fits well in its niche. In fact, it is an alternative to large frameworks for sites where these large frameworks are not needed. For example, me, a trendy web developer, was harnessed to write a multi-page site. I need to make a form elementary and any other interactive. What will i do? Iβll take jQuery - friends donβt understand, on pure JS writing everything is also not comme il faut. In addition, I already know the reacts, angulars and view, I know what a data-driven approach is. How do I now store data before sending in HTML?
Here Alpine.js comes to the rescue. You can, of course, screw Vue or React. But React without JSX no one in their right mind would write, and Vue minified via CDN weighs 34 kB (versus 8.1 kB for Alpine). So it turns out that the choice falls on Alpine.
Recently here on HabrΓ© there were already familiarization articles about Alpine.js . Apart from the fact that the site cut out references to the template tag everywhere, the articles turned out to be quite good.
In order not to repeat myself, I will not retell the documentation , since it is very short (the whole framework is 13 directives and 6 magic properties) and will soon be available in Russian (at the time of writing, the translation is under the approval of the creator, but itβs already can be read in my fork ).
If you are interested and / or not familiar with Vue, I highly recommend it. For those who are familiar with Vue, a brief description of the key differences:
- Instead, we
v-
use x-
, i.e. not v-model
, but x-model
; not v-bind
, but x-bind
why? This is your homework :) 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)">×</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. , , .
PS For English speakers I also want to advise a "almost completely free" screencast from the creator of Alpine.js. He is so good that even a link is a pity to share. Well then . In it, the author talks about how to create such a framework as Alpine, and that it is not at all as difficult as it might seem.