最近两周在研究react 相关项目,react 相关的 UI插件中,antd 算是比较好的一种,所以这里就用antd mobile 开发一个移动端项目。具体react 知识点就不赘述了。这里主要讲遇到的 tabs 问题。
有一块是新闻列表模块。但是用长列表做完以后发现,这个布局效果不理想,为什么就不能像头条一样布局呢?
虽然只是运用Tabs 和布局相关的知识,但是实际操作并没有像API 里说的那样简单。
首先在 antd mobile 里面可以发现有基本用法、无动画、垂直、自定义等各种说明。所以这里要想实现上述效果,要将垂直布局和自定义属性结合。
<Tabstabs={this.state.tabs}tabBarPosition="left"tabDirection="vertical"initalPage={'t2'}renderTabBar={props => <Tabs.DefaultTabBar {...props} page={this.state.totalPage} />}>{this.renderContent}</Tabs>
这里tabs 是左侧栏的标题内容,最后一项renderTabBar 是右侧内容区渲染函数,page指定当前tab 数量。当没有最后一个渲染函数时,初次不会渲染内容。剩下两个 tabBarPosition="left" 、tabDirection="vertical" 就是定义左侧标题栏的位置。
下面到了最难的地方,renderContent 。
官网给出的示例是:
renderContent = tab =>(<div style={
{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '150px', backgroundColor: '#fff' }}><p>Content of {tab.title}</p></div>);
这个函数其实就是对右侧内容进行渲染。
这里先对API 中给出的示例进行测试,看看这里到底会出现哪些结果。
这里可以看到其实在Tabs 初始化时,会先加载前两个tab 下的内容,以便切换tab 时,会出现一个缓冲的滑动效果。等到点击第二个 Tab 时,又重新渲染第二和第三块内容,以此类推。
放到实际运用中可以看到,会先传入tab 的id 属性
那这样根据id 做 ajax 调用不就可以了。但是发现,每次ajax 请求回来的数据渲染到h5 对象后,根本传不回来。也就是不能根据id 进行异步请求数据。所以换了一种思路,我想单纯只是用tab 而已,他右侧的内容区域用Flex 布局做成普通形式的异步请求,但是又发现
Tab 右侧内容区是自带的,并不能被人为消除,也就是2 区域所示的留白区会一直存在,且自适应大小。所以这里还是没办法要解决异步问题。
翻阅官方文档 https://www.jianshu.com/go-wild?ac=2&url=https%3A%2F%2Ffacebook.github.io%2Freact%2Ftips%2Finitial-ajax.html
要运用ajax 请求,还是要先在 componentDidMount() 中请求ajax 数据,封装到state 当中,每次点击不同tab 时再有针对性的从 state 中获取。下面给出源码示例。
componentDidMount(){this.getTabs();this.getNews();
}
getNews=()=>{axios({url:`http://localhost:3000/news?_page=1&_limit=25`,method:'get',async:false}).then(res=>{console.log(res.data);//var temp=this.renderRow(res.data);//this.setState({news:res.data})});
}
getTabs=()=>{axios({url:`http://localhost:3000/newsKind`,method:'get'}).then(res=>{this.setState ({tabs:[...res.data],totalPage:[...res.data].length});})
}render(){let mineStyle={height:document.documentElement.clientHeight-95,overflow:'auto',backgrounColor:'yellow'}return (<div >{/* 导航栏 */}<NavBar mode="dark" icon={<Icon type="left" />}onLeftClick={() =>{this.backGoing()}}rightContent={[<Icon key="0" type="search" style={
{ marginRight: '16px' }} />,<Icon key="1" type="ellipsis" />,]}>热点新闻</NavBar><div style={mineStyle}><Tabstabs={this.state.tabs}tabBarPosition="left"tabDirection="vertical"initalPage={'t2'}>{this.renderContent}</Tabs></div></div>)
}
renderContent = tab =>(<div style={
{backgroundColor: '#fff' }}>{this.renderRow(tab.id)}</div>);
renderRow=(index)=>{var jsxTemp=[];var linkStyle={display:'block'}this.state.news.forEach((val,ind)=>{if(index*this.state.totalPage<=ind && ind <this.state.totalPage*(index+1)){var newUrl=`/newDetail/${val.id}`;jsxTemp.push(<NavLink to={newUrl} key={val.id} style={linkStyle}><div style={
{ padding: '0 15px' }}><div style={
{lineHeight: '50px',color: '#000',fontSize: 18,borderBottom: '1px solid #F6F6F6',}}>{val.title}</div><div style={
{ display: '-webkit-box', display: 'flex', padding: '15px 0' }}><img style={
{ height: '64px', marginRight: '15px' }} src={val.newImg} alt="" /><div style={
{ lineHeight: 1 }}><div style={
{ marginBottom: '8px', fontWeight: 'bold' }}>{val.text}</div><div><span style={
{ fontSize: '16px', color: '#FF6E27' }}>{val.author}</span></div></div></div></div></NavLink>)}});return jsxTemp;
}
不过这里也有弊端,单次请求数据量会很大,不符合按需加载原则。希望之后对react 更了解之后再进一步改进。下面是最后的效果图: