banner
isolcat

isolcat

I am not afraid of storms, for I am learning how to sail my ship
github

Encapsulate element plus components and beautify with UnoCSS.

Preface#

In daily development, in order to avoid reinventing the wheel and wasting development time, we often use third-party component libraries such as element plus and vant-ui. However, in some cases, in order to improve the overall aesthetics of the project, we will not directly use third-party component libraries, but modify them to make them more in line with the overall UI style of the project. At this time, we can extract the third-party component library and package it into a common component library. This operation of encapsulating third-party component libraries is called secondary encapsulation.

Benefits of Secondary Encapsulation#

  • More concise code
  • Easier maintenance in the later stages of the project
  • Stronger component reusability

Introduction to Unocss#

Since we are going to encapsulate the original third-party component library, it is inevitable to modify its styles. Modifying CSS is often the most headache-inducing part (at least for me 🥴). At this time, I saw antfu's Reimagining Atomic CSS, and I strongly recommend reading this article before continuing, which will give you a deeper understanding of Atomic CSS. Here is a summary in the words of the master:

Atomic CSS is an architectural approach to CSS that tends to use small, single-purpose classes and names them based on visual effects.

Unocss is the high-performance and highly flexible instant atomic CSS engine created by antfu. As for why it is an engine rather than a CSS framework, it is because Unocss does not provide any core utility classes, and all functionality can be provided through presets and inline configurations.

Advantages of Unocss#

  • Flexibility (property mode, thousands of pure CSS icons, no need to worry about style conflicts)
  • Strong style reusability
  • No need to think about class names! (This is a great help for people who have difficulty naming things) 🤣

Since both secondary encapsulation and Unocss can greatly improve development efficiency and make everyone happy, let's try combining these two things together. Here, we will take the loading component of element plus for a simple secondary encapsulation, and then use Unocss to beautify it.

Core of Secondary Encapsulation#

Here, we use the component encapsulation method of vue3, which is slightly different from the encapsulation method of vue2. For the encapsulation method of vue2, please refer to Red Dust's article.

$attrs#

An object containing all the passed-through attributes of the component.

This is the official definition of $attrs in Vue, which refers to attributes and event handling functions that are passed in by the parent component and are not declared as props or custom events of the child component. For example, when we nest a <button> inside a <div> tag in a component, if we want to apply pass-through attributes such as class or v-on listeners directly to the inner <button>, we can use v-bind="$attrs" to achieve this.

Inheriting v-on Listeners#

In vue3, the $listeners event listener in vue2 has been directly removed, and its functionality has been merged into $attrs. For example, when writing a click event, in component encapsulation, the click of the atomic component will still trigger the onclick event of the parent component.

<!-- Child component -->
<button>click me</button>
<!-- Parent component -->
<MyButton @click="onClick" />

Component Encapsulation#

Project Initialization#

Enter the following command in the command line:

pnpm create vite element-plus-unocss --template vue

Use vite+pnpm to quickly initialize the project.

cd element-plus-unocss
pnpm i
pnpm run dev

After successful execution, the project initialization is complete.

Importing Component Library#

The component library we want to encapsulate is element plus, so let's import it:

pnpm install element-plus

Here, we still follow the recommended automatic import by the official website. I won't go into details here. Just click on the official website link for configuration. The following is the focus.

Secondary Encapsulation#

Here, we choose the loading component of element plus for demonstration. Add the child component loading.vue to the components folder, and directly copy the example from the official link (you can make some deletions if necessary):

<template>
  <el-button
    v-loading.fullscreen.lock="fullscreenLoading"
    type="primary"
    @click="openFullScreen1"
  >
    Click me
  </el-button>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { ElLoading } from 'element-plus'

const fullscreenLoading = ref(false)
const openFullScreen1 = () => {
  fullscreenLoading.value = true
  setTimeout(() => {
    fullscreenLoading.value = false
  }, 2000)
}
</script>

Now create the Myloading.vue component, import it, and modify its code:

<template>
  <Loading
    v-bind="$attrs"
    element-loading-text="Loading~"
    element-loading-background="rgba(122, 122, 122, 0.8)"
  />
</template>

<script setup>
import Loading from "./loading.vue";
</script>
<style>
.el-loading-mask .el-loading-spinner .el-loading-text {
  font-size: 20px;
}
</style>

The result is as follows:

image.png

This means that the secondary encapsulation of our component is successful.

Beautifying Components with UnoCSS#

At this time, we found that the click me button seems lifeless and does not make people want to click it. So, what can we do to make this button more eye-catching and make people want to click it? This is where our heavyweight character UnoCSS comes in.

Installing and Importing UnoCss#

pnpm i -D unocss

Configure vite.config.js:

import Unocss from 'unocss/vite'

export default {
  plugins: [
    Unocss({ /* options */ }),
  ],
}

And import UnoCSS into main.js: import 'uno.css'

Configuring Presets#

Configuring presets is an important advantage of UnoCSS. With just a few simple presets, you can build your own custom framework in minutes. Attributify is one of the characteristics of Windi CSS, which is also retained in UnoCSS. Here, we install preset-attributify and unocss/preset-uno:

pnpm i -D @unocss/preset-attributify
pnpm i -D @unocss/preset-uno

Modified vite.config.js:

import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import Unocss from '@unocss/vite'
import presetUno from '@unocss/preset-uno'
import presetAttributify from '@unocss/preset-attributify'

import vue from '@vitejs/plugin-vue'
export default defineConfig({
    plugins: [vue(), AutoImport({
            resolvers: [ElementPlusResolver()],
        }),
        Components({
            resolvers: [ElementPlusResolver()],
        }),
        Unocss({
            presets: [presetUno(), presetAttributify()]
        })
    ]
})

Now we have a default preset + attribute mode custom framework. After writing a long string of CSS classes, they will be grouped according to the attribute mode, making the code more tidy and greatly improving readability:

<button 
  bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
  text="sm white"
  font="mono light"
  p="y-2 x-4"
  border="2 rounded blue-200"
>
  Button
</button>

Modifying Component Styles#

In order to make the button look more desirable to click, we can try adding a jumping animation to click me. At this time, we open the UnoCSS playground and find that the official demo already has a bouncing style. Let's copy it and modify our child component:

<div  class="
      text-5xl
      fw300
      animate-bounce-alt
      animate-count-infinite
      animate-duration-1s"
    >
      click me
</div>

Now we feel that the default button text color seems a bit too dark. At this time, we can modify it in the parent component:

<Loading
    element-loading-text="Loading~"
    v-bind="$attrs"
    element-loading-background="rgba(122, 122, 122, 0.8)"
    class="text-lg 
           fw300 
           m2 
           op70"
  />

If we want to know what the cv actually means, we can download a UnoCSS plugin, search for it directly in vscode, and after installing it, it will display the source code of this class, which is convenient for subsequent development.

Okay, let's take a look at the appearance of the button after beautification:

GIF 2022-10-22 23-10-45.gif

Constantly jumping, doesn't it make people want to click it more? 😂

Conclusion#

As a newcomer to atomic CSS, UnoCSS is refreshing. It draws on the advantages of its predecessor taiwind CSS and incorporates its own characteristics of windiCSS, making it surprisingly easy to use. Although it is still in the testing phase, I highly recommend everyone to give it a try. It will definitely give you a feeling of "What? You can do this?". You can even use UnoCSS to build your own component library. Here is a link to my own component library project, which is an attempt with UnoCSS: https://github.com/isolcat/CatIsol-UI

Component library preview address: https://cat-isol-ui.vercel.app 😽

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.