react 项目要点

——————————按需加载

项目第一步 : 框架 / 路由

先创建 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

        });

———————————登陆注册

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容