React组件(可以视为第三方组件)如下所示:
import * as React from 'react';
import classnames from 'classnames';
import { extractCommonClassNames } from '../../utils';
export const Tag = (props: React.ElementConfig): React$Node =>{
const{
classNames,
props:
{
children,
className,
...restProps
},
} = extractCommonClassNames(props);
const combinedClassNames = classnames(
'tag',
className,
...classNames,
);
return (
<span
className={combinedClassNames}
{...restProps}
>
{children}
<i className="sbicon-times txt-gray" />
</span>
);
};
使用上面的组件的组件如下所示:
import React from 'react';
import * as L from '@korus/leda';
import type { KendoEvent } from '../../../types/general';
type Props = {
visible: boolean
};
type State = {
dropDownSelectData: Array<string>,
dropDownSelectFilter: string
}
export class ApplicationSearch extends React.Component<Props, State> {
constructor(props) {
super(props);
this.state = {
dropDownSelectData: ['Имя', 'Фамилия', 'Машина'],
dropDownSelectFilter: '',
};
this.onDropDownSelectFilterChange = this.onDropDownSelectFilterChange.bind(this);
}
componentDidMount() {
document.querySelector('.sbicon-times.txt-gray').classList.remove('txt-gray');
}
onDropDownSelectFilterChange(event: KendoEvent) {
const data = this.state.dropDownSelectData;
const filter = event.filter.value;
this.setState({
dropDownSelectData: this.filterDropDownSelectData(data, filter),
dropDownSelectFilter: filter,
});
}
// eslint-disable-next-line class-methods-use-this
filterDropDownSelectData(data, filter) {
// eslint-disable-next-line func-names
return data.filter(element => element.toLowerCase().indexOf(filter.toLowerCase()) > -1);
}
render() {
const {
visible,
} = this.props;
const {
dropDownSelectData,
dropDownSelectFilter,
} = this.state;
return (
<React.Fragment>
{
visible && (
<React.Fragment>
<L.Block search active inner>
<L.Block inner>
<L.Block tags>
<L.Tag>
option 1
</L.Tag>
<L.Tag>
option 2
</L.Tag>
<L.Tag>
...
</L.Tag>
</L.Block>
</L.Block>
</React.Fragment>
)}
</React.Fragment>
);
}
}
是否可以从外部从组件中删除"txt-gray"
,如果可以,怎么办?
答案 0 :(得分:1)
从使用Tag组件的位置删除该类:
componentDidMount() {
document.querySelector('.sbicon-times.txt-gray').classList.remove('txt-gray')
}
或更具体地:
.querySelector('span i.sbicon-times.txt-gray')
根据您的评论,
我有多个带有“ txt-gray”的组件,但是当我使用您的代码时,“ txt-gray”仅从第一个组件中删除了。如何从所有组件中删除它?
我建议您使用代码删除使用Tag组件的父组件中的类。并且也使用querySelectorAll as in this post。
答案 1 :(得分:1)
一种干净的方法是修改组件,以使其可以通过prop有条件地添加txt-gray
:
<i className={classnames('sbicon-times', { 'txt-gray': props.gray })} />
如果由于组件属于第三方库而无法对其进行修改,则涉及到分叉库或将第三方组件替换为其修改后的副本。
findDOMNode
一种解决方法是直接在父组件中访问DOM:
class TagWithoutGray extends React.Component {
componentDidMount() {
ReactDOM.findDOMNode(this).querySelector('i.sbicon-times.txt-gray')
.classList.remove('txt-gray');
}
// unnecessary for this particular component
componentDidUpdate = componentDidMount;
render() {
return <Tag {...this.props}/>;
}
}
通常不建议使用findDOMNode
,因为直接DOM访问不是React惯用的,它存在性能问题并且与服务器端呈现不兼容。
cloneElement
修补组件另一个解决方法是修补组件。由于Tag
是函数组件,因此可以直接调用它来访问和修改其子代:
const TagWithoutGray = props => {
const span = Tag(props);
const spanChildren = [...span.props.children];
const i = spanChildren.pop();
return React.cloneElement(span, {
...props,
children: [
...spanChildren,
React.cloneElement(i, {
...i.props,
className: i.props.className.replace('txt-gray', '')
})
]
});
}
这被认为是黑客,因为包装器组件应了解修补的组件实现,如果实现发生更改,它可能会中断。
答案 2 :(得分:0)
否,不可能
唯一的方法是更改标签组件
import * as React from 'react';
import classnames from 'classnames';
import { extractCommonClassNames } from '../../utils';
export const Tag = (props: React.ElementConfig): React$Node =>{
const{
classNames,
props:
{
children,
className,
...restProps
},
} = extractCommonClassNames(props);
const combinedClassNames = classnames(
'tag',
className,
...classNames,
);
const grayClass = this.props.disableGray ? 'sbicon-times' : 'sbicon-times txt-gray';
return (
<span
className={combinedClassNames}
{...restProps}
>
{children}
<i className={grayClass} />
</span>
);
};
现在,如果您通过disableGray={true}
,它将取消灰度级;否则,如果您传递false或完全避免通过该道具,它将使用灰度级。这是该组件的一个很小的更改,但是它允许您不更改代码中使用该组件的所有点(您对灰色文本满意)