React的项目构建

目录

React的起源

1.项目创建:

2.组件之间的值传递

3.react提交表单

点击button触发事件,绑定onClick事件。

在react中获取输入框的值

将值组装成APP.js 数据

重新渲染页面:关键(state)

4.react路由

5.商品页跳转详情页


 

React的起源

1.项目创建:

  1. 全局安装: npm install create-react-app -g
  2. 在指定路径下创建:create-react-app myreact

react在js文件中搭建项目结构
JSX:用于定义页面的结构

react的特点:

  1. 虚拟DOM
  2. 组件化开发

组件的创建方式

  1. es6定义组件
  2. 函数式定义的无状态组件
  3. ES5原生的JavaScript来实现的react组件

一个React组件的生命周期分为三个部分:实例化、存在期和销毁时。

以下这里用了一个评论回复的案例来讲解react,整个过程的流向图如下

流程图

2.组件之间的值传递

//1.引入React模块,首字母大写
import React, {Component } from 'react'
//2.实例化组件的创建
class CommentBox extends Component{
constructor(props){
        super(props)//初始化this

        this.state={
            // data:this.props.mydata
            data:[
                {author:"张小强",date:"今天",content:"Merry Christmas~!"},
                {author:"张大强",date:"昨天",content:"平安夜快乐!"},
                {author:"张大小强",date:"前天",content:"今天好冷哦!"},
                {author:"张小大强",date:"明天",content:"明天好冷哦~!"},
            ]
        }

    }
    getNewComment(obj){
        console.log("CommentBox收到子组件CommentForm的数据");
        console.log(obj);
        let currentComment=this.state.data;
        currentComment.push(obj);
        // this.state=currentComment;
        // console.log(this.state);

        this.setState({
            data:currentComment
        })

    }
    //html非结构 用JSX
    //调用生命周期函数render ,在进行渲染的时候会调用
    render(){
        // return 类似vue中的template
        console.log(window.location);
        return (
            <div className="box">
                <h1>CommentBox评论大BOX</h1>
                <CommentList mydata={this.state.data}/>
                <CommentForm onMyUpdate={this.getNewComment.bind(this)}/>
            </div>
        )
    }
}
export  default CommentBox;

代码实例一:

接下来是很重要的数据绑定,听了几遍都没有听得太明白
这里写详细一点

首先提到了通过props由App.js向下传递值,在调用的引入的组件上直接加上了一个mydata={this.props.mydata}

拓展一种遍历的方法:map()
.map() 

有返回值,可以return 出来。

arr[].map(function(value(当前循环项),index(遍历的下标),array(可选)){

  //do something

  return XXX

})

参数:value数组中的当前项,index当前项的索引,array原始数组;
区别:map的回调函数中支持return返回值;return的是啥,相当于把数组中的这一项变为啥(并不影响原来的数组,只是相当于把原数组克隆一份,把克隆的这一份的数组中的对应项改变了);

老师在这里做的是:
把之前app.js上写死的数据在这里用map循环出来:
在render中

let arr=this.props.mydata.map((item,index)=>{
    return (
    <Comment key={index} author={item.author}  date={item.date}>{item.content}</Comment>
        )
})

return(
    <div>
        <h1>CommentList评论列表</h1>
        {arr}//在这里把信息循环出来
    </div>

)

3.react提交表单

提交表单的主要步骤:

1.点击 提交 触发事件
2.获取输入框的值,将值组装成APP.js 数据
3.数据传递给CommentBox
4.重新渲染页面

子组件表单Form的render部分代码

addObj(){
       
        let author=this.refs.author.value;//获取到评论人的值,拓展:React之ref详细用法:https://blog.csdn.net/z69183787/article/details/69568467
        let textContent=this.refs.textContent.value;//获取内容的值
        let date=new Date().toLocaleDateString();//获取当前的时间
        let newObj={author:author,date:date,content:textContent}//用一个数组存放
        this.props.onMyUpdate(newObj)//在子组件中调用父组件的方法,传入参数
    }
