vue封装复选框组件
前言根据百度前端技术学院2018 MVVM 学院中的 2.5 表单实现Input、Checkbox组件用 vue 实现的checkbox复选框组件,使checkbox有三种状态: checked:ture (选中) / false (未选中) , indeterminate (部分选中)1.利用slot插槽2.在同一文件中用到父子通信 $emit $on本文章的 gith...
前言
根据百度前端技术学院2018 MVVM 学院 中的 2.5 表单实现Input、Checkbox组件 用 vue 实现的
checkbox复选框组件,使checkbox有三种状态: checked:ture (选中) / false (未选中) , indeterminate (部分选中)
1.利用slot插槽
2.在同一文件中用到父子通信 $emit $on
本文章的 github地址
实现思路
1.在mounted(附加到页面上)时绑定监听
因为只有在mounted(元素挂载到页面上)之后才能理清节点之间的关系,也才能找到目标节点的$parent,$children
mounted() {
// 得先检测其 $parent 是不是复选框组件(如果是,则其有onDispatch 函数)
if (this.$parent.onDispatch) {
// 如果组件的状态改变,则会执行其父组件的 onDispatch 函数
this.$on("checkStatus", this.$parent.onDispatch);
}
},
2. 当复选框状态改变时,将自己的改变后的复选框状态通知给其父复选框
this.$emit("checkStatus", "indeterminate"/true/false);
3. onDispatch 函数分析
3.1 接收到的值为 子组件状态改变后 发送过来的状态:{"indeterminate"/true/false}
3.2 改变其#(id).checked属性,直接操作其绑定的isChecked即可:checked="isChecked"
isChecked只有true/false
3.3 改变其#(id).indeterminate属性,得获取元素(需要id,所以每个chekbox需要绑定一个id:id="id"),得到其indeterminate,
_getIndeterminate() {
return document.getElementById(this.id).indeterminate;
},
_setIndeterminate(bool) {
document.getElementById(this.id).indeterminate = bool;
},
3.4 当复选框状态为选中/未选中 时,设置其全部子组件为相对应值
(递归,多层改变,能对孩子,孙子,重孙等起作用。)
_setAllSubItem(component, bool) {
component.$children.map(i => {
i.isChecked = bool;
this._setAllSubItem(i, bool);
});
},
4. 最后执行形式
<v-checkbox text="爱好" id="hobby">
<v-checkbox text="种花" id="plant">
<v-checkbox text="养鱼" id="fish"></v-checkbox>
</v-checkbox>
<v-checkbox text="购物" id="shop"></v-checkbox>
<v-checkbox text="吃饭" id="eat"></v-checkbox>
</v-checkbox>
代码实现
<template>
<div>
<label>
<input type="checkbox" @change="handleChange" :checked="isChecked" :id="id">
<span class="checkbox"></span>
<span class="text" s-if="text">{{text}}</span>
</label>
<div class="sub">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
props: ["text", "id"],
mounted() {
if (this.$parent.onDispatch) {
this.$on("checkStatus", this.$parent.onDispatch);
}
},
data() {
return {
id: this.id,
parent: null,
subItems: [],
isChecked: false
};
},
methods: {
// 设置元素 Indeterminate 状态,若为true,表示部分选中
_setIndeterminate(bool) {
document.getElementById(this.id).indeterminate = bool;
},
// 获取元素 Indeterminate 状态
_getIndeterminate() {
return document.getElementById(this.id).indeterminate;
},
// 将元素所有子元素的选中状态统一设置成该元素的选中状态 true/false
_setAllSubItem(component, bool) {
component.$children.map(i => {
i.isChecked = bool;
this._setAllSubItem(i, bool);
});
},
onDispatch(val) {
//不是根元素
// console.log(this.$parent.$parent._uid);
console.log(this);
// 恢复默认状态
this._setIndeterminate(false);
// 如果子组件传过来的值是"indeterminate",即子组件是部分选中状态,那么其父组件一定也是部分选中状态
if (val == "indeterminate") {
this._setIndeterminate(true);
this.$emit("checkStatus", "indeterminate");
return;
}
var subItems = this.$children;
if (subItems.length > 0) {
var check_num = 0;
subItems.map(i => {
// 或者如果子选项中有一个为indeterminate,那么其父组件也一定也是部分选中状态
if (i._getIndeterminate()) {
this._setIndeterminate(true);
this.$emit("checkStatus", "indeterminate");
return;
}
if (i.isChecked) {
check_num++;
}
});
if (check_num == subItems.length) {
//选中子项目个数
this.isChecked = true;
this.$emit("checkStatus", true);
} else if (check_num == 0) {
this.isChecked = false;
this.$emit("checkStatus", false);
} else {
this._setIndeterminate(true);
this.$emit("checkStatus", "indeterminate");
}
}
},
handleChange() {
this.isChecked = !this.isChecked;
this.$emit("checkStatus", this.isChecked);
if (this.isChecked) {
this._setAllSubItem(this, true);
} else {
this._setAllSubItem(this, false);
}
}
}
};
结束
如果文章对你有帮助,麻烦点赞哦!一起走码农花路~
更多推荐
所有评论(0)