weex-nuke
Version:
基于 Rax 、Weex 的高性能组件体系 ~~
271 lines (250 loc) • 6.51 kB
JSX
'use strict';
/** @jsx createElement */
import { Component, createElement, PropTypes } from 'rax';
import Icon from 'nuke-icon';
import Dom from 'nuke-dom';
import Input from 'nuke-normal-input';
import View from 'nuke-view';
import Text from 'nuke-text';
import Touchable from 'nuke-touchable';
import { isWeb, isWeex } from 'nuke-env';
import { connectStyle } from 'nuke-theme-provider';
import stylesProvider from '../styles';
class SearchBar extends Component {
constructor(props) {
super(props);
let value = '';
if ('defaultValue' in props) {
value = props.defaultValue;
} else if ('defaultValue' in props) {
value = props.value;
}
this.state = {
focus: false,
value,
};
this.userInputValue = value || '';
const events = [
'focusHandler',
'blurHandler',
'changeHandler',
'inputHandler',
'searchHandler',
'returnHandler',
'textSearchHandler',
];
events.forEach((m) => {
this[m] = this[m].bind(this);
});
}
// calcRem
componentDidMount() {
const { centered } = this.props;
if (!centered) return;
Dom.getRect('parentDOM').then(
(wrap) => {
this.setState({
strentchStyle: {
width: isWeb ? `${wrap.width}px` : wrap.width, // web 端 offset 的单位是 px
},
});
},
() => {}
);
}
componentWillReceiveProps(nextProps) {
if ('value' in nextProps) {
this.setState({
value: nextProps.value,
});
this.userInputValue = nextProps.value;
}
}
render() {
const {
value,
disabled,
defaultValue,
placeholder,
onInput,
onChange,
onSearch,
inputStyle,
style = {},
themeStyle: styles,
...others
} = this.props;
const searchbarWrapStyle = Object.assign({}, styles.wrap, style);
return (
<View clsName="search-bar-wrap" style={searchbarWrapStyle} {...others}>
<View clsName="body" ref="parentDOM" style={[styles.body, inputStyle]}>
{this.renderPlaceholder(styles)}
{this.renderInput()}
</View>
{this.renderSearchButton(styles)}
</View>
);
}
// 输入框以及placeholder
renderInput() {
const { maxLength, disabled, themeStyle: styles } = this.props;
return (
<Input
ref={(ref) => {
this._input = ref;
}}
style={styles['input-wrap']}
type="search"
returnKeyType="search"
materialDesign={false}
maxLength={maxLength}
value={this.state.value}
onFocus={this.focusHandler}
onBlur={this.blurHandler}
onReturn={this.returnHandler}
disabled={disabled}
inputStyle={styles['input-ele']}
onInput={this.inputHandler}
onChange={this.changeHandler}
/>
);
}
// 模拟的 placeholder
renderPlaceholder(styles) {
const { placeholder, centered, placeholderColor } = this.props;
const { focus } = this.state;
let element;
const textStyle = {};
const TextAttrArr = ['color', 'fontSize', 'fontStyle', 'fontWeight'];
TextAttrArr.forEach((item) => {
if (styles.placeholder[item]) {
textStyle[item] = styles.placeholder[item];
}
});
if (isWeb) {
element =
placeholder && !this.userInputValue && !focus ? (
<Text style={[textStyle, { color: placeholderColor }]}>
{placeholder}
</Text>
) : null;
} else {
element =
placeholder && !this.userInputValue && !focus ? (
<Text style={[textStyle, { color: placeholderColor }]}>
{placeholder}
</Text>
) : null;
}
const iconDOM = (
<Icon style={[styles.icon, { color: placeholderColor }]} name="search" />
);
const placeholderStyle =
centered && !focus && !this.userInputValue
? { ...styles['body-centered'], ...this.state.strentchStyle }
: {};
return (
<View
role="placeholder-wrap"
ref="placeholderDOM"
style={[styles.placeholder, placeholderStyle]}
>
{iconDOM}
{element}
</View>
);
}
// 搜索按钮
renderSearchButton(styles) {
if (!this.props.showSearchButton) return null;
return (
<Touchable onPress={this.searchHandler} style={styles.button}>
<Text onPress={this.textSearchHandler} style={styles['button-text']}>
{this.props.locale.search}
</Text>
</Touchable>
);
}
focusHandler(e) {
this.setState({
focus: true,
});
this.trigger('onFocus', e);
}
trigger(fn, ...attrs) {
if (typeof fn === 'string') fn = this.props[fn];
if (!(typeof fn === 'function')) return;
return fn.apply(this, attrs);
}
blurHandler(e) {
this.setState({
focus: false,
});
this.trigger('onBlur', e);
}
inputHandler(e) {
this.userInputValue = e.value;
this.trigger('onInput', e);
}
changeHandler(value, e) {
this.setState({
value,
});
this.userInputValue = value;
this.trigger('onChange', value, e);
}
returnHandler(e) {
const value = e.value;
this.setState({ value });
this.searchHandler();
}
searchHandler(e) {
// alert(this.userInputValue);
this._input.wrappedInstance.blur();
this.props.onSearch && this.props.onSearch({ value: this.userInputValue });
}
textSearchHandler(e) {
if (isWeb) {
e.stopPropagation();
}
this.searchHandler();
}
}
SearchBar.propTypes = {
onCancel: PropTypes.func,
onChange: PropTypes.func,
onSearch: PropTypes.func,
value: PropTypes.string,
defaultValue: PropTypes.string,
locale: PropTypes.object,
disabled: PropTypes.bool,
showSearchButton: PropTypes.bool,
centered: PropTypes.bool,
placeholderColor: PropTypes.string,
inputStyle: PropTypes.any,
style: PropTypes.any,
placeholder: PropTypes.string,
onInput: PropTypes.func,
};
SearchBar.defaultProps = {
locale: {
search: '搜索',
},
onSearch: () => {},
showSearchButton: true,
disabled: false,
centered: false,
defaultValue: null,
onCancel: () => {},
inputStyle: {},
onChange: () => {},
onInput: () => {},
placeholderColor: '#cccccc',
placeholder: '',
style: {},
};
SearchBar.displayName = 'SearchBar';
const StyledSearchBar = connectStyle(stylesProvider, { withRef: true })(
SearchBar
);
export default StyledSearchBar;