自学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自己或子元素时,自动初始化swiper
observeParents:true,//修改swiper的父元素时,自动初始化swiper
autoplay: { //滑动后继续播放(不写官方默认暂停)
disableOnInteraction: false,
},
})
}
getUsdtData(usdt){
let send_data = {"event":"subscription","data":"market.price."+usdt}
let that = this
this.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.data
else if(data.currency === 'ETHUSDT')
that.state.usdt[1] = data.data
else if(data.currency === 'LTCUSDT'){
that.state.usdt[2] = data.data
}
if(usdt==='stop')
return false
that.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;}