Appearance
横向分类列表开发,搞定诸多类似场景
本节目标:理解“横向分类列表开发,搞定诸多类似场景”的核心思路,并能把它用于实际开发或面试表达。
说明:原 OneNote 中有图片引用,但图片未包含在导出目录中;本页保留了可用的文字与代码内容。 ==本节最终效果如下所示==
:
接受参数 ==在== baseUI ==文件夹下新建== horizen-item ==目录,接着新建== index.js==。== ==首先分析这个基础组件接受哪些参数,==
import React, { useState, useRef, useEffect, memo } from 'react';import styled from'styled-components';import Scroll from '../scroll/index'import { PropTypes } from 'prop-types';import style from '../../assets/global-style';
function Horizen (props) { return ( //==暂时省略==
)}
//==首先考虑接受的参数==
//list==为接受的列表数据==
//oldVal==为当前的== item ==值==
//title==为列表左边的标题==
//handleClick==为点击不同的== item ==执行的方法==
Horizen.defaultProps = { list: [], oldVal: '', title: '', handleClick: null};
Horizen.propTypes = { list: PropTypes.array, oldVal: PropTypes.string, title: PropTypes.string, handleClick: PropTypes.func};export default memo (Horizen);==现在,来把== props ==对象进行解构赋值,==
const { list, oldVal, title } = props;const { handleClick } = props;==返回的== JSX ==代码为==
:
return ( <Scroll direction={"horizental"}> <div> <List> <span>{title}</span> { list.map ((item) => { return ( <ListItem key={item.key} className={`${oldVal === item.key ? 'selected': ''}`} onClick={() => handleClick (item.key)}> {item.name} </ListItem> ) }) } </List> </div> </Scroll>);==样式代码==
:
//==由于基础组件样式较少,直接写在== index.js ==中==
const List = styled.div` display: flex; align-items: center; height: 30px; overflow: hidden; >span:first-of-type { display: block; flex: 0 0 auto; padding: 5px 0; margin-right: 5px; color: grey; font-size: ${style ["font-size-m"]}; vertical-align: middle; }`const ListItem = styled.span` flex: 0 0 auto; font-size: ${style ["font-size-m"]}; padding: 5px 8px; border-radius: 10px; &.selected { color: ${style ["theme-color"]}; border: 1px solid ${style ["theme-color"]}; opacity: 0.8; }`==现在大家还看不到效果,可能会有些慌张,没关系,我们现在就把这个组件进入到页面中试一试。== 载入页面 ==进入到== application/Singers/index.js ==中,代码如下==
:
import React from 'react';import Horizen from '../../baseUI/horizen-item';import { categoryTypes } from '../../api/config';
function Singers () { return ( <Horizen list={categoryTypes} title={"==分类== (==默认热门==
):"}></Horizen> )}
export default React.memo (Singers);==分类数据在== api/config.js ==中,但现在还没定义,现在在这个文件中添加以下代码==
:
//==歌手种类==
export const categoryTypes = [{ name: "==华语男==
", key: "1001"},{ name: "==华语女==
", key: "1002"},{ name: "==华语组合==
", key: "1003"},{ name: "==欧美男==
", key: "2001"},{ name: "==欧美女==
", key: "2002"},{ name: "==欧美组合==
", key: "2003"},{ name: "==日本男==
", key: "6001"},{ name: "==日本女==
", key: "6002"},{ name: "==日本组合==
", key: "6003"},{ name: "==韩国男==
", key: "7001"},{ name: "==韩国女==
", key: "7002"},{ name: "==韩国组合==
", key: "7003"},{ name: "==其他男歌手==
", key: "4001"},{ name: "==其他女歌手==
", key: "4002"},{ name: "==其他组合==
", key: "4003"},];
//==歌手首字母==
export const alphaTypes = [{ key: "A", name: "A" }, { key: "B", name: "B" }, { key: "C", name: "C" }, { key: "D", name: "D" }, { key: "E", name: "E" }, { key: "F", name: "F" }, { key: "G", name: "G" }, { key: "H", name: "H" }, { key: "I", name: "I" }, { key: "J", name: "J" }, { key: "K", name: "K" }, { key: "L", name: "L" }, { key: "M", name: "M" }, { key: "N", name: "N" }, { key: "O", name: "O" }, { key: "P", name: "P" }, { key: "Q", name: "Q" }, { key: "R", name: "R" }, { key: "S", name: "S" }, { key: "T", name: "T" }, { key: "U", name: "U" }, { key: "V", name: "V" }, { key: "W", name: "W" }, { key: "X", name: "X" }, { key: "Y", name: "Y" }, { key: "Z", name: "Z" }];解决滚动问题 ==启动项目,进入歌手列表页后,你发现这个横向列表并不能滚动,我们再回顾下== better-scroll ==的== (==横向==) ==滚动原理,首先外面容器要宽度固定,其次内容宽度要大于容器宽度。== ==因此目前存在两个问题==:
- ==外部容器未限定宽度,也就是两个==
Horizen==外面包裹的==div==元素。== - ==内部宽度没有进行相应的计算,始终为屏幕宽度。==
==现在就分别来解决这两个问题。== ==首先,新建== Singers/style.js ==并增加:==
import styled from'styled-components';import style from '../../assets/global-style';
export const NavContainer = styled.div` box-sizing: border-box; position: fixed; top: 95px; width: 100%; padding: 5px; overflow: hidden;`;==在== Singers/index.js ==中使用==
:
import { NavContainer } from "./style";
//...//==返回的==
JSXreturn ( <NavContainer> <Horizen list={categoryTypes} title={"==分类== (==默认热门==
):"}></Horizen> <Horizen list={alphaTypes} title={"==首字母==
:"}></Horizen> </NavContainer>)//...==接下来== ==,我们进入== baseUI/horizen-item/index.js ==中==
:
//==加入声明==
const Category = useRef (null);
//==加入初始化内容宽度的逻辑==
useEffect (() => { let categoryDOM = Category.current; let tagElems = categoryDOM.querySelectorAll ("span"); let totalWidth = 0; Array.from (tagElems).forEach (ele => { totalWidth += ele.offsetWidth; }); categoryDOM.style.width = `${totalWidth}px`;}, []);
// JSX==在==Scroll==下面,对第一个== div ==赋予==
ref<Scroll direction={"horizental"}> <div ref={Category}>点击 item 样式改变 ==现在整个列表就可以滑动啦。不过还有一个问题,当我们点击某个== item ==的时候,应该呈现选中样式,然后并没有,因为我们并没有在点击的时候改变== oldVal ==的值。== ==现在进入到== Singers/index.js ==中,我们加入部分逻辑后代码如下==
:
import React, {useState} from 'react';import Horizen from '../../baseUI/horizen-item';import { categoryTypes, alphaTypes } from '../../api/config';import { NavContainer } from "./style";
function Singers () { let [category, setCategory] = useState (''); let [alpha, setAlpha] = useState ('');
let handleUpdateAlpha = (val) => { setAlpha (val); }
let handleUpdateCatetory = (val) => { setCategory (val); }
return ( <NavContainer> <Horizen list={categoryTypes} title={"==分类== (==默认热门==
):"} handleClick={(val) => handleUpdateCatetory (val)} oldVal={category}></Horizen> <Horizen list={alphaTypes} title={"==首字母==
:"} handleClick={val => handleUpdateAlpha (val)} oldVal={alpha}></Horizen> </NavContainer> )}
export default React.memo (Singers);==好,现在就有了我们开头的效果。现在你可以为所欲为地滑动、点击,都没有任何问题啦。== > 来自
<https://juejin.im/book/5da96626e51d4524ba0fd237/section/5da97528e51d452527779f1f>