render () {
        return (
            <div>
                <h1>表单</h1>
                <form>
                    评论人:<input type="text" ref="author" id="myinput"/>
                    <br/>
                    内容:<textarea name="" id="" cols="30" rows="10" ref="textContent"></textarea>
                    <br/>
                    <button type="button" onClick={this.addObj.bind(this)}>提交</button>问题:react组件的方法为什么要绑定this:我的理解this.addObj是该组件的一个方法,而这个方法并没有绑定在这个组件的实例上,为了完成事件的交互,所以必须要绑定在实例上。https://www.cnblogs.com/dashnowords/p/9343383.html
                </form>
            </div>
        )
    }

代码实例二:

点击button触发事件,绑定onClick事件。

问题:react组件的方法为什么要绑定this:我的理解this.addObj是该组件的一个方法,而这个方法并没有绑定在这个组件的实例上,为了完成事件的交互,所以必须要绑定在实例上。详细见:https://www.cnblogs.com/dashnowords/p/9343383.html

总结:render渲染页面生成实例,为了触发点击事件强制将原型方法绑定在实例上。

在react中获取输入框的值

拓展:React之ref详细用法:https://blog.csdn.net/z69183787/article/details/69568467

通过添加一个属性ref:详见:https://blog.csdn.net/Shuiercc/article/details/81383679

另外的获取输入值的方法:

addObj(){
       
        let author=this.refs.author.value;//获取到评论人的值,拓展:React之ref详细用法:https://blog.csdn.net/z69183787/article/details/69568467
        let textContent=this.refs.textContent.value;//获取内容的值
        let date=new Date().toLocaleDateString();//获取当前的时间
        let newObj={author:author,date:date,content:textContent}//用一个数组存放
        this.props.onMyUpdate(newObj)//在子组件中调用父组件的方法,传入参数
    }
render () {
        return (
            <div>
                <h1>表单</h1>
                <form>
                    //评论人:<input type="text" ref="author" id="myinput"/>
<input type="text" ref={this.author} id="myinput"/>
                    <br/>
                    内容:<textarea name="" id="" cols="30" rows="10" ref="textContent"></textarea>
                    <br/>
                    <button type="button" onClick={this.addObj.bind(this)}>提交</button>问题:react组件的方法为什么要绑定this:我的理解this.addObj是该组件的一个方法,而这个方法并没有绑定在这个组件的实例上,为了完成事件的交互,所以必须要绑定在实例上。https://www.cnblogs.com/dashnowords/p/9343383.html
                </form>
            </div>
        )
    }


 

将值组装成APP.js 数据

let newObj={author:author,date:date,content:textContent}//用一个数组存放

此时的数据流向:CommentFrom->CommentBox:onMyUpdate

CommentFrom通过props传递给CommentBox,CommentBox接收到信息,见代码实例一:

重新渲染页面:关键(state)

这是实例一的部分代码:(因为这里要用就直接粘过来了)

constructor(props){//constructor的作用:1.通过分配一个对象到 this.state 来初始化本地 state。
					//2.将 事件处理程序 方法绑定到实例。详见:https://react.css88.com/docs/react-component.html#constructor
        super(props)//初始化this,this的指向问题https://segmentfault.com/a/1190000008165717

        this.state={//存放状态的初始值
            // data:this.props.mydata
            data:[
                {author:"罗名扬",date:"今天",content:"Merry Christmas~!"},
                {author:"罗名小扬",date:"昨天",content:"平安夜快乐!"},
                {author:"罗大名扬",date:"前天",content:"今天好冷哦!"},
                {author:"罗名大扬",date:"明天",content:"明天好冷哦~!"},
            ]
        }

    }
 getNewComment(obj){
        console.log("CommentBox收到子组件CommentForm的数据");
        console.log(obj);
        let currentComment=this.state.data;
        currentComment.push(obj);
        // this.state=currentComment;//不能透过赋值来改变state的值
        // console.log(this.state);

        this.setState({//使用特定setState方法改变state,效果重新渲染页面
            data:currentComment
        })

    }//1.props 用于父子之间传递数据state 管理本组件上的数据
	//2.当state发生改变的时候 页面会触发render 重新渲染页面



  render(){
        // return 类似vue中的template
        console.log(window.location);
        return (
            <div className="box">
                <h1>CommentBox评论大BOX</h1>
                <CommentList mydata={this.state.data}/>
                <CommentForm onMyUpdate={this.getNewComment.bind(this)}/>在父组件调用子组件的位置这里写了一个事件,当子组件提交时触发这个事件。然后仍然需要对父组件中的方法进行绑定;(这里就涉及到子向父传递数据的一个应用)
            </div>
        )
    }

