译者 | 李睿
审校 | 孙淑娟
前端JAVAScript框架的创新是当今这个时代最伟大的技术文化现象之一。20多年来,人们见证了进化创造力的长尾。每一个新的想法都进行尝试,在软件开发过程和开发人员构建的最终产品中都会促进改进。
Alpine.js是近年来脱颖而出的框架之一。Alpine.js是一个极简主义框架。顾名思义,用于克服大量的困难(在崎岖的山地)进行轻操作。它在一个简洁、易于掌握的软件包中提供了很多的动力。本文将对Alpine.js进行介绍,这样就可以理解它提供了什么,以及它在什么时候可能有用。
正如Alpine.js文档所描述的,Alpine的API是15个属性、6个特性和2个方法的集合。这是一个非常小的API配置文件。其极简主义的目的是以干净的格式提供反应性,并辅以一些周围的细节,例如事件和中央商店。
考虑清单1中非常简单的Web页面。
<html>
<head>
<script src="https://unpkg.com/alpinejs@3.10.3/dist/cdn.min.js" defer></script>
</head>
<body>
<div x-data="">
<span x-text="'Text literal'"></span>
</div>
</body>
</html>
除了通过CDN包含Alpine包,这里仅有的两个与Alpine相关的是指令x-data和x-text。
如果将其放入系统上的HTML页面并在浏览器中查看,将会看到消息输出“文本文字”。虽然这个应用程序不是特别令人印象深刻,但它演示了Alpine的两个有趣方面。
首先,为了使反应性发挥作用,必须将标记包含在x-data指令中。如果删除该指令,则x-text将不会生效。本质上,x-data指令创建了一个Alpine组件。在这个例子中,x-data指令是空的。在实际使用中,这里几乎总是有数据。毕竟,正在编写的组件的目的是响应数据。
清单1中要注意的第二件事是,可以将任何有效的JavaScript放入x-text中。所有的Alpine指令都是如此。
x-data内容提供给所有包含的元素。要理解这个意思,可以查看清单2。
<div x-data="{ message: 'When in the course of human events...' }">
<span x-text="message"></span>
</div>
现在该页面将输出美国《独立宣言》的开头部分。可以看到x-data定义了一个简单的老旧JavaScript对象,只有一个字段“message”,其中包含声明的序言。x-text指向这个对象字段。
接下来,将使用反应性来修复声明中的错误。可以了解清单3。
<div x-data="{ pronoun: 'men' }">
<button x-on:click="pronoun = 'people'">Fix It</button>
<span x-text="`all ${pronoun} are created equal`"></span>
</div>
x-text指令指的是由x-data指令公开的代词变量。这里的新部件是按钮,它有一个x-on:click指令。这个单击事件的处理程序将旧的默认代词替换为中性代词,反应性负责更新x-text中的引用。
Alpine中的数据属性是功能齐全的JavaScript对象。考虑处理上述需求的另一种方法,如清单4所示。
<div x-data="{
pronoun: 'men',
fixIt: function(){
this.pronoun = 'people';
}
}">
<button x-on:click="fixIt()">Fix It</button>
<span x-text="`all ${pronoun} are created equal`"></span>
</div>
在清单4中,可以看到数据对象现在拥有一个由click处理程序调用的fixIt方法。
另外,有时会看到应用程序代码从x-data指令调用脚本标记中定义的函数——这是个人偏好,它的操作与内联x-data完全相同:
<div x-data="myDataFunction()">...</div>
...
<script>
function myDataFunction() {
return {
foo: "bar"
}
}
</script>
现在转换话题,可以考虑一个更复杂的需求。假设想从外部API加载一个json格式的美国总统列表。我们要做的第一件事是在页面加载时加载它。为此将使用x-init指令,例如清单5所示。
<div x-data="{
presidents: []
}"
x-init="(
async () => {
const response = await fetch('https://raw.Githubusercontent.com/hitch17/sample-data/master/presidents.json');
presidents = await response.json();
}
)">
<span x-text="presidents"></span>
</div>
在这里发生了什么?首先,x-data指令应该很清楚:它只是有一个带有空数组的总统(presidents)字段。span元素中的x-text输出该字段的内容。
x-init代码有点复杂。首先,注意它被包装在一个自动执行的函数中。这是因为Alpine需要函数,而不是函数定义。(如果要使用fetch的非异步回调形式,则不需要像这样包装函数。)
一旦从端点获得了presidents列表,将其插入到presidents变量中,Alpine将其作为x-data对象的一部分公开。
重申一下:Alpine.js正在使a-data中的数据可用于同一场景中的其他指令函数(例如x-init)。
此时,应用程序正在从远程端点提取数据并将其保存到状态中。需要注意,它输出的内容类似于[Object],[Object]....这不是想要的。可以了解一下遍历数据的过程,例如清单6所示。
<div x-data=...>
<ul>
<template x-for="pres in presidents">
<li><div x-text="pres.president"></div>
From: <span x-text="pres.took_office"></span> Until: <span x-text="pres.left_office"></span></li>
</template>
</ul>
</div>
清单6包含一个普通的无序列表,后面跟着一个HTML模板元素,其中包含一个x-for指令。这个指令的操作与在其他响应式框架中看到的类似。在本例中,它允许指定一个集合、总统(presidents)和一个标识符,该标识符将提供给表示该集合的每个实例的封闭标记,在本例中为pres。
标记的其余部分使用pres变量通过x-text从对象中输出数据。
其应用程序现在看起来如图1所示。
图1美国总统的名单
现在要设置应用程序,以便通过单击总统的名称来切换总统的数据。首先,将标记修改为清单7所示的内容。
<template x-for="pres in presidents">
<li><div x-text="pres.president" x-on:click="pres.show = ! pres.show"></div>
<div x-show="pres.show">
From: <span x-text="pres.took_office"></span> Until: <span x-text="pres.left_office"></span></li>
</div>
</template>
现在,在清单7中,可以在包含总统详细信息的div上使用x-show指令。x-show值的真实性决定内容是否可见。在本例中,这是由pres.show字段决定的 (注意的是,在实际应用程序中,可能不希望使用实际业务数据来承载show/hide变量) 。
为了改变press.show的值,在标头文件中添加一个x-on:click处理程序。这个处理程序简单地交换了press.show的true/false值:press.show=!pres.show。
Alpine包含内置转换功能,可以应用于显示/隐藏特性。清单8显示了如何添加默认动画。
<div x-show="pres.show" x-transition>
From: <span x-text="pres.took_office"></span> Until: <span x-text="pres.left_office"></span></li>
</div>
唯一改变的是,带有x-show指令的元素现在也有一个x-transition指令。在默认情况下,Alpine应用合理的转换。在这种情况下,转换是一种滑动和渐变效果。可以广泛地自定义转换,包括将自己的css类应用于动画的各个阶段。
现在,将添加一个简单的过滤器功能。这将需要添加一个绑定到数据的输入,然后根据该值筛选返回的数据集。可以在清单9中看到更改。
<div x-data="{
filter: '',
presidents: [],
getPresidents: function(){
return this.presidents.filter(pres => pres.president.includes(this.filter) )
}
}"
...
<input x-model="filter" />
...
<ul>
<template x-for="pres in getPresidents">
注意,x-data对象现在有一个“filter”字段。这是通过指向“filter”的x-model指令双向绑定到输入元素的。
已经更改了模板x-for指令,以引用一个新的getPresidents()方法,该方法在x-data对象上实现。该方法使用标准JavaScript语法,根据总统是否在筛选字段中包含文本来筛选。
就像它的名字一样,Alpine.js是一个轻量级的软件包,里面有着基本的装备,可以“穿越高山”。这是最小的软件包,但已经足够了。
该框架包括一些更高级的功能,特别是中央存储和事件系统,以及插件架构和生态系统。
总之,Alpine.js是符合人体工程学。如果你有使用其他响应式框架的经验,那么Alpine应该会很快学会,在x-data指令中声明组件及其数据的简单性。
可能想知道组件间的通信。Alpine.js避免了组件之间的显式连接(例如,没有父-子道具)。与其相反,它通过$dispatch指令使用浏览器环境(即窗口)作为事件总线。这符合Alpine的理念,即添加足够的功能来增强现有的功能。它工作得很好。
随着应用程序的规模和复杂性的增长,所有这些元素都将受到考验。所以它适用于选择的任何堆栈。Alpine.js是你下次进行代码冒险的一个诱人选择。
原文标题:Intro to Alpine.js: A JavaScript framework for minimalists,作者:Matthew Tyson