React入门实例:组件化+react-redux实现网上商城(1)

react

项目运行

    1.git clone https://github.com/soybeanxiaobi/React_demo_onlineShop

2.cd React_demo_onlineShop(文件目录)

3.npm install(安装依赖)

4.npm start(项目启动)

功能一览

1.购买产品

2.查看购买的产品

3.删除购买的产品

功能gif图:

实现过程


一、创建项目(脚手架方式)

通过使用create-react-app创建项目,可以免去安装和配置webpack和babel等工具,使得创建项目变得便捷许多,因为他们已经被预先安装和配置了。

npm install -g create-react-app //安装React脚手架

好了,开始构建项目!

    create-react-app react-demo-shop //最后面的是项目文件夹名字

cd react-demo-shop //进入文件夹

npm start //启动

简单解释一下自动生成的各文件的含义

react-demo-shop/

node_modules/ //依赖包

public/

index.html //页面模板

favicon.ico //react的ICON图标

src/ //开发源码

App.css

App.js

App.test.js

index.css

index.js //js入口文件

logo.svg

package.json //定义了这个项目所需要的各种模块,以及项目的配置信息

README.md //备注

二、分析公共组件和路由组件

公共组件总共有两个,一个是顶部的React_Demo:小商城(topInfo);另一个是左侧的导航栏(leftNavigator)

现在对页面结构进行一些更改:

  1. 删除自动生成的App文件,同时删除index.js里App的内容。
  2. 新增images、pages、router文件夹
  3. images用于放置后面需要用到的两张图片:icebox.png、tv.jpg
  4. router用来实现代码的路由功能
  5. pages用来放公共组件(common)和路由组件

现在页面结构如下:

react-demo-shop/

node_modules/

public/

src/ //开发源码

images/ //图片

tv.jpg

pages/

common/ //公共组件

topInfo.js //顶部组件

leftNavigator.js //左侧导航栏

Product.css //产品界面样式

modules/ //路由组件

allProducts/ //所有产品

myProducts/ //我的产品

router/

index.js

index.css //公共css

index.js //js入口文件

package.json

README.md

三、给页面添加公共组件

//topInfo.js

import React,{Component} from \'react\' //添加react模块

export default class TopInfo extends Component{

render(){

return(

<div>

<p>React组件Demo:小商城</p>

</div>

)

}

}

//navleftNavigator.js

import React from \'react\'

import { Link,withRouter } from \'react-router-dom\'

