How to Write Alpine.js Components

How to Write Alpine.js Components

When using Alpine.js, you may have encountered the challenge of how to structure components. Unlike Vue or React which are component-first, Alpine’s documentation keeps componentization relatively subtle.

Here, we provide two approaches for writing components in Alpine.js. You can consider both methods and choose according to your preference.

Morph

The official Alpine.js site offers a tool called Morph that can be used to achieve component functionality.

Firstly, add this plugin above where you normally include Alpine, as follows:

<script src="libs/alpine.morph.min.js" defer></script>
<script src="libs/alpine.min.js" defer></script>
<script defer src="components/sc-loading.js"></script>

The CDN link is CDN. Download it to your server to ensure proper use by domestic users.

The sc-loading.js file contains the component code.

Write it like this:

Alpine.morph(
  document.querySelector('sc-loading'),
  `
  <div class="fixed top-0 left-0 w-full h-full bg-gray-900 bg-opacity-50 z-50 flex items-center justify-center" x-show="isLoading" x-transition>
    <span class="loading loading-ring loading-lg"></span>
  </div>
`
)

This is a loading component using TailwindCSS.

You can see that it can directly use Alpine variables within the same scope, such as isLoading, which is defined in the corresponding HTML structure.

HTML structure:

<div x-data="indexData">
    ...
    <sc-loading></sc-loading>
</div>

indexData:

Alpine.data('indexData', () => ({
  isLoading: false,
}))

Business Logic Handling

Handling business logic is straightforward; you can proceed as usual without extra attention.

this.isLoading = true;
this.isLoading = false;

Custom Directives

Example usage:

Alpine.directive('loadmore', (el, { expression }, { evaluateLater }) => {
  const _fn = evaluateLater(expression);
  let isLoading = false;
  let lastScrollTime = 0;
  const THROTTLE_DELAY = 200;

  el.addEventListener('scroll', () => {
    const now = Date.now();
    if (now - lastScrollTime < THROTTLE_DELAY || isLoading) return;

    const scrollBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
    if (scrollBottom <= 50) {
      isLoading = true;
      lastScrollTime = now;

      _fn().finally(() => {
        isLoading = false;
      });
    }
  });
});
<div x-loadmore="onLoadMore"></div>

This can be quite complex, but the advantage is high customizability. For detailed explanations, refer to the official documentation. Here are some key points:

  • el: The mounted element.
  • expression: The expression following the directive, which can be a variable or function. Use evaluateLater to handle it accordingly.
  • evaluateLater: A utility that converts expressions into functions. There are two types of returned functions: one returns the passed expression function, while the other returns a function that generates an expression variable. The former can be used as an expression directly. The latter needs to be used with effect to implement listening effects. Check the documentation for more details.

Conclusion

These two solutions cover most scenarios you might encounter when working with Alpine.js. Other hacky methods are not discussed here. Thank you for reading, and I hope this helps you.

Comments

Popular posts from this blog

How to turn off Sass warning prompts in Nuxt.js projects

Guide to Modifying Docker Container Port Mappings

Optimizing Class Name Management with CSS Attribute Selector