15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > 通过React16.8构建新闻网站第三章:新闻主页的构建

通过React16.8构建新闻网站第三章:新闻主页的构建

时间:2023-06-02 11:00:01 | 来源:网站运营

时间:2023-06-02 11:00:01 来源:网站运营

通过React16.8构建新闻网站第三章:新闻主页的构建:

专栏地址:

第三章为网站主页的构建

实现效果图如下:

1 构建主页的layout

因为主页面的数据交互比较复杂 所以根据布局 将主页面拆为四个组件IndexLeft、IndexRgiht、IndexTab、IndexBottom,而Index组件只用于主页布局,具体渲染交给各个组件来完成

目录结构如下:

Index组件

import React, { useState, useEffect } from 'react';import {Row, Col} from 'antd';//新闻列表组件import IndexTab from './IndexTab/index';//主页左边内容 轮播图和新闻图文列表import IndexLeft from './IndexLeft/index'//主页底部新闻列表import IndexBottom from './IndexBottom/index';//主页右侧新闻列表import IndexRight from './IndexRight/index';import './index.scss';const Index = props => { return ( <div className='index'> <Row> <Col span={2}/> <Col span={21}> <Row className='top_news'> <Col span={8}> <div className='top_left top'> <IndexLeft /> </div> </Col> <Col span={7}> <div className='top_center top'> <IndexTab /> </div> </Col> <Col span={6}> <div className='top_right top'> <IndexRight /> </div> </Col> </Row> <Row> <div className='bottom'> <IndexBottom /> </div> </Row> </Col> <Col span={4}/> </Row> </div> );}export default Index;这里我通过ANT Design的栅格布局将页面划分成四个部分 每个部分引入对应的组件

布局方法这里不再叙述,详见https://ant.design/components/grid-cn/

2 until.js

在开始编码具体组件前,我们先顶一个until.js来放置我们的公共方法和变量