1.通过分配一个对象到 this.state 来初始化本地 state。

 2.将 事件处理程序 方法绑定到实例。详见:https://react.css88.com/docs/react-component.html#constructor
        super(props)//初始化this,this的指向问题https://segmentfault.com/a/1190000008165717
在 getNewComment里,重新设置state,通过setState方法,而不是用state赋值,达到重新渲染页面的作用。

1.props 用于父子之间传递数据
      state 管理本组件上的数据
    2.当state发生改变的时候 页面会触发render 重新渲染页面

组件之间的沟通方式:

父子组件的沟通
1.最常见的沟通方式:
父组件更新子组件状态,父组件更新子组件状态,通过传递props,就可以了。(懂了)
2.子组件更新父组件状态
这种情况需要父组件传递回调函数给子组件,子组件调用并触发。(懂了)


兄弟组件沟通

1.通过props传递父组件回调函数(不是很懂)
2.React提供的一种上下文方式,可以让子组件直接访问祖先的函数或者数据,无需从祖先组件一层层地传递数据到子组件中。(不懂)

全局事件沟通(不懂)

4.react路由

====================路由======================

npm install react-router-dom --save-dev

BrowserRouter as Router 最大的路由视图容器

Route 进行路由配置的组件

Link 跳转

will 函数 进入状态之前调用,did 函数在进入状态之后调用

以下使用另一个常见的商品展示实例来向我们展示react中路由的使用。

实例2-1:App.js引入路由,以及要跳转的组件

import React, { Component } from 'react';
//引入路由
import {BrowserRouter as Router,Route} from 'react-router-dom'
//引入要跳转的CommentBox组件
import CommentBox from './Components/Comment/CommentBox'
import Home from './Components/Home'
import Nav from './Components/Nav'
import ProductList from './Components/Product/ProductList'
class App extends Component {
//JSX:
render() {  
return (  
<div className="App">     
	<Router>        
		<div>           
		<Nav/>                  
		<Route path="/Comment" component={CommentBox}/>                  
		<Route path="/Home" component={Home}/>                  
		<Route path="/ProductList" component={ProductList}/>              
		</div>          
	</Router>      
</div>
    );  
}
}export default App;

实例2-2:Nav.js板块的代码

在 react training 中有各种人写好的nav,适当使用提升开发效率

import React,{Component} from 'react'
import {Link} from 'react-router-dom'//nav.js引入link
import { NavLink } from 'react-router-dom'//是从gitHub上down下的别人写的导航
import "./nav.css"

class Nav extends Component{
    render(){
        // console.log(window.location);//通过location属性获取当前pathname从而改变导航选中状态active
        // let myHome=window.location.pathname==="/Home"?"active":"";
        // let myComment=window.location.pathname==="/Comment"?"active":"";
        // return (
	//========================bootstrap导航=========
        //     <ul className="nav nav-tabs">
        //         <li role="presentation" >
        //             <Link to="/Home" className={myHome}>Home</Link>
        //         </li>
        //         <li role="presentation" className={myComment}>
        //             <Link to="/Comment">留言</Link>
        //         </li>
        //     </ul>
        // )
        //=============================================
        return (
            <ul>
                <li>
                    <NavLink to="/Home" >Home</NavLink>
                </li>
                <li>
                    <NavLink to="/Comment">留言</NavLink>
                </li>
                <li>
                    <NavLink to="/ProductList">产品</NavLink>
                </li>
            </ul>
        )
    }
}
export  default Nav

实例:2-3产品列表页面

import React,{Component} from 'react'
import 'whatwg-fetch'

