element-plus 组件解析 - Collapse 折叠面板

  • 1, 组件介绍
  • 2,组件组成
  • 3,组件实现
  • 3.1,el-collapse
    • 1,v-model="activeNames"
    • 2,手风琴效果
    • 3,el-collapse 关键逻辑
  • 3.2,el-collapse-item
    • 1,el-collapse-item 关键逻辑
  • 3.3,el-collapse-transition
    • 1,el-collapse-transition 关键逻辑

代码做了简化,只保留核心部分,并且去掉了 typescript。
欢迎大家评论交流。

1, 组件介绍

Collapse 折叠面板

作用:通过折叠面板收纳内容区域

  • 同时打开多个,互不影响
  • 只能打开一个,也就是手风琴效果。

2,组件组成

由 3 个组件组成

  • el-collapse,作为整体容器。
  • el-collapse-item,包括面板标题和面板内容
  • el-collapse-transition,实现面板内容的过度动画

相关 AttributesEventsSlots,举例如下:

<el-collapse accordion v-model="activeNames" @change="handleChange"><el-collapse-item name="1"><template #title>Consistency<el-icon class="header-icon"><info-filled /></el-icon></template><div>Consistent with real life: in line with the process and logic of real life, and comply with languages and habits that the users are used to;</div><div>Consistent within interface: all elements should be consistent, such as: design style, icons and texts, position of elements, etc.</div></el-collapse-item><el-collapse-item title="Feedback" name="2" disabled><div>Operation feedback: enable the users to clearly perceive their operations by style updates and interactive effects;</div></el-collapse-item>
</el-collapse>

3,组件实现

3.1,el-collapse

1,v-model=“activeNames”

对组件使用v-model

<el-collapse v-model="activeNames"></el-collapse>

相当于

<el-collapse :modelValue="activeNames" @update:modelValue="newValue => activeNames = newValue"></el-collapse>

所以 el-collapse 在组件中定义了:

  • props: modelValue
  • emits: update:modelValue

2,手风琴效果

每次只能展开1个面板

element-plus 为了使用方便,当为手风琴效果时,activeNames 类型可以设置为 string。

// 使用
const activeName = ref('1')

非手风琴效果时,传入数组

// 使用
const activeNames = ref(['1'])

所以,最终 modelValue 的类型如下:

const props = defineProps({modelValue: {type: [Array, String, Number],default: () => []}
})

3,el-collapse 关键逻辑

  1. 处理 activeNames,统一为数组格式。
  2. 定义点击面板的事件 handleItemClick,统一处理面板的折叠状态。

html 部分

<template><div class="el-collapse"><slot /></div>
</template>

js 部分

// 暴露给用户的参数,可以让用户手动设置 activeNames
const { activeNames, setActiveNames } = useCollapse(props, emit)
defineExpose({/** @description active names */activeNames,/** @description set active names */setActiveNames
})

主要逻辑

/*** @param props {accordion: boolean, modelValue: string | []}* @param emit {"update:modelValue", "change"}*/
const useCollapse = (props, emit) => {// activeNames 数组表示已打开的面板// ensureArray 将传入的值转为数组const activeNames = ref(ensureArray(props.modelValue))const setActiveNames = (_activeNames) => {activeNames.value = _activeNames// 手风琴 ? 则只打开一个 : 所有都可以打开const value = props.accordion ? activeNames.value[0] : activeNames.valueemit('update:modelValue', value)emit('change', value)}// 点击面板const handleItemClick = (name) => {if (props.accordion) {// 手风琴点击相同会关闭setActiveNames([activeNames.value[0] === name ? '' : name])} else {const _activeNames = [...activeNames.value]const index = _activeNames.indexOf(name)// 点击已存在的,则从 activeNames 删除(关闭),反之打开if (index > -1) {_activeNames.splice(index, 1)} else {_activeNames.push(name)}setActiveNames(_activeNames)}}// 先统一处理为数组watch(() => props.modelValue,() => (activeNames.value = ensureArray(props.modelValue)),{ deep: true })// 传递给 el-collapse-item 使用,collapseContextKey 作为唯一标识 = Symbol('collapseContextKey')provide(collapseContextKey, {activeNames,handleItemClick})return {activeNames,setActiveNames}
}

Tips:ensureArray 实现, lodash.castArray

3.2,el-collapse-item

1,el-collapse-item 关键逻辑

  1. 在点击面板时,将对应 name 传递给父级 el-collapsehandleItemClick 处理
  2. 计算展示相关样式(样式这里不做讨论,因为都是一些简单的布局样式)

html 部分

<template><div :class="rootKls"><!-- 面板 title 部分 --><div><div:class="headKls":tabindex="disabled ? -1 : 0"@click="handleHeaderClick"@keypress.space.enter.stop.prevent="handleEnterClick"@focus="handleFocus"@blur="focusing = false"><slot name="title">{{ title }}</slot><el-icon :class="arrowKls"><arrow-right /></el-icon></div></div><!-- 内容部分 --><el-collapse-transition><div v-show="isActive" class="el-collapse-item__wrap"><div class="el-collapse-item__content"><slot /></div></div></el-collapse-transition></div>
</template>