var Tools = { // fetch接口封装 api: function({ url, args='', callback }) { let argsStr = ''; if(args!='') { for(let key in args) { argsStr += key + '=' + args[key] + '&'; } argsStr = '?' + argsStr.substr(0, argsStr.length-1); } fetch(url+argsStr) .then(response => response.json()) .then(res => { callback(res); }); }, /** * zyx * 2019/10.22 * 时间戳转时间‘YYYY-MM-DD HH:mm:ss’ */ time : function(time){ //从数据库拿出来的时间戳是字符串形式 需要转化为数字 time = parseInt(time); // 增加8小时 let date = new Date(time + 8 * 3600 * 1000); return date.toJSON().substr(0, 19).replace('T', ' '); //Date的‘toJSON’方法返回格林威治时间的JSON格式字符串,实际是使用‘toISOString’方法的结果。 //字符串形如‘2018-08-09T10:20:54.396Z’,转化为杭州时间需要额外增加八个时区, //我们需要取字符串前19位,然后把‘T’替换为空格,即是我们需要的时间格式。 }}export const api = Tools.api.bind(Tools);//host 请求地址export const host = 'http://xxx.xx.xx.xxx/tp5/public/index.php/index/index/';export const time = Tools.time.bind(Tools);这里我们主要使用封装好的fetch请求和暴露出来的host

这里建议将host地址在这里暴露出来,这样当项目变动需要改请求地址时,我们只需要把这个地址改了就行,否则每个文件都需要改动

3 公共组件

这三个模块公用一个模块 ImgBlockTypeOne

这里三个模块的样式基本一样,不同点可能在排列方式和模块的width、height

所以渲染方式我使用flex布局

将justifyContent和这个模块的width、height以props的方式传递进去,来管控布局

然后传入type来分别渲染不同类别的新闻数据

import React, { useState, useEffect } from 'react';import {Card} from 'antd';import {Link} from 'react-router-dom';//引入封装的fetch方法和host地址import {api,host} from '../../until';import './index.scss';const ImgBlockTypeOne = props => { //定义需要渲染使用state const [news,setNews] = useState(''); //组件加载时调用 相当于componentDidMount useEffect(()=>{ //动态获取数据 根据传入得type type不同拿到的数据类型不同 let wenzhangType = props.type; /** * zyx * 2020/6/9 * 拿到数据 */ api({ url:host + 'newsSelectContentByType', args: { type:1, wenzhangType, }, callback: (res) => { showData(res); } }); },[]) /** * zyx * 2020/6/9 * 数据处理函数 */ const showData = (data)=>{ let listData = []; for (let i = 0; i < props.count; i++) { let img = JSON.parse(data[i].img); listData.push({ uniquekey: data[i].id, thumbnail_pic_s: img[0], title: data[i].title, author_name: data[i].name, }); } //调用news的change方法 setNews(listData) } //根据数据渲染方法 //根据传入的componentType来渲染不同的样式 //同时布局采用的flex布局 具体样式通过props传递 判断是横向的排列还是纵向排列 const newsImage = ()=>{ if(news.length){ let newsList = ''; if(props.componentType == 1){ newsList=news.map((newsItem, index) => ( <div key={index} className='image_news_item' style={{width:props.imageWidth}}> <Link to={`details/${newsItem.uniquekey}`} target='_blank'> <img alt="newsItem.title" src={newsItem.thumbnail_pic_s} width={props.imageWidth}/> <h3>{newsItem.title}</h3> <p>{newsItem.author_name}</p> </Link> </div> )); }else if (props.componentType == 2){ newsList=news.map((newsItem,index)=>( <Link to={`details/${newsItem.uniquekey}`} target='_blank' key={index}> <section className='imageSingle_sec' style={{width:props.width}}> <div className='imageSingle_left' style={{width:props.ImageWidth}}> <img style={{width:props.ImageWidth}} src={newsItem.thumbnail_pic_s} alt={newsItem.title}/> </div> <div className='imageSingle_right'> <p>{newsItem.title}</p> <span className='realType' >{newsItem.realtype}</span> <span>{newsItem.author_name}</span> </div> </section> </Link> )); } return( <Card className={props.componentType == '2' ? 'imageSingleCard':'image_card'} title={props.cartTitle} bordered={true} style={{width:props.width,marginTop:'10px'}}> <div className='image_news_container' style={{width:props.width,justifyContent:props.justifyContent}}> {newsList} </div> </Card> ) }else{ //判断数据是否为空 如果为空 直接渲染一个正在加载 return '正在加载' } } return ( <div className='pc_news_imgblock'> {/* 调用处理好的模块*/} {newsImage()} </div> )}export default ImgBlockTypeOne;

4 IndexLeft

主页左边布局的那一模块

使用 ANT Design 的轮播图 和公共组件ImgBlockTypeOne

import React, { useState, useEffect } from 'react';import {Carousel} from 'antd';import ImgBlockTypeOne from '../../component/ImgBlockTypeOne/index';const IndexLeft = props => { return ( <div> <Carousel autoplay> <div><img src="https://zyx-news.oss-cn-hangzhou.aliyuncs.com/news1.jpg"/></div> <div><img src="https://zyx-news.oss-cn-hangzhou.aliyuncs.com/news2.jpg"/></div> <div><img src="https://zyx-news.oss-cn-hangzhou.aliyuncs.com/news3.jpg"/></div> <div><img src="https://zyx-news.oss-cn-hangzhou.aliyuncs.com/news4.jpg"/></div> </Carousel> <ImgBlockTypeOne count={10} type='4' width='100%' imageWidth='112px' cartTitle='美国大暴动' justifyContent='space-around' componentType='1'/> </div> )}export default IndexLeft;

5 IndexTab

主页中间布局的那一模块

使用ANT Design的Tab组件 来渲染不同的文章列表

import React, { useState, useEffect } from 'react';import {Tabs} from 'antd';import {Link} from 'react-router-dom';import {host,api} from '../../until';const { TabPane } = Tabs;const IndexTab = props => { const callback = (key)=>{ console.log(key); } //定义渲染需要使用的数据 const [news,setNews] =useState([]); //组件加载时调用 相当于componsetNewsentDidMount useEffect(()=>{ //动态获取数据 根据传入得type let wenzhangType = props.type; /** * zyx * 2020/6/19 * 拿到数据 */ api({ url:host + 'newsSelectContentByType', args: { type:1, }, callback: (res) => { showData(res); } }); },[]) /** * zyx * 2020/6/9 * 数据处理函数 */ const showData = (data)=>{ let listData = []; for (let i = 0; i < data.length; i++) { let img = JSON.parse(data[i].img); listData.push({ uniquekey: data[i].id, title: data[i].title, }); } //调用news的change方法 setNews(listData) } const List = ()=>{ // 将对应的新闻数据渲染成li列表 let newsList=news.map((newsItem, index) => ( <li key={index}> <Link to={`details/${newsItem.uniquekey}`} target='_blank'> {newsItem.title} </Link> </li> )); return( <ul> {newsList} </ul> ) } return ( <div> <Tabs defaultActiveKey="1" onChange={callback}> <TabPane tab="热点文章" key="1"> <List /> </TabPane> <TabPane tab="热点帖子" key="2"> <List /> </TabPane> <TabPane tab="国际新闻" key="3"> <List /> </TabPane> <TabPane tab="国内新闻" key="4"> <List /> </TabPane> </Tabs> </div> )}export default IndexTab;

6 IndexRight

主页右边布局那一个模块,纯展示模块 直接调用公共模块ImgBlockTypeOne

import React, { useState, useEffect } from 'react';import ImgBlockTypeOne from '../../component/ImgBlockTypeOne/index';const IndexRight = props => { return ( <div> <ImgBlockTypeOne width='100%' ImageWidth='100px' type='3' count={5} cartTitle='海贼王' componentType='2'/> </div> )}export default IndexRight;7IndexBottom

主页底边布局那一个模块,纯展示模块 直接调用公共模块ImgBlockTypeOne

import React, { useState, useEffect } from 'react';import ImgBlockTypeOne from '../../component/ImgBlockTypeOne/index';const IndexBottom = props => { return ( <div> <ImgBlockTypeOne count={12} type='2' width='100%' imageWidth='112px' cartTitle='R.I.P Kobe' justifyContent='space-start' componentType='1'/> </div> )}export default IndexBottom;一个主页抽离这么多模块主要是为了将数据处理和页面渲染分开,降低项目耦合

关键词:新闻,通过

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