How NutUI’s Collapse Panel Boosts Development Efficiency with Vue3
This article explains the design and implementation of NutUI’s Collapse component, covering its basic interaction, animation techniques using height and transform, flexible header customization, slot-based extensions, SCSS variable usage, and Vue3 provide/inject communication, all illustrated with practical code examples.
Collapse Panel Design
Collapse panels are common UI components that can expand or collapse content areas, useful for navigation, detail sections, and filter categories. NutUI provides a mobile‑first component library built with Vue, supporting TypeScript, on‑demand imports, theming, and Vue3 syntax.
Implement Expand/Collapse
The basic interaction toggles a boolean variable to show or hide the content. A simple implementation uses a show ref and a click handler to invert its value.
<template>
<div class="container">
<div class="title" @click="handle">标题</div>
<div class="content" v-show="show">测试内容测试内容测试内容</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const show = ref(false)
const handle = () => { show.value = !show.value }
</script>For smoother animations the component controls the height style directly, calculating the content’s offsetHeight and applying a transition with transform and the CSS will-change property.
will-change informs the browser about upcoming changes, allowing it to optimise rendering for faster, smoother animations.
const wrapperRefEle = wrapperRef.value;
const contentRefEle = contentRef.value;
if (!wrapperRefEle || !contentRefEle) return;
const offsetHeight = contentRefEle.offsetHeight || 'auto';
if (offsetHeight) {
const contentHeight = `${offsetHeight}px`;
wrapperRefEle.style.willChange = 'height';
wrapperRefEle.style.height = proxyData.openExpanded ? contentHeight : 0;
}Flexible Header
The header can display an icon that rotates 180° when the panel expands. The rotation is controlled by a CSS rotate transform based on the component’s expanded state.
if (parent.props.icon && !proxyData.openExpanded) {
proxyData.iconStyle['transform'] = 'rotate(0deg)';
} else {
proxyData.iconStyle['transform'] = `rotate(${parent.props.rotate}deg)`;
}APIs are exposed for custom icons, rotation angles, and subtitle configuration, enabling diverse use‑cases such as news feeds or notification badges.
Configuration Upgrade
Additional props like sub-title and slot:extraRender allow developers to inject extra content or custom titles via slots, enhancing extensibility.
<view v-if="$slots.extraRender" class="collapse-extraWrapper">
<div class="collapse-extraRender">
<slot name="extraRender"></slot>
</div>
</view>A disabled prop disables interaction, applying a style that changes cursor and colour.
.nut-collapse-item-disabled {
color: #c8c9cc;
cursor: not-allowed;
pointer-events: none;
}SCSS Variable Usage
Vue3 allows CSS variables to be bound to component data, enabling dynamic styling directly in the style block.
<template>
<span>NutUI</span>
</template>
<script>
export default {
data() { return { color: 'red' } }
}
</script>
<style vars="{ color }" scoped>
span { color: var(--color); }
</style>Component Communication (Provide/Inject)
Parent and child components share data via Vue’s provide and inject APIs. The provide function adds key/value pairs to the component’s provides object, while inject looks up the value through the prototype chain, optionally returning a default.
// a.vue – provide
import { defineComponent, provide } from 'vue'
export default defineComponent({
setup() {
const msg = 'Hello NutUI'
provide('msg', msg)
}
})
// b.vue – inject
import { defineComponent, inject } from 'vue'
export default defineComponent({
setup() {
const msg = inject('msg') || ''
}
})When using provide in Vue3, the data must be reactive if the consumer expects reactivity. The implementation relies on prototype inheritance to propagate provided values down the component tree.
Summary
The article introduced NutUI’s Collapse component, detailing its design philosophy, animation implementation, flexible header, slot‑based extensions, SCSS variable styling, and Vue3 provide/inject communication, providing practical code snippets to help developers integrate and extend the component efficiently.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
JD.com Experience Design Center
Professional, creative, passionate about design. The JD.com User Experience Design Department is committed to creating better e-commerce shopping experiences.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
