目录
React的起源
1.项目创建:
- 全局安装: npm install create-react-app -g
- 在指定路径下创建:create-react-app myreact
react在js文件中搭建项目结构
JSX:用于定义页面的结构react的特点:
- 虚拟DOM
- 组件化开发
- es6定义组件
- 函数式定义的无状态组件
- 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 函数在进入状态之后调用
- 页面加载,产品列表product.js//页面发送请求数据,(在渲染页面之前),关于fetch发起请求请见https://segmentfault.com/a/1190000003810652 搜索简书浅谈fetch https://www.jianshu.com/p/35123b048e5e
- 把数据存在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^
React的项目构建
最新推荐文章于 2024-09-18 14:22:52 发布