跳转至

响应式

Alpine 是"响应式"的,意思是当你更改一段数据时,所有依赖该数据的东西都会自动"响应"这一更改。

Alpine 中发生的每一处响应式行为,都源于 Alpine 核心中两个非常重要的响应式函数:Alpine.reactive()Alpine.effect()

Alpine 在底层使用 VueJS 的响应式引擎来提供这些函数。 → 阅读更多关于 @vue/reactivity

理解这两个函数将为你作为 Alpine 开发者带来超能力,甚至作为一般的 Web 开发者也是如此。

Alpine.reactive()

首先来看 Alpine.reactive()。该函数接受一个 JavaScript 对象作为参数,并返回该对象的"响应式"版本。例如:

let data = { count: 1 }

let reactiveData = Alpine.reactive(data)

在底层,当 Alpine.reactive 接收到 data 时,会将其包裹在一个自定义的 JavaScript Proxy 中。

Proxy 是 JavaScript 中一种特殊的对象,可以拦截对 JavaScript 对象的"get"和"set"调用。

→ 阅读更多关于 JavaScript Proxy

从表面上看,reactiveData 的行为应该与 data 完全一样。例如:

console.log(data.count) // 1
console.log(reactiveData.count) // 1

reactiveData.count = 2

console.log(data.count) // 2
console.log(reactiveData.count) // 2

你在这里看到的是,因为 reactiveDatadata 的薄包装层,任何对属性的 get 或 set 操作的行为都与你直接操作 data 完全相同。

主要的区别在于,任何时候你修改或检索(get 或 set)reactiveData 的值时,Alpine 都能感知到,并可以执行任何依赖该数据的其他逻辑。

Alpine.reactive 只是故事的一半。Alpine.effect 是另一半,让我们深入了解。

Alpine.effect()

Alpine.effect 接受一个回调函数。一旦 Alpine.effect 被调用,它将立即运行所提供的函数,同时主动寻找与响应式数据的任何交互。如果它检测到交互(上述响应式 proxy 的 get 或 set 操作),它将跟踪该交互,并确保在将来任何响应式数据发生变化时重新运行该回调。例如:

let data = Alpine.reactive({ count: 1 })

Alpine.effect(() => {
    console.log(data.count)
})

当这段代码首次运行时,"1" 将被记录到控制台。每当 data.count 发生变化时,其值将再次被记录到控制台。

这就是解锁 Alpine 核心中所有响应式机制的机制。

为了进一步串联起来,让我们看一个简单的"计数器"组件示例,完全不使用 Alpine 语法,仅使用 Alpine.reactiveAlpine.effect

<button>Increment</button>

Count: <span></span>
let button = document.querySelector('button')
let span = document.querySelector('span')

let data = Alpine.reactive({ count: 1 })

Alpine.effect(() => {
    span.textContent = data.count
})

button.addEventListener('click', () => {
    data.count = data.count + 1
})

Count:

如你所见,你可以让任何数据变得响应式,也可以将任何功能包装在 Alpine.effect 中。

这种组合为 Web 开发解锁了一种极其强大的编程范式。尽情发挥吧。