class Nav extends React.Component{

render(){

// console.log(this.props.history.location.pathname);

return(

<ul className="nav nav-pills">

<li className={this.props.history.location.pathname === \'/\' ? \'active\' : \'\'} role="presentation"> //role="presentation"是无障碍阅读

<Link className="liBtn" to=\'/\'>所有产品</Link>

</li>

<li className={this.props.history.location.pathname === \'/myProducts\' ? \'active\' : \'\'} role="presentation">

<Link className="liBtn" to=\'/myProducts\'>我的产品</Link>

</li>

</ul>

)

}

}

//通过withRouter给Nav组件注入路由信息

Nav = withRouter(Nav);

export default Nav;

leftNavigator需要安装react-router-dom模块. 在文件根目录(package.json所在位置)终端输入:

npm install react-router-dom --save

withRouter可以包装任何自定义组件,将react-router 的 history,location,match 三个对象传入。

例如:

//withRouter例子:

render() {

const { match, location, history } = this.props

return (

<div>当前路由:{location.pathname}</div>

)

}

通过对this.props.history.location.pathname进行三元运算,可以高亮当前选中的li

如果仅仅是想在Link上实现点击后呈现高亮效果,可以使用官方文档的activeClassName

http://react-guide.github.io/react-router-cn/docs/API.html#link

最后我们在route/index.js里面加入这两个公共组件!

//route/index.js

import React from \'react\'

import { BrowserRouter as Router,Route,Switch} from \'react-router-dom\';

import \'bootstrap/dist/css/bootstrap.min.css\'

//添加组件

//公共组件

import Navigator from \'../pages/common/leftNavigator\' //左侧导航栏组件

import TopInfo from \'../pages/common/topInfo\' //顶部信息栏

class RouteJs extends React.Component{

render(){

return(

<Router>

<div className="componentWried">

<div className="topInfo">

<TopInfo />

</div>

<div className="container-fluid">

<div className="row">

<div className="col-sm-2 left_nav">

<Navigator />

</div>

<div className="col-sm-10 right_cont">

<div className="showComp">

</div>

</div>

</div>

</div>

</div>

</Router>

)

}

}

export default RouteJs

因为index.js用到了bootstrap,所以我们还需要去安装bs的依赖包

npm install bootstrap —save

引入css比较容易,不需要依赖其他

import ‘bootstrap/dist/css/bootstrap.css’

引入bootstrap.js 需要先引入jq和popper(编译bs4.0)

npm install jquery —save 

npm install popper.js —save //不能漏掉.js,popper和popper.js不一样

如果不安装popper,会提示can’t resolve ‘popper.js’

最后在js入口文件引入路由文件,渲染组件

//index.js

import React from \'react\';

import ReactDOM from \'react-dom\';

import registerServiceWorker from \'./registerServiceWorker\';

import \'./index.css\';

//导入路由Js

import RouterJs from \'./router/index\'

ReactDOM.render(<RouterJs />,document.getElementById(\'root\'))//渲染到html标签

registerServiceWorker();//用于在生产环境中为用户在本地创建一个service worker 来缓存资源到本地,用来处理离线缓存、消息推送、后台自动更新等任务,提升应用的访问速度

好,写到这我们看一下现在页面效果

四、给页面添加路由组件

*当路由路径为\'/\'时候,渲染allProducts组件

*当路由路径为\'/myProducts\'时候,渲染myProducts组件

//allProducts.js

import React from \'react\'

class AllProducts extends React.Component{

render(){

return(

<div>

<p>AllProducts</p>

</div>

)

}

}

export default AllProducts;

//myProducts.js

import React from \'react\'

class MyProducts extends React.Component{

render(){

return(

<div>

<p>MyProducts</p>

</div>

)

}

}

export default MyProducts;

我们在index.js中导入这两个路由组件,并添加上相应的路由

import React from \'react\'

import { BrowserRouter as Router,Route,Switch} from \'react-router-dom\';

import \'bootstrap/dist/css/bootstrap.min.css\'

//添加组件

//公共组件

import Navigator from \'../pages/common/leftNavigator\' //左侧导航栏组件

import TopInfo from \'../pages/common/topInfo\' //顶部信息栏

import allProducts from \'../pages/modules/allProducts/index\' //主页组件

//注意,这里通过component加载组件,首字母是可以小写的,如果是自定义组件,首字母必须大写

import myProducts from \'../pages/modules/myProducts/index\' //添加信息组件

class RouteJs extends React.Component{

render(){

return(

<Router>

<div className="componentWried">

<div className="topInfo">

<TopInfo />

</div>

<div className="container-fluid">

<div className="row">

<div className="col-sm-2 left_nav">

<Navigator />

</div>

<div className="col-sm-10 right_cont">

<div className="showComp">

<Switch>

<Route exact path="/" component={allProducts} />

<Route path="/myProducts" component={myProducts} />

</Switch>

</div>

</div>

</div>

</div>

</div>

</Router>

)

}

}

export default RouteJs

注意:exact是匹配精准路径,只有当路径为\'/\'才会渲染allProducts组件.如果没有exact,当路由路径为\'/myProducts\',route会先识别到\'/\',从而先渲染allProducts组件,后再渲染myProducts

我们现在再看一下页面效果:

好,页面总的框架我们已经搭建好啦。

我们现在完善一下路由组件的内容:

首先我们先看一下\'所有产品\'模块的文件目录:

  allProducts/

index.js //allProductsf根(父)组件

child/ //根据情况划分的公共组件

allProduct.js //公共组件的根组件,实现react-redux

allProductJson.js //这是模拟的产品的数据

allProductLists.js //这里是处理产品添加功能的逻辑组件

modal.css //样式

myProducts/

index.js //allProductsf根(父)组件

child/ //根据情况划分的公共组件

myProdutLists.js //显示我的产品、处理逻辑的组件

介绍一下各个js的内容

//allProductJson.js

//模拟json数据,导入组件中引用

module.exports = {

products:[

{

name:\'小米小电视\',

description:\'优质、优惠、优美\',

price:\'550\',

},

]

}

//allProducts.js

//这里用来发送react-redux的action和数据,避免代码过于繁杂,把其他逻辑功能放到子组件实现

import React from \'react\'

//导入子组件

import ProductLists from \'./allProductLists\'

class AllProducts extends React.Component{

render(){

// console.log(AllProductsJson);

addProduct(e){

//获得子组件传递的数据

console.log(e)

//数据传入函数

// this.props.onSubmitData(e);

}

return(

<div className="allProducts">

<ProductLists onSubmitData={this.addProduct.bind(this)} />

</div>

)

}

}

export default AllProducts;

allProductLists通过props方法传递产品数据给父组件allProduct

//数据传回父级

onSubmitChild(e){

// let idx = e.target.getAttribute(\'data-idx\');

//state存储的数据是在打开模态框的时候添加的

let idx_pro_name = this.state.idx_pro_info.name;

let idx_pro_price = this.state.pro_price;

let idx_pro_count = this.state.pro_count;

//数据传回父级

this.props.onSubmitData({

pro_name:idx_pro_name,

pro_price:idx_pro_price,

pro_count:idx_pro_count,

})

}

<button type="button" className="btn btn-primary" onClick={this.onSubmitChild.bind(this)} >添加</button>

父组件获得子组件传递的数据

至此!案例只剩下allProducts和myProducts之间的通信功能.

我们要把在allProducts选中的产品添加到myProducts,但是this.props无法做到没有任何联系的两个组件之间的通信.这时候我们可以使用react-redux。

仅仅使用react-redux的固定模板并不会太难,要深入理解每一个概念,需要花一点功夫。我们可以先预习一下,在下篇再介绍这个案例如何通过react-redux实现两个组件的通信

可以先看看阮一峰老师的文章:http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_three_react-redux.html

以上是 React入门实例:组件化+react-redux实现网上商城(1) 的全部内容, 来源链接: utcz.com/z/383295.html

回到顶部