-
数据的双向绑定
首先来一个双向绑定来开开胃,react不像vue、angular一样都有双向绑定的自定义标签 v-model、 ng-model ,自定义标签方便了数据的双向绑定的写法;react中就没有这种自定义标签,需要用代码逻辑来实现
class App extends Component { constructor(props) { super(props); this.state = { inputValue: "test", }; this.changeInput = this.changeInput.bind(this); } changeInput(e) { // 将改变后的 input 值赋值给 inputValue,通过事件对象 $event.target.value 实现 this.setState({ inputValue: e.target.value }); } render() { // input 改变时触发 changeInput return ( <div className="App"> <input value={this.state.inputValue} onChange={this.changeInput} /> <p>{this.state.inputValue}</p> </div> ); } } export default App;
-
数据的展示
组件内部的展示和更新都是通过 state 来实现的,如果要使用 state 必须使用 ES6 的 class 定义组件。数据更新在双向数据绑定部分探讨,这部分仅讨论展示初始化数据。
如果你熟悉Vue、 React 的state对象相当于Vue的data对象
下面是简单的数据展示
class App extends Component { constructor(props) { super(props); // 初始化 state this.state = { inputValue: "test", }; } render() { // 注意,在 react 中,DOM 元素是对象,所以使用‘()'包住 return ( <div className="App"> <p>{this.state.inputValue}</p> </div> ); } } export default App;
在通过 class 定义的 React 组件中,除了生命周期钩子函数, constructor() 和 render() 着两个方法也是自动执行的,先执行 constructor() ,执行 constructor() 的同时也是再为 render() 渲染 DOM 做数据准备。
实际上 constructor() 函数是组件生命周期中调用的第一个函数
-
父子组件之间的数据传递以及事件、方法
首先创建两个组件父组件和子组件分别命名为 父---Sudoku、子---Popup。应用场景是父组件为任务组件,子组件为任务介绍以及所需完成任务功能。父组件任务逻辑比较复杂和业务逻辑需求特殊,所以将父组件Sudoku封装了起来,在页面组件PromoteProsperity 中使用下面有介绍里面应用到的react组件事件和方法的传递。
import React, { Component } from 'react'; import Popup from '../../components/Popup/index' class Sudoku extends Component{ constructor(props){ super(props); this.state = { checked : false, //显示隐藏提示组件 isShowImg:false,//动态确定按钮的显示隐藏 someConster:'',//任务的内容 beginDate:'',//开始的时间 endDate:'',//结束的时间 code:'', // 任务标识 inviteCode:'',//邀请码 linkUrl:'',//去做任务的地址 } } promoteClcik (n) { // 点击任务,弹框的显示 console.log(n) let signinBeginDate = n.beginDate; let signEndDate = n.endDate; let startCode = n.code; let conatenCon = n.explain; let isConImg = n.isComplete;//任务的状态 let Name = n.name let url = n.url; let type = n.type if(type === 2){ TDAPP.onEvent('QKH502002','特殊任务',{Name})//特殊任务的埋点 }else if(type ===1){ TDAPP.onEvent('QKH502001','日常任务',{Name})//日常任务的埋点 } if(url !== undefined){ // 判断弹框内容以及需要的内容 this.setState({ someConster:conatenCon, beginDate:signinBeginDate, endDate:signEndDate, code:startCode, isShowImg:isConImg, linkUrl:url }) }else{ this.setState({ someConster:conatenCon, beginDate:signinBeginDate, endDate:signEndDate, code:startCode, isShowImg:isConImg, }) } this.setState({ checked:!this.state.checked }) } onokClick(code,win,url){ // 去完成,跳转页面做任务 console.log(code,win,url); if(win){ this.setState({ checked:!this.state.checked }) TDAPP.onEvent('QKH502004') }else{ let pushUrl = url.split('url相同的前缀进行截取'); if(pushUrl[1]){ this.props.history.push(pushUrl[1]); }else{ jsbridge.downApp(url); } TDAPP.onEvent('QKH502003'); } } this.setState({ checked:!this.state.checked }) } getInviteCode(){ getInviteInfo().then( res=>{ if(res.success){ this.setState({ inviteCode:res.data.code }) }else{ this.layer(res.message); } }) .catch( ()=>{ this.layer('服务器开小差,请稍后再试'); } ) } propsmote(shareName){ TaskComplete(shareName).then(res =>{ if(res.success){ this.props.megShow() }else{ console.log(res.message); } }).catch(()=>{ this.layer('服务器开小差,请稍后再试'); }) } disClick(){ // 隐藏任务弹出框 this.setState({ checked:!this.state.checked }) } componentDidMount(){ this.getInviteCode(); } render(){ const {beginDate,endDate,code,isShowImg,linkUrl} = this.state const {newtitle,sudoArr,text} = this.props; //父组件传递的值 return ( <div> <div className={style.promconter}> <div className={style.contertitle} > <img src={Blueox} alt=""/><div>{newtitle}</div> { sudoArr.map((item,index)=>{ return ( <div className={style.oneconter} key={index}> <div onClick={()=>{this.promoteClcik(item)}}> <img className={style.promfrider} src={item.picture} alt=""/> <p>{item.name}</p> <div className={style.probott}> { item.isComplete ? <div><img src={Finish} alt=""/> <span>{text}</span></div> : <div><span >+{item.prosperityValue}</span> 繁荣值</div> } </div> </div> { // 任务弹框组件是否显示 this.state.checked ? <Popup beginDate={beginDate} //子组件的使用 endDate={endDate} contenter={this.state.someConster} title="任务说明" disClick={()=>{this.disClick()}} onok={()=>{this.onokClick(code,isShowImg,linkUrl)}} isShow={isShowImg} code={code} /> : "" } </div> ) }) } </div> </div> </div> ) } } export default Sudoku;
在子组件Popup中使用父组件传递的参数和事件
import React, { Component } from 'react'; class Popup extends Component{ constructor(props){ super(props); this.state ={ } } render(){ const {disClick,onok,title,contenter,beginDate,endDate,isShow ,code} = this.props; return ( <div> <div className={style.popup}> <div className={style.propfont}> <div className={style.popobox}> {title} </div>//父组件中传递的title和时间 <div >{contenter}<span>任务有效期: {beginDate} 起至 {endDate}</span></div> { isShow ?code === "share" || code ==="open_gome" ? <img onClick={onok} src={BackBottom} alt=""/>//图片的展示 :<div className={style.popotext} onClick={onok}>确定</div>//事件的传递 : <img onClick={onok} src={BackBottom} alt=""/> } </div> </div> </div> ) } } export default Popup;
this.props接受父组件传递的数据和事件。
其实父组件中有用到react方法传递 this.props.megShow()这是页面组件PromoteProsperity 传过来的,现在我们来看下页面组件里面是怎么样传的。
import React, { Component } from 'react' import { TaskList } from './../../api/task' import Sudoku from '../../components/Sudoku/index' import Header from "Header" import Main from "Main" class PromoteProsperity extends Component { constructor(props){ super(props); this.state ={ typeOutProArr:[], typeTwoProArr:[], errorMesage:'' } } megShow(){ TaskList().then( res =>{ if(res.success){ this.setState({ typeOutProArr:res.data.filter(item => item.type === 1), typeTwoProArr:res.data.filter(item => item.type === 2), }); }else{ this.layer(res.message); } }).catch(() =>{ this.layer('服务器开小差了,请稍后再试'); }) } componentDidMount(){ this.megShow(); } render() { return ( <div className="full"> <Header {...this.props} title="任务记录"/> <Main {...this.props} hasHeader> <div style={promotebackgStyle}> <img style={promoStyle} src={Bannar} alt=""/> <Sudoku text="已完成" newtitle='日常任务' megShow={this.megShow.bind(this)} sudoArr={this.state.typeOutProArr}></Sudoku> <Sudoku text="已完成" newtitle='特殊任务' megShow={this.megShow.bind(this)} sudoArr={this.state.typeTwoProArr} ></Sudoku> <div style={footitleStyle} >更多任务,敬请期待! </div> </div> </Main> </div> ); } } export default PromoteProsperity;
如上所示,页面组件中使用了Sudoku组件将megShow方法传递下去 到应用组件中this.props.megShow()调用。