alpinejs框架使用简介
Alpine.js是一个轻量级的JavaScript框架,设计灵感来源于Tailwind Css和Vue.js,就是一个借鉴Vue语法的JS版的Tailwind
Alpine.js的官方github网址:github.com/alpinejs/alpine
Alpine.js无需安装,不依赖虚拟 DOM,模板通过遍历 DOM 来解析
Alpine.js的一些主要特点:
1. 无需安装:同时支持npm方式和传统的script标签引入方式 2. 轻量级:核心库非常小,非常适合快速加载的网页 3. 声明式语法:使用声明式的语法,通过HTML属性来定义行为和状态 4. 响应式:提供响应式数据绑定,轻松地处理状态变化并自动更新DOM 5. 简单易学:学习曲线相对较平缓,适合熟悉 HTML和基本JavaScript的开发者 6. 组件化:支持组件化开发方式,将复杂的 UI 逻辑分解为可重用的组件 7. 与其他框架兼容:可以与其他前端框架共存,适合逐步迁移或增强现有应用
安装或引入
通过访问https://cdn.jsdelivr.net/npm/alpinejs/dist/来确定需要引入的版本和文件
cdn用于作为js脚本,cjs用于node,esm用于ES6的模块
npm方式
安装:npm install alpinejs 引入:import Alpine from 'alpinejs' 初始化:Alpine.start() 每个页面一般只调用一次Alpine.start(),多次调用将导致Alpine的多个“实例”同时运行
Script标签方式
模块方式
<script type="module">
import Alpine from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/module.esm.min.js';
Alpine.start();
</script>
常规方式
<script defer src="/static/js/src.js"></script>
其中defer标记为必须属性,用于自动初始化
Alpine的使用
Alpine的所有行为和状态都是通过自定义HTML属性来实现的,这些自定义HTML属性称之为指令
Alpine的所有指令都是以"x-"作为前缀(该项目名字确定之前项目名为project-x)
Alpine的所有指令的值都视为js代码
x-data
x-data指令用于标记Alpine管控该元素及其所有子元素的渲染,该HTML元素称之为Alpine组件
也就是说只有使用了该指令的元素才会被视为需要Alpine控制,否则会被视为普通的html元素
x-data用于指定组件的同时也用于向组件传递专用数据,传递的值为一个对象,或一个返回对象的函数
<div x-data="{ name:"清河洛", run(){ console.log("i am running");} }" ></div> 或者 function getdata(){ return { name : "清河洛", run(){ console.log("i am running");}, get GetName(){ return this.name; }, init(){...}, } } <div x-data="getdata()" ></div>
如果传递数据的方法中有init()函数会自动调
x-data指令传递的数据可用于其本身及所有子元素
x-data可以嵌套使用
x-ignore
强制Alpine忽略管控使用该指令的元素
x-init
该指令是唯一可用于所有html元素(非Alpine组件也可以)且都生效的指令
表示在开始初始化该元素时执行的js代码
x-data传递的init()函数优先级更高,会优先于该指令调用之前调用
显示和隐藏指令
x-show 根据指定的值的bool值来确定元素的显示和隐藏,通过修改css的display属性值none来实现隐藏
<div x-show="open" >...</div>
x-if 也用于元素的显示可隐藏,与x-show不同的是x-if在隐藏时是直接将元素删除
由于这种差异,x-if不能直接应用于元素,而要包含于<template>元素中
<template x-if="open"> ... </template>
x-transition 用于在显示或隐藏元素时创建平滑过渡效果
<div x-show="open" x-transition>Hello</div>
默认过渡效果为淡化+缩放,入场时间150ms,离场时间75ms
设置过渡效果
x-transition:enter 进场设置
x-transition:leave 离场设置
x-transition 同时设置进场和离场
duration.500ms 持续时间
elay.50ms 在进场和离场开始时的延迟时间
x-transition:enter.duration.500ms 设置进场持续时间
x-cloak 在使用x-show或x-if指令时,如果传递的值初始化为false,在组件初始化时可能会有短暂的显示
为了解决该"bug",添加了该指令用于防止在初始化时隐藏元素的任何“短暂”出现
要使用该指令,需要在CSS中添加
[x-cloak] { display: none !important; } <span x-cloak x-show="false">some code</span>
x-cloak不仅对x-show或x-if初始化隐藏的元素有效,还可以用来确保元素在数据被正确设置之前被隐藏
<span x-cloak x-text="message"></span> 将隐藏<span>元素,直到Alpine将其文本内容设置为message属性
数据绑定指令
x-text 将文本内容设置为给定表达式的结果,如果结果中有html代码会进行转义,用于非表单元素
x-html 与x-text类似,但是不会转义html代码,有安全风险
x-model 数据双向绑定,用于表单元素
x-modelable 将一个父级变量绑定到局部变量,外部访问该父级变量时指向该局部变量
需要与x-model配合使用,x-model指定外部变量,x-modelable指定内部变量
<div x-data="{ number: 5 }">
<div x-data="{ count: 0 }" x-modelable="count" x-model="number">
<button @click="count++">Increment</button>
</div>
Number: <span x-text="number"></span>
</div>
上面代码中将一个父级变量number绑定到局部变量count,在外部使用该变量时会指向count变量
x-bind
用于绑定任意html属性,包括自定属性
<div x-bind:class="closed && 'hidden'" >...</div> <input x-bind:value="msg" > x-bind指定还提供了一种简写形式,仅保留最后的冒号":" <div :class="closed && 'hidden'" >...</div> <input :value="msg" >
Alpine还为class属性设置了多种支持格式
三元运算或短路运算 <div x-bind:class="closed && 'hidden'" >...</div> 传递对象,对象的键名解析为类名,值的bool属性确定是否添加该class类 <div x-bind:class="{ "active": false, "show": true }" >...</div> Alpine还会自动分析元素现有的class类后在现有类之后附加计算后的类而不是直接覆盖 <div class="w-760" x-bind:class="closed && 'hidden'" >...</div> 会渲染为 <div class="w-760 hidden" >...</div> 或 <div class="w-760" >...</div>
当绑定style时,需要传递一个对象,元素的键为css的属性,对应的值为该css属性的值
<div x-bind:style="{ display: open, font-size: '1.5rem' }" >...</div>
事件相关指令
x-on 用于添加任意事件监听,包括自定事件
<div x-on:click="..." >...</div> <input x-bind:change="..." > x-on指定还提供了一种简写形式,使用"@"替代 <div @click="..." >...</div> <input @change="..." >
在该指令中可以使用$event魔法属性获取触发的事件对象
<div x-on:click="alert($event.target.innerHTML)" >...</div>
事件触发的运行函数如果省略括号会默认传递事件对象
<div x-on:click="func" >...</div> 运行func($event)
键盘事件
通过@keydown 和 @keyup监听键盘事件,通过属性来添加(可以链式添加)监听的按键
<div @keydown.shift.enter="..." >...</div> // 同时按住Shift和Enter 支持的按键点击查看,需要将该页中的键名转化为"-"连接的小写 如PageDown转化为page-down 常用的有:shift、enter、ctrl、space、cmd、meta、alt、tab、 up、down、left、right等
鼠标事件
常用的鼠标事件有
click, auxclick, context, dblclick, mouseup, mousedown mouseover, mousemove, mouseenter, mouseleave, mouseout
另外还支持一些修饰符,表示在指定按键按下的状态下鼠标事件
shift、ctrl、cmd、meta、alt
所有事件均可用的共用修饰符
prevent 禁用默认行为 stop 取消冒泡捕获 outside 监听所在元素之外的触发事件 window 在window对象上注册而不是元素本身 document 在document global上注册 once 处理程序仅被调用一次 debounce 防抖,默认250ms @input.debounce.500ms 指定防抖时间 throttle 节流,默认250毫秒 @scroll.document.throttle.500ms self 仅触发自身事件,不处理来自子元素的事件 passive 性能优化,主要用于频繁触发的事件,如触摸、滚动、鼠标移动等 capture 冒泡捕获
列表循环指令
x-for 通过遍历来创建一系列DOM元素
x-for只能在<template>
元素上使用且该<template>
元素必须仅包含一个根元素
<template x-for="(val,index) in list_obj" :key="index">
<p>
<span x-text="index"></span>:<span x-text="val"></span>
</p>
</template>
当仅有一个接收变量时会返回值而忽略索引
上例中每次循环生成两个span元素,因为<template>仅能包含一个根元素,所以我们使用p标签包含
如果动态生成列表,那排序会错乱,这时使用:key指定唯一键用于确定顺序
x-for还可以循环一个整数,表示从1开始至指定整数(包含该整数)的列表
模块相关指令
x-teleport 将一个模板追加到该指令指定的DOM中
值可以是任何合法的CSS选择器,如果有多个DOM匹配则选择第一个匹配的DOM元素
<template x-teleport="body">
<div>comecode</div>
</template>
示例表示将指定的内容追加到body的DOM中
注意该方式中模板中的命名空间仍然是该模板编写时所在的命名空间
其他指令
x-effect 指定一个表达式,每当表达式中任何值发生改变时运行整个表达式,类似于svelte中的"$:"
<div x-effect="console.log(label)"></div>
x-ref 与预定义变量$refs配合来快捷的访问DOM元素
x-ref指定DOM元素名称,$refs.name获取指定名称的DOM
<button @click="$refs.text.remove()">Remove</button>
<span x-ref="text">Hello</span>
x-id 与预定义函数$id(text)一起使用创建当前页面唯一ID
参数text表示id名称,生成的id会在名称之后自动添加后缀
<input type="text" :id="$id('myinput')">
<!-- id="myinput-1" -->
<input type="text" :id="$id('myinput')">
<!-- id="myinput-2" -->
有时候需要生成相同的id,如laber的for属性,用来与表单元素绑定时需要与该表单元素的id相同
可以使用以下来实现
<div x-data="{ id: $id('text-input') }">
<label :for="id"> <!-- "text-input-1" -->
<input type="text" :id="id"> <!-- "text-input-1" -->
</div>
<div x-data="{ id: $id('text-input') }">
<label :for="id"> <!-- "text-input-2" -->
<input type="text" :id="id"> <!-- "text-input-2" -->
</div>
x-id指令就是用于创建id组来实现上述功能
x-id的值为一个列表,表示在该元素中要创建的id组名
<div x-id="['text-input']">
<label :for="$id('text-input')"> <!-- "text-input-1" -->
<input type="text" :id="$id('text-input')"> <!-- "text-input-1" -->
</div>
<div x-id="['text-input']">
<label :for="$id('text-input')"> <!-- "text-input-2" -->
<input type="text" :id="$id('text-input')"> <!-- "text-input-2" -->
</div>
预定义变量
除了上面已经介绍的$refs和$id两个预定义变量,还有其他的预定义变量
$el 用于表示当前DOM节点
<button @click="$el.innerHTML = 'Hello World!'">Replace</button>
$store 获取使用Alpine.store()注册的全局状态
$store.name获取指定名称的全局状态
$watch 监控指定的变量,当变量的值改变时运行回调函数
$watch(val,(new_val[,old_val])=>{})
当监控一个obj等复杂值时,会自动进行深度监控,任何一个子属性改变都将触发回调
在回调中进行值的修改会导致无限递归死循环
$dispatch 触发指定事件,包括自定义事件
$dispatch(event_name[,data])
event_name表示事件名称
可选参数data表示要传递的数据,通过事件对象的detail属性获取
<div @diyevent="alert($event.detail.msg)">
<button @click="$dispatch('diyevent', { msg: 'demo' })">Demo</button>
</div>
$nextTick 在进行响应式DOM更新完成后执行给定的表达式,一般为回调函数
<button @click="title='new_cont';$nextTick(() => { console.log($el.innerText) });" x-text="title"></button>
$nextTick()返回的是一个promise,借用该特性,上面的代码可以写为
<button @click="title='new_cont';await $nextTick();console.log($el.innerText);" x-text="title"></button>
$root 获取该元素所在DOM数向上最接近的包含x-data的DOM元素
$data 获取当前命名空间所有可用的数据
预定义事件
Alpine预定义了一些特定的自定义事件,用于在生命周期中进行相关操作
alpine:init 在Alpine加载之后 + 初始化之前触发,多用于设置全局变量、状态等
document.addEventListener('alpine:init', () => { ... })
alpine:initialized 在Alpine初始化完成之后触发
全局控制
全局控制包含全局变量设置、全局状态设置和全局绑定,这些必须在Alpine加载之后 + 初始化之前定义
如果通过模块方式使用Alpine则在运行Alpine.start()之前定义
如果通过script标签引入,则需要在document.addEventListener('alpine:init', () => { ... })回调函数中定义
全局变量 :Alpine.data(name,func),定义一个值全局变量name,值为func函数返回值(一个对象)
Alpine.data('myglobal', () => ({
name: '三千'
}))
<div x-data="myglobal">
<p x-text="name"></p>
</div>
如果func的返回值中有几个特殊的属性
init()方法 在渲染组件之前自动执行
destroy()方法 在清理组件之前自动执行
全局状态 :Alpine.store(name,val),定义一个值全局状态name,值为val
val可以是任意js支持的数据,如果val为一个对象,那么init()方法将在注册store后自动执行
全局属性组 :Alpine.bind(name,obj_val),由obj_val创建一组可复用的属性组name
创建一组可复用的属性组,通过x-bind="name"进行绑定
Alpine.bind('SomeButton', {
'type': 'button',
'id': 'mybut',
'@click': function () { this.text = 'new'; },
':disabled': () => true,
})
键名为一个指令时,值必须为一个函数
<div x-data="{ text: 'Hello'}">
<input x-bind="SomeButton" x-model="text" />
</div>