class ProductList extends Component{
    constructor(props){
        super(props);
        this.state={
            product:[]
        }
    }
    componentWillMount(){
        console.log(this);
        let that=this;
        //发送请求获取json数据
        //把数据存在state==》render中遍历啊State,输出遍历后的布局结构
        fetch('product.json').then(function (resp) {
            console.log(resp);
            return resp.json()
        }).then(function (data) {
            console.log(data);
            console.log(that);
            that.setState({
                product:data
            })
        })
    }
    render(){
        let productArr=this.state.product.map((item,index)=>{
            return (
                <div key={index}>
                    <h1>产品名称:{item.productname}</h1>
                    <img src={item.imgsrc} alt=""/>
                </div>
            )
        })
        return (

            <div>
                <h1>产品列表页</h1>
                {productArr}
            </div>
        )
    }
}
export default ProductList

will 函数 进入状态之前调用,did 函数在进入状态之后调用

  1. 页面加载,产品列表product.js//页面发送请求数据,(在渲染页面之前),关于fetch发起请求请见https://segmentfault.com/a/1190000003810652 搜索简书浅谈fetch https://www.jianshu.com/p/35123b048e5e
  2. 把数据存在state==》render中遍历啊State,输出遍历后的布局结构

5.商品页跳转详情页

商品列表页

ProductList.js
import React,{Component} from 'react'
import 'whatwg-fetch'


class ProductList extends Component{
    constructor(props){
        super(props);
        this.state={
            product:[]
        }
    }
    componentWillMount(){
        console.log(this);
        let that=this;
        //发送请求获取json数据
        //把数据存在state==》render中遍历啊State,输出遍历后的布局结构
        fetch('product.json').then(function (resp) {
            console.log(resp);
            return resp.json()
        }).then(function (data) {
            console.log(data);
            console.log(that);
            that.setState({
                product:data
            })
        })
    }
    render(){
        let productArr=this.state.product.map((item,index)=>{
            return (
                <div key={index}>
		<Link to={
			{
			pathname:"ShowDeatil"
			query:{id:item.id}
			}
			}>路由拦截正常拦截<Route path="/ShowDetail"{在这里要动态拦截id} component={showDetail}/ >
                    <h1>产品名称:{item.productname}</h1>
                    <img src={item.imgsrc} alt=""/>
		 <Link/>
                </div>
            )
        })
        return (

            <div>
                <h1>产品列表页</h1>
                {productArr}
            </div>
        )
    }
}

商品详情页面

import React,{Component} from 'react'
import 'whatwg-fetch'

class showDetail extends Component{
    constructor(props){
        super(props);
        this.state={
            productDetail:[]
        }
    }
    componentWillMount(){
        console.log(this.props.match.params.id);//在这里拿到参数

        let that=this;

        //发送请求获取json数据
        //把数据存在state==》render中遍历啊State,输出遍历后的布局结构//另外在这里使用jq发送请求也是一样的 npm install jquery --save-dev
        fetch('http://172.16.6.59:8888/show.do',{
	method: 'POST',
 	 headers: {
  	  'Content-Type': 'application/json'
 	 },
 	 body: JSON.stringify({
   	 myId: this.props.match.params.id,
	  }).then(function (resp) {
            console.log(resp);
            return resp.json()
        }).then(function(json){
		console.log(json);
		that.setState({
		productDetail:json
		})
	})
    }
    render(){
	console.log(this.props.match.params.id);
        let productDetailArr=this.state.productDetail.map((item,index)=>{
            return (
                <div  key={index}>
		<Link to={"/ShowDetail"}>//在appjs对应的地方修改路由<Route path="/ShowDetail/:id"{在这里要动态拦截id} component={showDetail}/ >
			//地址栏传参的两种方法: 
			<h1>产品id:{item.id}
			<h3>产品名称:{item.productname}</h3>
                   	<img src={require("../../../public/"+item.imgsrc)} alt=""/>
		<Link/>
                </div>
            )
        })
        return (

            <div>
                <h1>详情页</h1>
                {productDetailArr}
            </div>
        )
    }
}
export default showDetail 

如有错误请不吝指正!谢谢 ^v^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值