jimu-mobile
Version:
积木组件库助力移动端开发
301 lines (293 loc) • 8.05 kB
JavaScript
import React, { Component } from 'react';
/*
<Brand
cityArr={cityArr} // 城市数组
dataAttrName={ // 城市对象的默认属性为// city_id、city_name、first_char,如果对象不是这三个属性名,请把属性名传进去
{
id:'city_id',
name:'city_name',
firstChar:'first_char'
}
}
callBack={this.selectCallBack.bind(this)} 选择完以后,回调函数
/>
*/
class Brand extends Component {
constructor(props) {
super(props);
let i = 0;
const firstChar = [];
// 把26个字母放进数组里
while (i < 26) {
firstChar.push(String.fromCharCode(i + 97).toLocaleUpperCase());
i++;
}
this.fast_charTouchMove = this.fast_charTouchMove.bind(this);
this.fast_charTouchEnd = this.fast_charTouchEnd.bind(this);
this.fast_charClick = this.fast_charClick.bind(this);
this.carClick = this.carClick.bind(this);
this.hotCarBrandClick = this.hotCarBrandClick.bind(this);
this.initMaxChar = this.initMaxChar.bind(this);
this.initHotCarBrandCon = this.initHotCarBrandCon.bind(this);
this.initCarBrandCon = this.initCarBrandCon.bind(this);
this.init_fast_char = this.init_fast_char.bind(this);
this.state = {
selectBrand: null,
max_char: 'A',
showMaxChar: false,
firstChar,
};
}
componentWillMount() {
let {
carArr,
dataAttrName,
} = this.props;
if (carArr) {
// 如果是对象的话,需要转换一下
if (!carArr.length) {
const carObj = carArr;
carArr = [];
this.state.firstChar.map((char) => {
if (carObj[char]) {
carObj[char].map((ele) => {
ele[dataAttrName.firstChar] = char;
carArr.push(ele);
});
}
});
}
const Obj = {};
/* 把城市分成数组,字母相同的在一组 */
carArr.map((ele, i) => {
const firstChar = ele[dataAttrName.firstChar];
if (!Obj[firstChar]) {
Obj[firstChar] = [];
}
Obj[firstChar].push(carArr[i]);
});
this.setState({ carObj: Obj });
}
}
/* 初始化右侧字母栏 */
init_fast_char() {
const self = this;
const {
fast_charTouchMove,
fast_charTouchEnd,
fast_charClick,
state,
} = this;
const {
carObj,
firstChar,
} = state;
return (
<div
className="fast_char"
onTouchMove={fast_charTouchMove}
onTouchEnd={fast_charTouchEnd}
>
{firstChar.map((char, i) => {
if (carObj[char]) {
return (<a
href="javascript:;"
data-char={char}
key={i}
onClick={fast_charClick}
>{char}
</a>
);
}
return null;
})}
</div>
);
}
/* 解决锚点会产生历史记录,点后退,退不出当前页面的问题 */
fast_charClick(e) {
const fastCharEle = e.currentTarget;
const ele = document.querySelector(`#first_char_${fastCharEle.dataset.char}`);
const _carBrandCon = document.querySelector('._carBrandCon');
_carBrandCon.scrollTop = ele.offsetTop;
}
/* 城市点击事件 */
carClick(e) {
const {
callBack,
} = this.props;
const carObj = JSON.parse(e.currentTarget.dataset.carobj);
this.setState({
selectBrand: carObj,
});
callBack && callBack(carObj);
}
fast_charTouchMove(e) {
const { clientX, clientY } = e.targetTouches[0];
const ele = document.elementFromPoint(clientX, clientY) || {};
const dataset = ele.dataset;
if (ele && dataset.char) {
this.setState({
maxChar: dataset.char,
showMaxChar: true,
});
ele.click();
}
e.preventDefault();
}
fast_charTouchEnd() {
this.setState({
showMaxChar: false,
});
}
initCarBrandCon() {
const self = this;
const {
carObj,
selectBrand,
} = this.state;
const {
dataAttrName,
} = this.props;
if (!carObj) {
return null;
}
return (
<ul className="carBrandCon">
{
(function () {
const arr = [];
for (const a in carObj) {
arr.push(<li key={a} id={`first_char_${a}`}>
<a
className="first_char"
href="javascript:;"
>
{a}
</a>
{
carObj[a].map((ele, index) => {
let isCheck = false;
if ((selectBrand && selectBrand.id) && selectBrand[dataAttrName.id] === ele[dataAttrName.id]) {
isCheck = true;
}
{ /* div不用label是因为label click 会触发两次 */ }
return (
<div
className={`list${isCheck ? ' select' : ''}`}
key={index}
id={`car_${ele[dataAttrName.id]}`}
data-carobj={JSON.stringify(ele)}
onClick={self.carClick}
>
<img src={`${self.props.staticImgURL}${ele.id}.jpg`} />
<span
className="carBrandName"
>
{ele[dataAttrName.name]}
</span>
</div>
);
})
}
</li>);
}
return arr;
}())
}
</ul>
);
}
/* 点击定位城市的事件 */
hotCarBrandClick(e) {
document.getElementById(`car_${e.currentTarget.dataset.carid}`).click();
}
initHotCarBrandCon() {
const {
dataAttrName,
// brandStaticURL,
staticImgURL,
hotCarBrandData,
} = this.props;
const {
selectBrand,
} = this.state;
if (!hotCarBrandData) {
return null;
}
return (
<div>
<div className="selectTitle">热门车型</div>
<ul
className="hotCarBrandCon clearfix"
>
{
hotCarBrandData.map((ele, index) => {
let isCheck = false;
if ((selectBrand && selectBrand.id) &&
selectBrand[dataAttrName.id] === ele[dataAttrName.id]) {
isCheck = true;
}
return (
<li
key={index}
className={`hotCarBrandList ${isCheck ? 'select' : null}`}
data-carid={ele.id}
onClick={this.hotCarBrandClick}
>
<img src={`${staticImgURL}${ele.id}.jpg`} />
<span className="hotCarBrandName block">{ele[dataAttrName.name]}</span>
</li>
);
})
}
</ul>
</div>
);
}
initMaxChar() {
const {
maxChar,
showMaxChar,
} = this.state;
if (!showMaxChar) {
return null;
}
return <div className="max_char">{maxChar}</div>;
}
render() {
const {
carArr,
dataAttrName,
callBack,
show,
hotCarBrandData,
...other
} = this.props;
if (!show) {
return null;
}
return (
<div className="catBrandWrap">
{/* <div className="selectTitle">请选择城市</div> */}
{/* 滑动右侧字母时,中间显示的大字母 */}
{this.initMaxChar()}
{/* 城市列表 */}
<div className="_carBrandCon" {...other} >
{hotCarBrandData ? this.initHotCarBrandCon() : null}
{this.initCarBrandCon()}
</div>
{/* 初始化右侧首字母 */}
{this.init_fast_char()}
</div>
);
}
}
Brand.defaultProps = {
dataAttrName: {
id: 'id',
name: 'name',
firstChar: 'first_char',
},
};
module.exports = Brand;