——————————按需加载
项目第一步 : 框架 / 路由
先创建 pages 文件夹, 并且给每个页面加文件夹,并且加jindex.js 文件
安装 npm i react-loadable -S
在pages 的index.js 里面用 loadable 来完成页面的按需加载。。
先 const Loading = ()=> null
并将按需加载的页面用export 导出
———————————创建路由
在src 目录下创建 routers.js 文件,并将 pages里的页面导入。
定义一个route 数组 每个数组元素是个对象。 包括 path 和 component
安装 react-router-dom
npm i react-router-dom -S
在最外部的index.js 里 引入
import {
BrowserRouter as Router,
Route
}from 'react-router-dot'```
并在render 的最外面加一个Router
—————————— App.js 通过路由不同来渲染数据
创建一个App.js
将 Switch Redirect 和 Routr 从 react-router-dom 引入。
import {
Switch,
Redirect,
Route
}from 'react-router-dom';
import routes from './routes'
在render 中使用 Switch 来判断路由并且 进入。
<Switch>
{
routes.map(route =>{
return (
<Route
key = {route.path}
path = {route.path}
component = {route.component}/>
)
}
)
}
<Redirect exact from='/' to ={routes[0].path}/>
<Redirect to = '/404'/>
</Switch>
根据路由来进入不同的页面显示内容, 在只有/ 的时候显示主业。在找不到页面的时候显示 404
—————————————tabbar 的制作点击更新页面 调整显示
第三部写 tabbar 最下面的导航
新建一个 Tabbar 的目录。
里面包括 一个tabbar.less 和一个 index.js
在Tabbar 中通过 map 函数渲染 生成导航
通过root 的path 来判断是否为点击状态, 点击状态是一个,当 this.props.history 与你传递的参数相等的时候, 将该盒子添加active 类。
在 iconfont 中查找想要的图标 复制倒入到 tabbar.less 中 并且在icon类中把 font-style 设置为 iconfont
第一种方法
//并在 span 中直接添加代码就可以。
//用这种方法不可以把 代码写在routes 中,要在 index.js 中 写一个方法通过 传递进来的 path 和
//switch 语句来判读 对应的加载内容,完成加载图标。
修改App 中的 less 来用弹性盒子。来将导航放到底部。
第二种方法
将icon的代码保存到 routes.js 中,icon = ‘’; 字符串的方式 , 在用map 渲染的是,将 要添加的对象中添加一个dangeroudlySetInnerHTML 属性,属性传递的参数 必须是一个对象。
<span className='icon' dangerouslySetInnerHTML = {{__html : route.icon}}></span>
在 nom 中 找到 css reset 找到最开始的 css 初始化设置,来完善
————————————轮播图制作
轮播图制作
在antd-mobile 中有走马灯 carousel 这个组建。 在组建下面有控制 轮博体效果的类。
dote swipe autoplay 等都应该为 true。 这样才是正常 轮播图的效果。
在 有轮播图页面的 less 最外元素设置一个 touch-action 为none 可以消除 滑动时候的错误。
不加的时候报错 如下
react-dom.development.js:1574 [Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See
———————————用axios 完成数据请求
用axios 做数据请求 。 用rap2 来生成数据
创建借口 ,
返回数据
安装 axios
npm i axios -S
新建一个 servieces.js 文件 引入 axios
定义一个ajax 用
axios.create(
baseURL:‘’;
)
来传递基础的链接。返回一个方法, 用来 ajax.get (不相同的地址)
在Home 中的 index.js 引入到处的 方法,
在 componentDidMount进行ajax 请求,
componentDidMount(){
getSwiper()
.then(res =>{
console.log(res);
this.setState({
swiper : res.data.data
})
})
}
res 返回的数据中的data.data 就是传递进去的假数据。
打印出返回的数据
——————————— 实现加载中 操作
实现加载未完成的时候 的loading洁面
在 antd -mobile 中找到 toast并 在 ajax 的
interceptor 中 做 如果请求 则显示加载。 请求完成则 loading 消失。。
为了看到 loading显示 做了setTime 测试
ajax.interceptors.request.use(config=>{
Toast.loading("加载中…",0)
return config;
})
ajax.interceptors.response.use(res =>{
Toast.hide();
if(res.data.code === 200 && res.data.error_message === 'SUCCESS'){
return res.data.data
}else {
Toast.fail(res.data.error_message)
}
}
———————————— 判断是否为开发环境 ,请求不同接口
在 services.js 中 的 baseURL中判断 是否飞开发环境 如果是开发环境 就请求假数据。如果不是就请求真实的接口
react 自带的 process.env.NODE_ENV 可以判断是否为开发环境。
const isDev = process.env.NODE_ENV === 'development';
// console.log(isDev);
const ajax = axios.create (
{
baseURL :isDev ? 'http://rap2api.taobao.org/app/mock/117677' : '真实的API地址'
}
);
——————————https 协议的接口 通过配置proxy 可以实现代理请求数据
请求别人的后段接口,如果是http 的协议,可以直接访问,如果是https 接口 会受访问限制,
可以在两个地方修改。
一个是 config 中 的webpackDevServer.config 文件
第二种方式 在package.json 中添加一个 proxy 并做如下配置。
但是老子的报错。。
"proxy" : {
"/epet" : {
"target" : "https://mallcdn.api.epet.com",
"changeOrigin" : true,
"pathRewrite" :{
"/epet" :""
}
}
}
——————————————Header渲染
header 组件作为一个共有的组件创建在component 文件夹下
在header 的index 中 引入 connect
定义方法 用来返回 页面标题信息。
const mapState =(state) =>{
return {
pageTitle : state.ui.pageTitle
}
}
state 来自于 要引入header 的界面 的 connect的第一个括号传递来的参数
根据data 的pageTittle 和switch 语句来渲染不同的header
export default connect(mapState)(Header)
在 App.js中引入Header组件
创建一个action 文件夹
其中包括 actionType => 用来命名 action 的type 名字 并且返回。
export const CHANGE_PAGE_TITLE = "CHANGE_PAGE_TITLE";
和一个 ui.js 文件夹
action 下的 ui.js 用来返回一个 掉用参数时要传递的action参数。
export const changeUiTitle = (title) =>{
return {
type : actionType.CHANGE_PAGE_TITLE,
title
}
}
在reducer 中的
在ui.js 引用 actiontype
import * as actionType from '../actions/actionType'
并且传递参数 和action
export default (state = initState,action)
通过switch 语句来判断 aciton 的type 属性 如果为 CHANGE_PAGE_TITLE
则将 在文件前定义的参数 initState 改成 action传递 过来的 title (action中ui.js 返回的changeUiTitle )
在每个需要渲染Header 的页面
引入 connect import { connect } from 'react-redux';
在页面中定义一个mapState 用来返回当前页面的 页面标题
在到处的时候 运用 connect 导出
export default connect (null , { changeUiTitle })(Home);
————————————Mall商城页面制作
第三部进行商城分类页面构建 在 Mall 的 index 中完成
用constructor 来进行构造函数。
this.state 进行初始化
在 rap2 中生成导航数据和 商品列表的 假数据。
在services 中 export const 一个新的函数 用来返回 要请求的导航 或者商品的接口。
并在index 中引入 services 中的 组件
在componentDidMount 中发送ajax请求。
在 .then 中 进行用setState 来修改 数据
在 Mall 页面下 新建 两个组件,
sidebar -> 用来渲染左边的导航栏
和mainbar -> 用来渲染右边的商品显示页面。
两个组件
在index 中引入两个组件。 在 render 的时候用标签饮用
将 当前id 用属性的方式传递。
在sidebar中根据传递来的属性来进行 active 渲染
读取当前 id 在map 中与每一个id 进行对比。如果不想等 就没有active 类,如果想等就有 active 类。
componentDidMount (){
this.props.changeUiTitle ('分类');//此时为 将页面的 标题传递给header
getList()
.then(res=>{
this.setState({
list : res,
currentListId : res[0].id
}
,()=>{
this.getList();
})
});
}
getList = () =>{// getList 是一个方法 不仅要在加载的时候调用,还要在每次点击别的标签的时候从新渲染数据
getShopListById(this.state.currentListId)
.then(res=>{
this.setState ({
shopList : res
})
})
}
onItemClick = (id) =>{
this.setState({
currentListId : id
},()=>{
this.getList()
}
)
}
在 mainbar 中 通过传递进来的id 来进行跳转页面 path 进去相应 的详情页。
—————————商品详情页面
首先在 servuces 中 添加 返回商品详情页 的方法。
用rap2 生成。。跟id 对应。
当从分类页面点击的时候,要跳转到商品详情页面, 然后传递 所点击的id 到 props 在 detail 中打印 this.props 用 引入react 的组件都有props
在 componentDidMount 中做 ajax 请求
componentDidMount(){
this.props.changeUiTitle('商品详情');
const {id} = this.props.match.params;
// console.log(id)
getDetailById (id)
.then(res =>{
this.setState({
detail : res.filter(item=>{
return item.id == id
//遍历列表 返回 与传入id 想等的数据 在 render 中渲染。
})
})
})
}
———————————本地存储的方式
1.cookie 限制 4kb
2.webstorage -> localstorage 和 sessionstorage 大小 5M
3.indexedDB 存储量 最大
—————————购物车制作
先设计ui 显示。
在 action 的 actiontype 中 添加方法 点击数量增加或减少
然后在 cart.action 中 引入action type
导出 添加和减少的方法
export const cartAdd =(id) =>{
return {
type : actionType.CART_COUNT_ADD,
id
}
}
在要进行 添加购物车的页面 引入action 的cart.js
用connect链接, 将 返回的参数通过 action中的方法到处到reducer 中操作
然后在reducer 的 cart.js 引入actiontype 添加一个 init 保存 测试数据,
引入
通过switch 来判断 type 和actiontype中的 type是否相等来进行对应操做
在每次更改购物车数据的时候在 localstorage 中进行保存
const addstorage = (list)=>{
return window.localStorage.setItem('animal-cart', JSON.stringify(list));
}
export default (state = initState , action) =>{
switch (action.type){
case actionType.CART_COUNT_REDUCE :
const reduceList= state.list.reduce((result,item) =>{
if(item.id === action.id){
item.count= item.count - 1 ;
}
if(item.count > 0){
result.push(item)
}
return result;
},[])
addstorage(reduceList);
return Object.assign({},state,{
list :reduceList
});
———————————登陆注册
网友评论