自学react有一段时间了,官网文档基础的看了一遍,然后便把之前公司做的一个vue项目用react搭建了下,顺便整理下一些知识点。
项目大概效果:
一、利用create-react-app搭建项目
1、全局安装create-react-app,执行:npm install -g create-react-app 命令进行安装
2、进入要安装项目的文件夹,执行:npx create-react-app my-app 创建一个my-app项目
3、进入项目cd my-app,执行:npm start 编译启动项目即可
二、引入公用的css和脚本(rem.js移动端适配用)
一开始我是直接在src文件夹下新建了个assets文件夹,用来放置各种资源文件,然后直接在public文件下的index.html文件中直接用link和script引入css和脚本,但是引入脚本却报错了(Uncaught SyntaxError: Unexpected token < )百度了下也没明白是什么原因,然后解决办法就是:把assets文件夹放到和index.html同级目录下再引入就可以了。
三、搭建页面(以首页为例)
1、在src文件夹下新建assets(放置资源文件)、component(放置公用的组件)、pages(放置页面)文件夹。
2、创建页面及对应的样式文件,并通过import '路径',直接引入,然后ClassName=“类名”来引用。
3、创建组件:可以通过es5原生方式React.createClass定义的组件,或者 es6形式的extends React.Component定义的组件(需要手动绑定this),这边采用后者来创建
//es5
const MyComponent=React.createClass({render:function () {return <h1>mycomponent</h1>}})//es6
class MyConponent extends React.Component{constructor(props){super(props);}render() {return (<h1>mycomponent</h1>);}}
四、遇到的几个问题如下:
(1)import直接引入css样式的话,会导致css样式成为全局样式,容易产生类名冲突,样式互相覆盖。
解决方法:把css文件命名成xxx.module.css文件,然后通过import styles from ‘路径’ 引入,再通过styles.xxx来引用对应的类名,对于main-box之类的类名可通过styles['main-box']来引用,但是并不是很方便,所以可以使用驼峰法mainBox来命名类
import styles from './home.module.css'<div className={styles['user-box']+' flex-h flex-hsb'}><div className="flex-h flex-vc"><img className={styles.photo} src={require('../../assets/images/default.png')} /><span className={styles.user}>{this.state.username}</span></div><span className={styles.signin}>签到</span></div>
(2)如何使用swiper轮播
解决方法:执行:npm install swiper --save 安装依赖包;然后在要使用的页面上导入对应的css文件和js文件:
import Swiper from 'swiper/dist/js/swiper.js'
import 'swiper/dist/css/swiper.min.css'
接下来就是和平时使用swiper是一样的了,html:
<div className="banner swiper-container"><div className="swiper-wrapper"><div className="swiper-slide"><img className="banner-img" src={require('../../assets/images/home/banner1.jpg')} /></div><div className="swiper-slide"><img className="banner-img" src={require('../../assets/images/home/banner2.jpg')} /></div><div className="swiper-slide"><img className="banner-img" src={require('../../assets/images/home/banner3.jpg')} /></div></div><div className="swiper-pagination"></div></div>
初始化(在组件生命周期componentDidMount里面调用初始化):
initSwiper(){let banner = new Swiper ('.banner', {loop: true, //循环slidesPerView: "auto",centeredSlides:true,autoplay: { //滑动后继续播放(不写官方默认暂停)disableOnInteraction: false,},pagination: { //分页器el: '.swiper-pagination'}})}
(3)图片的引入
解决方法:a、导入图片路径:
import Img from "./images/1.png"
<img src={Img} alt=""/>
b、直接获取图片路径:
<img src={require("./images/1.png")} alt=""/>
c、作为背景图片使用,可以直接写在css文件上或者如下
style={{background:`url(${require("./images/1.png")})` }}
首页具体代码如下:
/*首页*/
import React from 'react'
import Swiper from 'swiper/js/swiper.js'
import 'swiper/css/swiper.min.css'
import styles from './home.module.css'import './homeSwiper.css'import Tabbar from '../../components/tabbar/tabbar'import activity_img from '../../assets/images/home/home_activity.png'
import menu_icon1 from '../../assets/images/home/menu_icon1.png'
import menu_icon2 from '../../assets/images/home/menu_icon2.png'
import menu_icon3 from '../../assets/images/home/menu_icon3.png'
import menu_icon4 from '../../assets/images/home/menu_icon4.png'class Home extends React.Component{constructor(props){super(props)this.state = {username: 'Helen',menu: [{ id: 0,title: '资讯快递',icon: menu_icon1,descript: '了解行业动态'},{id: 1,title: '财经要闻',icon: menu_icon2,descript: '最新财经资讯'},{id: 2,title: '新手引导',icon: menu_icon3,descript: '轻松玩转币赚'},{id: 3,title: '了解区块链',icon: menu_icon4,descript: '全球数字经济'}],notice: [1,1,1,1,1,1,1,1,1],usdt: []}this.initSwiper = this.initSwiper.bind(this)}initSwiper(){let banner = new Swiper ('.banner', {loop: true, //循环slidesPerView: "auto",centeredSlides:true,autoplay: { //滑动后继续播放(不写官方默认暂停)disableOnInteraction: false,},pagination: { //分页器el: '.swiper-pagination'}})}initNoticeSwiper(){let banner = new Swiper ('.notice-swiper', {loop: true, //循环direction : 'vertical', observer:true,//修改swiper自己或子元素时,自动初始化swiperobserveParents:true,//修改swiper的父元素时,自动初始化swiperautoplay: { //滑动后继续播放(不写官方默认暂停)disableOnInteraction: false,},})}getUsdtData(usdt){let send_data = {"event":"subscription","data":"market.price."+usdt}let that = thisthis.sendMsg(send_data,ev=>{//console.log(JSON.parse(ev.data),'订阅数字货币最新价格')let data = JSON.parse(ev.data);if(data.currency === 'BTCUSDT')that.state.usdt[0] = data.dataelse if(data.currency === 'ETHUSDT')that.state.usdt[1] = data.dataelse if(data.currency === 'LTCUSDT'){that.state.usdt[2] = data.data}if(usdt==='stop')return falsethat.setState({usdt: that.state.usdt})})}componentDidMount(){this.initSwiper()this.initNoticeSwiper()this.getUsdtData('all')}componentWillUnmount(){this.getUsdtData('stop')}render(){const up_color = styles['color-05AC8B'],down_color = styles['color-D94F65'];const is_up1 = (this.state.usdt[0]&&this.state.usdt[0].rpt.toString().indexOf('-')!=-1)?down_color:up_color;const is_up2 = (this.state.usdt[1]&&this.state.usdt[1].rpt.toString().indexOf('-')!=-1)?down_color:up_color;const is_up3 = (this.state.usdt[2]&&this.state.usdt[2].rpt.toString().indexOf('-')!=-1)?down_color:up_color;return (<div className={styles['home-wrap']}><div className={styles['user-box']+' flex-h flex-hsb'}><div className="flex-h flex-vc"><img className={styles.photo} src={require('../../assets/images/default.png')} /><span className={styles.user}>{this.state.username}</span></div><span className={styles.signin}>签到</span></div><div className="banner swiper-container"><div className="swiper-wrapper"><div className="swiper-slide"><img className="banner-img" src={require('../../assets/images/home/banner1.jpg')} /></div><div className="swiper-slide"><img className="banner-img" src={require('../../assets/images/home/banner2.jpg')} /></div><div className="swiper-slide"><img className="banner-img" src={require('../../assets/images/home/banner3.jpg')} /></div></div><div className="swiper-pagination"></div></div><div className={styles['notice-box']+' flex-h'}><i className={styles['horn-icon']}></i><div className={styles['notice-swiper']+' notice-swiper swiper-container swiper-no-swiping'}><div className="swiper-wrapper">{this.state.notice.map((item,index)=>{return <div className="swiper-slide" key={index}><p>全球币交易全新升级,等你来体验!---{index+100}</p></div>})}</div></div></div><div className={styles['usdt-box']+' flex-h'}><div className={styles['usdt-item']}><p className={styles['color-fff']}>BTC/USDT</p><p className={styles['font-32']+' '+is_up1}>{this.state.usdt[0]?this.state.usdt[0].p.toFixed(2):'1221.12'}</p><p className={is_up1}>{this.state.usdt[0]?(this.state.usdt[0].rpt*100).toFixed(2):'0.26'}%</p><p>¥{this.state.usdt[0]?this.state.usdt[0].pr.toFixed(2):'223.45'}</p></div><div className={styles['usdt-item']}><p className={styles['color-fff']}>ETH/USDT</p><p className={styles['font-32']+' '+ is_up2}>{this.state.usdt[1]?this.state.usdt[1].p.toFixed(2):'1115.22'}</p><p className={is_up2}>{this.state.usdt[1]?(this.state.usdt[1].rpt*100).toFixed(2):'-0.12'}%</p><p>¥{this.state.usdt[1]?this.state.usdt[1].pr.toFixed(2):'3212.11'}</p></div><div className={styles['usdt-item']}><p className={styles['color-fff']}>LTC/USDT</p><p className={styles['font-32']+' '+is_up3}>{this.state.usdt[2]?this.state.usdt[2].p.toFixed(2):'2201.13'}</p><p className={is_up3}>{this.state.usdt[2]?(this.state.usdt[2].rpt*100).toFixed(2):'0.12'}%</p><p>¥{this.state.usdt[2]?this.state.usdt[2].pr.toFixed(2):'323.11'}</p></div></div> <div className={styles['activity']}><img className="wh100" src={activity_img} /></div><div className={styles['notice-box']+ ' flex-h '+styles['border-none']}><i className={styles['horn-icon']+' '+styles['recharge-text']}></i><div className={styles['notice-swiper']+' notice-swiper swiper-container swiper-no-swiping '+styles['recharge-swiper']}><div className="swiper-wrapper">{this.state.notice.map((item,index)=>{return <div className="swiper-slide" key={index}><p>相见不如怀恋 成功充值2000元---{index+10}</p></div>})}</div></div></div><div className={styles['menu-box']+' flex-h'}>{this.state.menu.map((item,index)=>{return <div className={styles['menu-item']+' flex-h flex-vc'} key={item.id}><img className={styles['menu-icon']} src={item.icon} /><div><p className={styles['menu-title']}>{item.title}</p><p>{item.descript}</p></div></div>})}</div><Tabbar /></div>)}
}export default Home
.home-wrap{color: #fff; background-color: #0C1537;}
.user-box{padding: .4rem;}
.signin{padding: 0 .36rem;height: .6rem;line-height: .6rem;background-color: #3975F9;font-size: .28rem;border-radius: 27px;
}
.user{position: relative;font-size: .32rem; margin-left: .28rem;}
.user:before{position: absolute;right: -18px;top: 8px;content: '';width: 0;height: 0;border-width: 6px;border-style: solid;border-color: #fff transparent transparent transparent;
}
.photo{width: .65rem;height: .65rem;border: 2px solid #fff;border-radius: 50%;
}.notice-box{margin: 0 .31rem;padding: .28rem 0;border-bottom: 1px solid #353F61;
}
.horn-icon{width: .34rem;height: .3rem;background-image: url(../../assets/images/home/icon_horn.png);background-repeat: no-repeat;background-size: 100%;margin-right: .28rem;
}
.notice-swiper{width: 90%;font-size: .24rem;color: #fff;height: .3rem;line-height: .3rem;
}
.usdt-box{padding-top: .5rem;padding-bottom: .5rem;font-size: .24rem;color: #69748D;
}
.usdt-item{width: 33.33%;text-align: center;
}
.activity{margin: 0 .2rem; height: 1.56rem;}
.recharge-text{width: 1.1rem;height: .27rem;background-image: url(../../assets/images/home/recharge_text.png);
}
.recharge-swiper{width: 78%;}
.border-none{border: none}
.menu-box{margin: 0 .15rem; -webkit-flex-wrap: wrap; flex-wrap: wrap;}
.menu-item{width: 3.4rem;padding: .36rem 0;background-color: #04092C;-webkit-border-radius: 8px;border-radius: 8px;font-size: .24rem;color: #737FA1;margin: 0 .1rem .2rem;
}
.menu-icon{width: .8rem; height: .8rem; margin-left: .4rem; margin-right: .3rem;}
.menu-title{font-size: .28rem; color: #fff; font-weight: bold;}.font-32{font-size: .32rem; font-weight: bold; margin-top: .12rem;}
.color-fff{color: #fff;}
.color-05AC8B{color: #05AC8B;}
.color-D94F65{color: #D94F65;}