js 部分

name 唯一标识符,对应activeName,用于判断打开和折叠面板

// { title: string, name: [String, Number], disabled: boolean }
const props = defineProps(['title', 'name', 'disabled'])const { focusing, isActive, handleFocus, handleHeaderClick, handleEnterClick } = useCollapseItem(props)const { arrowKls, headKls, rootKls } = useCollapseItemDOM(props, { focusing, isActive })// 暴露出给用户用的参数
defineExpose({/** @description current collapse-item whether active */isActive
})

主要逻辑

const useCollapseItem = (props) => {// { activeNames, handleItemClick }const collapse = inject(collapseContextKey)// tabindex 可以控制 Tab 键切换 el-collapse-item 面板,元素会处于 focus 状态,// focusing,isClick,handleFocus 这3个都是为了控制 focus 状态的 cssconst focusing = ref(false)const isClick = ref(false)// 是否被选中,影响 cssconst isActive = computed(() => collapse?.activeNames.value.includes(props.name))const handleFocus = () => {setTimeout(() => {if (!isClick.value) {focusing.value = true} else {isClick.value = false}}, 50)}// 调用 el-collapse 传递的方法const handleHeaderClick = () => {if (props.disabled) returncollapse?.handleItemClick(props.name)focusing.value = falseisClick.value = true}const handleEnterClick = () => {collapse?.handleItemClick(props.name)}return {focusing,isActive,handleFocus,handleHeaderClick,handleEnterClick}
}
// 动态设置 class
const useCollapseItemDOM = (props, { focusing, isActive }) => {const rootKls = computed(() => ['el-collapse-item', unref(isActive) && 'is-active', props.disabled && 'is-disabled'])const headKls = computed(() => ['el-collapse-item__header', unref(isActive) && 'is-active', { focusing: unref(focusing) && !props.disabled }])const arrowKls = computed(() => ['el-collapse-item__arrow', unref(isActive) && 'is-active'])return {rootKls,headKls,arrowKls}
}

3.3,el-collapse-transition

1,el-collapse-transition 关键逻辑

  1. 实现面板内容部分 el-collapse-item__wrap 的折叠动画。

html 部分

<template><transition name="el-collapse-transition" v-on="on"><slot /></transition>
</template>

js 部分

先说几点前提:

  1. v-on 支持对象语法
<!-- 对象语法 -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
  1. Transition 支持 JavaScript 钩子函数

对应关系

css 过渡 class JavaScript 钩子函数
v-enter-from beforeEnter
v-enter-active enter
v-enter-to afterEnter
v-leave-from beforeLeave
v-leave-active leave
v-leave-to afterLeave
  1. 在高度变化的折叠动画中:

    • paddingToppaddingBottom 需要做处理,因为当元素 height = 0 时,padding 还会占据高度。
    • overflow: hidden 为了形成BFC,让浮动元素也参与高度计算。浮动元素会让父级高度塌陷
