MultiList 3.0.4
多级选择列表组件,该组件基于list组件封装,支持列表展示,支持自定义模板展示,内容异步加载等功能。
引用方式
import { MultiList } from '$yo-component';
// 如果你的项目中未使用最新的 ykit-config-yo 插件,可能无法使用上面这个语法糖
// 你仍然可以通过下面这种方式来引用
import MultiList from 'yo3/component/multilist';
使用场景
这里展示的是 multiList 主要使用场景,用于多级列表选择。常见于去哪儿客户端、美团客户端、大众点评客户端,位置筛选功能。
class MultiListDemo extends Component {
constructor(props) {
super(props);
this.state = {
multiValue: [],
dataSource: originalData
};
}
handleValueChange({newValue}) {
let value;
// 最后一项选中项value值为0,则清空value,0通常是不限。
if (newValue[newValue.length - 1] === DEFAULT) {
value = [];
} else {
value = newValue;
}
this.setState({
multiValue: value
});
}
async handleUpdateData(item){
switch (item.asyncType){
case 'SUBWAY-2':
originalData.subList[5].subList[1].subList = await fetchDataOfSubway();
this.setState({
dataSource: Object.assign({}, originalData)
});
break;
}
}
render() {
return (
<Page title="multiList Demo" extraClass="demo-content">
<MultiList
dataSource={this.state.dataSource}
value={this.state.multiValue}
onChange={this.handleValueChange.bind(this)}
onUpdateData={this.handleUpdateData.bind(this)}
/>
</Page>
);
}
}
异步加载数据
该方法用于减少首次渲染数据的大小,不适用于替代首次数据的获取。下面是传入组件中用于渲染的 dataSource
。
const dataSource = {
defaultValue: 1,
subItemType: 'MENU',
subList: [{
name: '同步',
value: 1,
defaultValue: '1-1',
subItemType: 'RADIO',
subList: [{
name: '1-1 默认选项',
value: '1-1'
}, {
name: '1-2',
value: '1-2'
}, {
name: '1-3',
value: '1-3'
}, {
name: '1-4',
value: '1-4'
}]
}, {
name: '异步',
value: 2,
subItemType: 'RADIO',
defaultValue: '2-2',
subList: 'ASYNC',
asyncType: '2-2'
}]
};
组件按照 Value 和 defaultValue 来计算展开路径,并渲染组件。当渲染到 subList
为 ASYNC
的节点时会触发 onUpdateData
事件,并传入该层级数据内容作为参数,用户可以通过判断 Value
或自定义 key
值标记,获取数据更新 dataSource
。
class SimpleMultiList extends Component {
// ...
async handleUpdateData(item){
/**
* item 内容为
* {
* name: '异步',
* value: 2,
* subItemType: 'RADIO',
* defaultValue: '2-2',
* subList: 'ASYNC',
* asyncType: '2-2'
* }
*/
switch (item.asyncType){
case '2-2':
testData[1].subList = await fetchData();
this.setState({
dataSource: {
defaultValue: 1,
subList: testData,
subItemType: 'MENU'
}
});
break;
}
}
render() {
return (
<Page
title="multiList Demo"
extraClass="demo-content"
>
<MultiList
dataSource={ this.state.dataSource}
value={this.state.value}
onUpdateData={this.handleUpdateData.bind(this)}
onChange={({newValue}) => {
this.updateValue(newValue);
Toast.show(`您的选择是${newValue.join('>')}`)
}}
/>
</Page>
)
}
}
自定义内容
multiList 主要适用于多级选择列表,但是也支持自定义二级及二级以下内容的自定义。使用时传入 subList 传入自定义内容,触发 renderContent,该方法需返回一个 element。
const multiData = {
subItemType: 'ProductMenu',
subList: [{
name: '产品1',
value: 1,
subList: 'product1'
},{
name: '产品2',
value: 2,
subList: 'product2',
}]
};
class SimplaMultiList extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: multiData,
value: [1]
}
}
updateValue(value) {
this.setState({
value,
})
}
render() {
return (
<Page
title="multiList Demo"
extraClass="demo-content"
>
<MultiList
dataSource={ this.state.dataSource}
value={this.state.value}
onChange={({newValue}) => {
this.updateValue(newValue);
}}
onItemTap={({item})=>{
return [item.value];
}}
renderItem={({itemType, data, isSpread, index})=>{
switch (itemType){
case 'ProductMenu':
return <ProductMenu data={data} isSpread={isSpread} index={index}/>
}
}}
renderContent={({type}) => {
switch (type) {
case 'product1':
return <Product tit="product1" />;
case 'product2':
return <Product tit="product2" />;
}
}}
/>
</Page>
)
}
}
ReactDOM.render(<SimplaMultiList /> , document.querySelector('#container'));
dataSource { Array } #
dataSource 是一个树形的结构,每一个层级会有defaultValue,表示默认展开该哪个item或者默认选中项(非必填),subList为下级层级的内容,subList的每个字项设置内容如下。
- name 为文字描述
- value 该项value
- subItemType 用于设置下一层级的list item使用的组件,内置
MENU
,RADIO
,CHECKBOX
。如果传入的字符不在默认序列中会触发组件的renderItem方法,由用户自行渲染。 - itemType 用于定义当前item 使用的组件,优先级高于父层级的
subItemType
。 - subList支持数组和String类型,当传入array类型渲染为列表,
内置String为
FAULT
,ASYNC
,EMPTY
对应内置模板分别用于展示加载错误,加载中,加载内容为空三种情况, 其中加载ASYNC
会触发onUpdateData事件,通知用户更新数据。用户可以通过自定义字符串,触发renderContent方法, 返回ReactElement作为内容并进行其他操作。 - defaultValue 表示该层级的默认值,若下一级为最后一层级表示,默认值[注意:默认值不会作为value]。
const dataSource = {
defaultValue: 1,
subItemType: 'MENU',
subList: [{
name: '同步',
value: 1,
defaultValue: '1-1',
subItemType: 'RADIO',
subList: [{
name: '1-1 默认选项',
value: '1-1'
}, {
name: '1-2',
value: '1-2'
}, {
name: '1-3',
value: '1-3'
}, {
name: '1-4',
value: '1-4'
}]
}, {
name: '异步',
value: 2,
subItemType: 'RADIO',
defaultValue: '2-2',
subList: 'ASYNC',
asyncType: '2-2'
}]
};
value { Array } #
mutliList的值,该值为点选的value
onChange { Function } #
用于更新结果的回调函数
function({level, listValue, newValue, newItems}){
level 表示当前菜单层级
oldValue 表示当前multiList的value
newValue 表示更新后的multiList的value
newItems 表示更新后的value对应的item
}
extraClass { String } #
给组件根节点附加的额外样式类
默认值: null
onItemTap { Function } #
当Item的类型不是'MENU'、'CHECKBOX'、'RADIO',该事件将会被触发。事件处理函数需要有返回值,该值将会作为newValue
触发组件的onChange
事件。
方法参数:
参数名 | 类型 | 描述 | 支持版本 |
---|---|---|---|
父层数据,层级,改节点数据,该节点索引, | data, level, item, index, target |
renderItem { Function } #
当Item的类型不是'MENU'、'CHECKBOX'、'RADIO',该事件将会被触发。事件处理函数需要有返回值,返回值是PropsTypes.element
类型作为List
的 item
。
renderItem={(item)=>{
const {itemType, data, isSpread, index} = item;
JSON.stringify(item);
// { "itemType":"ProductMenu", 节点的Type类型(此时的`itemType`是组件根据父节点`subItemType`和该节点`itemType`按照优先级处理过的值。)
// "level":0, item所在层级
// "index":"2", item所在父节点subList
// "route": "1>2>1", item在dataSource中的索引值
// "isLeaf":false, 该节点是否为叶子节点
// "isSpread":false, 如果该节点为父节点时该值表示该节点是否是展开的
// "isChecked":false, 该节点是否是有效值
// "data":{"name":"产品2","value":2,"subList":"product2","key":1,"_index":1} 原数据内容`key`值为组建计算由于优化List性能,如原数据中有设置则使用原数据,单请调用者保证key值在该层级中的唯一性。
// }
switch (itemType){
case 'ProductMenu':
return <ProductMenu data={data} isSpread={isSpread} index={index}/>
}
}}
方法参数:
参数名 | 类型 | 描述 | 支持版本 |
---|---|---|---|
父层数据,节点所在层级,节点数据,该节点在父节点`subList`中的索引, | itemType, data, level, item, index, target |
renderContent { Function } #
当subList的类型不是array,该事件将会被触发,事件处理函数需要有返回值,返回值是PropsTypes.element
类型作为List
的 item
。
renderContent={(item) => {
const {type} = item;
console.log(JSON.stringify(item));
// {"type":"product1","data":{"name":"产品1","value":1,"subList":"product1","key":"1"},"level":1}
switch (type){
case 'product1':
return <Product tit="product1" />;
case 'product2':
return <Product tit="product2" />;
}
}}
方法参数:
参数名 | 类型 | 描述 | 支持版本 |
---|---|---|---|
节点的Type类型, | itemType, data, level | 父层数据,层级,改节点数据,该节点索引, |
onUpdateData { Function } #
当加载的层级为ASYNC
时触发,用于用户更新dataSource,用户通过获取数据中的内容判断如何更新dataSource。
方法参数:
参数名 | 类型 | 描述 | 支持版本 |
---|---|---|---|
data | 父节点的数据 |