这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
TIP 👉 业精于勤荒于嬉,行成于思毁于随。唐·韩愈《进学解》
前言
Web Component是前端界一直非常热衷的一个领域,用第三方组件化的框架去实现的话,你需要依赖框架本身很多东西,很多时候我们只是简单的几个组件,不是很大,也不是很多,所以为了保证组件的轻量,简单
,其实这个时候我们并不想采用第三方的框架。
先来看一下实现的效果
CheckBox 多选框
import
import CheckBox from '@/components/CheckBox/CheckBox';
Props
1. checked
-
类型:bool
-
默认值:false
-
说明:是否选中, true表示选中
2. disabled
-
类型:bool
-
默认值:false
-
说明:是否不可用,true表示复选框不可用,复选框为灰色
3. indeterminate
-
类型:bool
-
默认值:false
-
说明:是否开启不确定状态 (即未全选,checked为false时有效;true表示不确定状态,checked为false时复选框中间显示蓝色小方块)
4. onChange
-
类型:func (必填)
-
默认值:无
-
说明:选中状态改变时的回调函数,入参:
-
{boolean} newChecked 新的选中状态
5. className
-
类型:string | array | object(key: 样式名,value: bool)
-
默认值:无
-
说明:最外层元素样式
<CheckBox className = {'my-class'}></CheckBox>
<CheckBox className = {['my-class1', 'my-class2']}></CheckBox>
<CheckBox className = {{'my-class1': true}}></CheckBox>
CheckBoxGroup 多选框组
import
import CheckBoxGroup from '@/components/CheckBox/CheckBoxGroup';
Props
1. options
-
类型:array (必填)
-
默认值:无
-
说明:可选项数组
<CheckBoxGroup options = {[{label: "选项一", value: 1}, {label: "选项2", value: 2, disabled: true}]}></CheckBoxGroup>
2. value
-
类型:array
-
默认值:[]
-
说明:选中选项value组成的数组
3. disabled
-
类型:bool
-
默认值:false
-
说明:是否不可用,true表示复选框组不可用,该组复选框全部为灰色
4. onChange
-
类型:func (必填)
-
默认值:无
-
说明:组内复选框选中状态改变时的回调函数,入参:
-
{Array} newGroupValue 新的选中选项value组成的数组
5. className
-
类型:string | array | object(key: 样式名,value: bool)
-
默认值:无
-
说明:最外层元素样式
<CheckBoxGroup className = {'my-class'}></CheckBoxGroup>
<CheckBoxGroup className = {['my-class1', 'my-class2']}></CheckBoxGroup>
<CheckBoxGroup className = {{'my-class1': true}}></CheckBoxGroup>
实现CheckBox.js
import React from 'react';
import PropTypes from 'prop-types';
// 为保证测试用例运行,不使用webpack内置utils模块,单独引入
import utils from '../../js/common/utils/index.js';
import './CheckBox.scss';
/**
* CheckBox 复选框
*/
class CheckBox extends React.Component {
// 入参类型检查
static propTypes = {
// 是否选中 (true表示选中)
checked: PropTypes.bool,
// 是否不可用 (true表示复选框不可用,复选框为灰色)
disabled: PropTypes.bool,
// 是否开启不确定状态 (即未全选,checked为false时有效;true表示不确定状态,checked为false时复选框中间显示蓝色小方块)
indeterminate: PropTypes.bool,
/**
* 选中状态改变时的回调函数
* @param {boolean} newChecked 新的选中状态
*/
onChange: PropTypes.func.isRequired,
// 最外层元素样式
className: PropTypes.oneOfType([
PropTypes.string,
PropTypes.array,
PropTypes.objectOf(PropTypes.bool)
])
}
// 入参默认值
static defaultProps = {
checked: false,
disabled: false,
indeterminate: false
}
constructor(props) {
super(props);
this.state = {
// 鼠标是否浮动在组件上方
hover: false
};
}
/**
* 选择框最外层需要的class
* @returns {string}
*/
getCheckboxWrapperClassName(){
return utils.clasx(this.props.className, {
'checkbox-wrapper': true,
'checkbox-checked': this.props.checked,
'checkbox-disabled': this.props.disabled,
'checkbox-indeterminate': this.props.indeterminate && !this.props.checked
});
}
/**
* 点击事件
* @param e
* @returns {boolean}
*/
checkedToggle(e) {
if (!this.props.disabled && this.props.onChange) {
this.props.onChange(!this.props.checked);
}
}
render() {
return (
<div className={this.getCheckboxWrapperClassName()}
onClick={(e) => this.checkedToggle(e)}>
<span className="checkbox"></span>
<span className="checkbox-text">{this.props.children}</span>
</div>
);
}
}
export default CheckBox;
下面我们来实现多选CheckBoxGroup.js
import React from 'react';
import PropTypes from 'prop-types';
import CheckBox from './CheckBox.js';
// 为保证测试用例运行,不使用webpack内置utils模块,单独引入
import utils from '../../js/common/utils/index.js';
import './CheckBox.scss';
/**
* CheckBoxGroup 复选框组
*/
class CheckBoxGroup extends React.Component {
// 入参类型检查
static propTypes = {
// 可选项数组,例:[{label: "选项一", value: 1}, {label: "选项2", value: 2, disabled: true}]
options: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (typeof propValue[key] !=='object') {
return new Error(`Invalid prop \`${propFullName}\` of type \`${typeof propValue[key]}\` supplied to \`${componentName}\`, expected \`object\``);
}
if (!propValue[key].hasOwnProperty('label')) {
return new Error(`\`${componentName}\`组件的 prop 参数\`${propFullName}\`缺少属性\`label\``)
}
if (!propValue[key].hasOwnProperty('value')) {
return new Error(`\`${componentName}\`组件的 prop 参数\`${propFullName}\`缺少属性\`value\``)
}
}).isRequired,
// 选中选项value组成的数组
value: PropTypes.array,
// 是否不可用,true表示复选框组不可用,该组复选框全部为灰色
disabled: PropTypes.bool,
/**
* 组内任意选项选中状态改变时的回调函数
* @param {Array} newGroupValue 新的选中选项value组成的数组
*/
onChange: PropTypes.func.isRequired,
// 最外层元素样式
className: PropTypes.oneOfType([
PropTypes.string,
PropTypes.array,
PropTypes.objectOf(PropTypes.bool)
])
}
// 入参默认值
static defaultProps = {
disabled: false,
value: []
}
constructor(props) {
super(props);
this.state = {
options: this.getCheckboxGroupOptionList()
};
}
/**
* 获取options解析后的本组件要使用的数据
* 在要props的基础上添加一些属性
*/
getCheckboxGroupOptionList(){
let itemOptions = [];
if (this.props.options && this.props.options instanceof Array) {
let optionItem;
for (let i = 0; i < this.props.options.length; i++) {
optionItem = {...this.props.options[i]};
if (typeof this.props.options[i].value === 'object' && this.props.value instanceof Array) {
optionItem.checked = false;
for (let j =0; j < this.props.value.length; j++) {
if (JSON.stringify(optionItem.value) === JSON.stringify(this.props.value[j])) {
optionItem.checked = true;
break;
}
}
} else {
optionItem.checked = this.props.value.includes(optionItem.value);
}
itemOptions.push(optionItem);
}
}
return itemOptions;
}
/**
* 选择框组最外层需要的class
* @returns {string}
*/
getCheckboxGroupClassName(){
return utils.clasx(this.props.className, {
'checkbox-group': true,
'checkbox-group-disabled': this.props.disabled
})
}
/**
* 点击事件
* @param {number} idx 当前选项索引值
* @returns {boolean} newChecked 当前选项的新选中状态
*/
itemToggle(idx, newChecked) {
this.state.options[idx].checked = newChecked;
let newGroupValue = [];
for (let i = 0; i < this.state.options.length; i++) {
let optionItem = this.state.options[i];
if(optionItem.checked){
newGroupValue.push(optionItem.value);
}
}
this.props.onChange(newGroupValue)
}
render() {
return (
<div className={this.getCheckboxGroupClassName()}>
{this.state.options.map((item, index) =>
<CheckBox
key={JSON.stringify(item.value)}
checked={item.checked}
disabled={item.disabled || this.props.disabled}
onChange={(newChecked) => this.itemToggle(index, newChecked)}>
{item.label}
</CheckBox>
)}
</div>
);
}
}
export default CheckBoxGroup;
「欢迎在评论区讨论」