// el 是被 transition 组件包裹的元素
const on = {beforeEnter(el) {if (!el.dataset) el.dataset = {}el.dataset.oldPaddingTop = el.style.paddingTopel.dataset.oldPaddingBottom = el.style.paddingBottomel.style.maxHeight = 0el.style.paddingTop = 0el.style.paddingBottom = 0},enter(el) {el.dataset.oldOverflow = el.style.overflowel.style.overflow = 'hidden'el.style.maxHeight = `${el.scrollHeight}px`el.style.paddingTop = el.dataset.oldPaddingTopel.style.paddingBottom = el.dataset.oldPaddingBottom},afterEnter(el) {el.style.maxHeight = '' // 需要还原。el.style.overflow = el.dataset.oldOverflow},beforeLeave(el) {if (!el.dataset) el.dataset = {}el.dataset.oldPaddingTop = el.style.paddingTopel.dataset.oldPaddingBottom = el.style.paddingBottomel.dataset.oldOverflow = el.style.overflowel.style.overflow = 'hidden'el.style.maxHeight = `${el.scrollHeight}px`},leave(el) {if (el.scrollHeight !== 0) {el.style.maxHeight = 0el.style.paddingTop = 0el.style.paddingBottom = 0}},afterLeave(el) {el.style.maxHeight = ''el.style.overflow = el.dataset.oldOverflowel.style.paddingTop = el.dataset.oldPaddingTopel.style.paddingBottom = el.dataset.oldPaddingBottom},
}

css 部分

.el-collapse-transition-leave-active,
.el-collapse-transition-enter-active {transition: 0.3s max-height ease-in-out,0.3s padding-top ease-in-out,0.3s padding-bottom ease-in-out;
}

以上是 Collapse 折叠面板的全部逻辑。

element-plus 组件解析 - Collapse 折叠面板相关推荐

  1. 用timeline 时间线 和 Collapse 折叠面板做一个简单的时间轴

    项目上有个时间轴功能,我看了一下element上有时间轴功能,不过有点太简单,我想改造一下这个时间轴,记录一下,用Timeline 时间线 和 Collapse 折叠面板,两个加起来做了一时间轴,当是 ...

  2. collapse 微信小程序_微信小程序之有赞组件Collapse折叠面板的使用

    1. 使用指南 在 app.json 或 index.json 中引入组件 es6 "usingComponents": { "van-collapse": & ...

  3. ElementPlus的Collapse 折叠面板问题

    我也不明白为什么会报这个错误,把关于ts的代码改成js的就可以了.. ERROR in ./src/views/Home.vue?vue&type=script&lang=ts& ...

  4. el-menu,Collapse 折叠面板,收起后子菜单弹窗popover跟菜单的距离

    如图上面的距离,ui强调受气候菜单的宽度为48px,导致距离过大 解决办法 查看空值太,发现这个树形影响了位置 这个是在全局样式下的,直接修改会导致全局样式改变,这样行不通,需要添加一个class,查 ...

  5. 修复uview的collapse折叠面板箭头不能变向的官方bug(小程序里)

    打开u-collapse-item.vue文件,按图中修改代码. 代码修改说明:其实就是把 .u-arrow-down-icon和.u-arrow-down-icon-active这两个类名绑定到了的 ...

  6. Vue3折叠面板(Collapse)

    可自定义设置以下属性: 折叠面板数据,可使用 slot 替换对应索引的 header 和 text(collapseData),必传,类型:Array<{key?: string, header ...

  7. 解决折叠面板Collapse上点击复选框会触发折叠面板问题

    在项目中有一个小需求,需要在折叠面板头部加一个复选框按钮,点击复选框,修改数据状态,这里的问题是,点击复选框,会触发折叠面板,效果如下. 这里我查阅了一下资料,这是因为事件传递导致的,点击复选框,复选 ...

  8. 045_Collapse折叠面板

    1. Collapse折叠面板 1.1. Collapse折叠面板通过折叠面板收纳内容区域. 1.2. Collapse Attributes 参数 说明 类型 可选值 默认值 value / v-m ...

  9. html5中折叠面板,Ant Design中折叠面板Collapse

    这段时间做react项目遇到一些平常并不会去在意的问题,但解决的时候又需要思考一番.这次开发用到了蚂蚁金服的UI框架Ant Design.项目中有一个模块的样式和功能用到了折叠面板Collapse组件 ...

最新文章

  1. 重读【代码整洁之道】
  2. MFC_Combo_Box(组合框)的详细用法
  3. arm下如何烧写指定分区大小的内核和文件系统
  4. 在斜坡上哪个物体滚的最快_人教版一年级上册 第十七课 会滚的玩具
  5. Pytorch实现基本循环神经网络RNN (3)
  6. 机器学习-算法背后的理论与优化(part4)--结构风险最小(上)
  7. SAP C4C里没有选择Port binding的url Mashup行为分析
  8. AgileConfig - RESTful API 介绍
  9. php 自定义行间距,phpstorm 常见设置
  10. 厉害了,我的清华大学,各系横幅让网友看花眼,尤其是第3条
  11. html语言hr的用法,htmlhr各种样式使用 - 米扑博客
  12. 移动视频监控(2)---原型开发---(音视频编解码多平台移植(for window/wince))ffmpeg --自由之路即是曲折之路。...
  13. java 关于集合的笔试题_Java集合面试题(一)
  14. c语言除法在全局区,深入C语言内存区域分配(进程的各个段)详解
  15. 阶段1 语言基础+高级_1-3-Java语言高级_07-网络编程_第4节 模拟BS服务器案例_2_模拟BS服务器代码实现...
  16. Directshow 采集-截屏和显示
  17. 联想y7000 Linux显卡驱动,联想Y7000安装显卡驱动
  18. Python识别图形验证码
  19. linux vps 桌面,linode linux vps的centos系统上安装X Window System GNOME图形桌面使用vnc连接 - 乖兔博客...
  20. 提取视频中的前景物体

热门文章

  1. 新加坡:迈向智慧国家
  2. sched_clock
  3. unity edit模式下停止运行
  4. 双色球手机版 旋转矩阵手机版
  5. 3-MongoDB常用的命令-数据库创建-文档插入
  6. Nokia E52的Runtime java.lang.Runtime Exception Toolkit Closed问题解决
  7. python keras安装配置_Keras官方中文文档:Keras安装和配置指南(Linux)
  8. 百度无人驾驶汽车上路 安全系数究竟有多高
  9. NLP----Baidu-中文词法分析(LAC)
  10. 整理了两个版本的道德经 简体繁体,均使用竖排 PDF格式