vue实现折叠组件-collapse
相信大家对于下面的列表形式应该不陌生吧,至少我个人在后台OA系统的时候就用到了,那么我来聊下这样形式的列表,应该怎么封装成为一个公共的组件。(代码参考了iview用于个人学习之用)一.列表组件参数设置每一个公共组件都应该约定好参数,定义好回调函数所传递参数。不应该与业务组件和业务逻辑相互耦合。这个组件的约定参数和使用方法如下:<Collapse v-model="value1" @...
相信大家对于下面的列表形式应该不陌生吧,至少我个人在后台OA系统的时候就用到了,那么我来聊下这样形式的列表,应该怎么封装成为一个公共的组件。(代码参考了iview用于个人学习之用)
一.列表组件参数设置
每一个公共组件都应该约定好参数,定义好回调函数所传递参数。不应该与业务组件和业务逻辑相互耦合。
这个组件的约定参数和使用方法如下:
<Collapse v-model="value1" @on-change="changFun">
<Panel name="1">
<span>标题1</span>
<p slot="content">标题1的内容</p>
</Panel>
<Panel name="2">
<span>标题2</span>
<p slot="content">标题2的内容</p>
</Panel>
<Panel name="3">
<span>标题3</span>
<p slot="content">标题3的内容</p>
</Panel>
<Panel name="4">
<span>标题4</span>
<p slot="content">标题4的内容</p>
</Panel>
</Collapse>
Collapse参数
属性 | 说明 |
---|---|
value | 激活面板的name |
accordion | 是否开启手风琴模式 |
Collaspe事件
事件名 | 说明 |
---|---|
on-change | 返回面板的key,格式为数组 |
Panel参数
属性 | 说明 |
---|---|
name | 对应面板的name |
二.建立文件夹存放Collapse和Panel组件
在src/components下分别建立collaspse.vue,panel.vue和index.js
index.js
import Panel from './panel.vue'
import Collapse from './collapse'
Collapse.Panel = Panel
export default Collapse
在main.js中
这里在main.js中导入,全局注册组件,那么我们就不需要在某个vue文件中单独引入。
Collapse.vue
<template>
<div :class="classes">
<slot></slot>
</div>
</template>
<script>
const prefixCls = "ka-collapse";
export default {
name: "collapse",
props: {
// 是否是手风琴模式
accordion: {
type: Boolean,
default: false
},
// 传递进来的值
value: [Array, String]
},
computed: {
classes() {
// `${prefixCls-simple}` 是变量需要添加[]
return [`${prefixCls}`];
}
},
data() {
return {
currentValue: this.value // 传递进来当前的值
};
},
mounted() {
this.setActive();
},
methods: {
setActive() {
// 为它下面的子元素都设置一个index值
// console.log("setActive");
const activeKey = this.getActiveKey();
this.$children.forEach((child, index) => {
const name = child.name || index.toString(); // toString 1=>"1"整数转换成为字符串
child.isActive = activeKey.indexOf(name) > -1; // 给选中的元素赋值活跃状态
// console.log(child);
child.index = index;
});
},
toggle(data) {
// console.log("toggle");
const name = data.name.toString(); // 强行转换成为字符串
let newActivekey = [];
if (this.accordion) {
// 如果是手风琴模式
if (!data.isActive) {
newActivekey.push(name);
}
} else {
let activeKey = this.getActiveKey();
const nameIndex = activeKey.indexOf(name);
if (data.isActive) {
// 如果当前是展开状态
if (nameIndex > -1) {
activeKey.splice(nameIndex, 1);
}
} else {
if (nameIndex < 0) {
activeKey.push(name);
}
}
newActivekey = activeKey;
}
this.currentValue = newActivekey;
// console.log(data);
this.$emit("input", newActivekey);
this.$emit("on-change", newActivekey);
},
getActiveKey() {
// 获取当前展开的元素,并且做成数组的形式 1 => ["1"]
let activeKey = this.currentValue || [];
const accordion = this.accordion;
if (!Array.isArray(activeKey)) {
// 判断 activeKey 是不是数组
activeKey = [activeKey]; // 不是数组则让它变成数组
}
if (accordion && activeKey.length > 1) {
// 如果是手风琴模式,必定是只会有一个元素
activeKey = [activeKey[0]];
}
for (let i = 0; i < activeKey.length; i++) {
activeKey[i] = activeKey[i].toString();
}
return activeKey;
}
},
watch: {
value(val) {
console.log(val);
this.currentValue = val;
},
currentValue() {
console.log("currentValue");
this.setActive();
}
}
};
</script>
<style lang="scss" scoped>
// border-top: 1px solid #dcdee2;
</style>
panel.vue
<template>
<div :class="itemClasses">
<div :class="headerClasses" @click="toggle">
<Icon type="icon-right" v-if="!hideArrow"></Icon>
<slot></slot>
</div>
<div :class="contentClass" v-show="isActive">
<div :class="boxClasses">
<slot name="content"></slot>
</div>
</div>
</div>
</template>
<script>
const prefixCls = "ka-collapse";
export default {
name: "Panel",
data() {
return {
index: 0,
isActive: false
};
},
props: {
name: {
type: String
},
hideArrow: {
type: Boolean,
default: false
}
},
computed: {
itemClasses() {
return [
`${prefixCls}-item`,
{
[`${prefixCls}-item-active`]: this.isActive
}
];
},
// 定义header样式
headerClasses() {
return `${prefixCls}-header`;
},
contentClass() {
return `${prefixCls}-content`;
},
boxClasses() {
return `${prefixCls}-content-box`;
}
},
methods: {
toggle() {
// console.log(this);
this.$parent.toggle({
name: this.name || this.index,
isActive: this.isActive
});
}
}
};
</script>
<style lang="scss" scoped>
.ka-collapse-header {
color: red;
}
</style>
这个组件大概的思路为,在panel子组件直接触发父组件的tooggle,这样做的好处就是可以把当前点击panel对象的状态传递到父组件,有父组件去完成切换的逻辑。
最后给上github地址:
https://github.com/whenTheMorningDark/workinteresting/tree/master/src/components/collapse
更多推荐
所有评论(0)