01-render 从渲染一个组件开始~
使用map来渲染多个标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Demo extends Component { render(){ const names = ['Ale x','swif t','jon y'] return ( <div> <ul>{ names.map((name,index)=>{ return ( <h1 key={index}>hello{name}</h1> ) }) }</ul> </div> ) } }
02-父子组件 父子组件的渲染
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Hello extends Component { render(){ return <h1>hello {this .props.name}</h1> } }class Demo extends Component { render(){ const arr = [ <h1 key="1" >hello</h1>, <h2 key="2" >react</h2> ] return ( <div> <Hello name="john" ></Hello > <ul>{ arr }</ul> </div> ) } }
03-children 类似vue中的slot,获取组件开始标签和结束标签之间的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Hello extends Component { render(){ return ( <ol> {this .props.children.map((child,index)=><li key={index}>{child}</li>) } </ol>) } }class Demo extends Component { render(){ const arr = [ <h1 key="1" >hello</h1>, <h2 key="2" >react</h2> ] return ( <div> <Hello > { arr} </Hello > </div> ) } }
获取父组件demo中的h1标签,然后渲染成li标签
04-propTypes验证参数 对传入组件的参数进行验证,安装prop-type库
1 2 3 4 5 6 7 8 9 class MyTitle extends Component { render(){ return <h1>{this .props.title}</h1> } }MyTitle .propTypes={ title:PropTypes .string };
05-state状态控制 写一个按钮来显示state,实现每次触发onclick点击事件的时调用handleClick函数来改变state的状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class MyClick extends Component { constructor(props){ super (props); this .state={success:false } } handleClick(){ this .setState({success:!this .state.success}) } render(){ const text=this .state.success?'ye s':'n o' return ( <button onClick={()=>{ this .handleClick() }}> {text} </button> ) } }
官网提到使用箭头函数绑定的话,会导致父组件重复渲染,所以可以写成下面这样,绑定this值后直接调用handleClick函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class MyClick extends Component { constructor (props){ super (props); this .state={success:false } this .handleClick=this .handleClick.bind(this ) } handleClick(){ this .setState({success:!this .state.success}) } render(){ const text=this .state.success?'yes' :'no' return ( <button onClick={ this .handleClick }> {text} </button> ) } }
注意调用handleClick时后面是没有括号的,不然的话就会因为重复调用,然后报错
1 Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
即,当组件在componentWillUpdate或componentDidUpdate内重复调用setState时,就会发生这种情况
个人的理解是,当调用函数添加了括号时,执行函数return的结果,这里的handleClick函数内部是没有返回结果的,所以就会重复调用,不添加括号时就只是调用函数
06-获取真实DOM 通过ref属性从组件获取真实DOM的节点
使用一个文本框,来获取用户输入的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class MyClick extends Component { constructor(props){ super (props); this .value=React .createRef(); this .handleClick=this .handleClick.bind(this ) } handleClick(){ this .value.current.focus(); } render(){ return ( <div> <input type ="text" ref={this .value} /> <input type ="button" value="click me" onClick={ this .handleClick }></input> </div> ) } }
07-双向数据绑定 手动实现一个双向数据绑定,使用onChange事件监听文本框的输入,每次输入触发handleChange事件通过setState来修改value的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class MyBind extends Component { constructor(props){ super (props); this .state={value:"hi!" } } handleChange(event){ this .setState({value:event.target.value}) } render(){ return ( <div> <input type ="text" value={this .state.value} onChange={this .handleChange.bind(this )}/> <p>{this .state.value}</p> </div> ) } }
08-生命周期 组件的生命周期 分成三个状态,官网的图示很清晰地展示了:
Mounting:挂载,已插入真实 DOM
Updating:更新,正在被重新渲染
Unmounting:销毁,已移出真实 DOM
挂载 当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:
constructor()
static getDerivedStateFromProps()
render()
componentDidMount()
更新 当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:
static getDerivedStateFromProps()
shouldComponentUpdate()
render()
getSnapshotBeforeUpdate()
componentDidUpdate()
卸载 当组件从 DOM 中移除时会调用如下方法:
错误处理 当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:
static getDerivedStateFromError()
componentDidCatch()
在组件挂载时设置定时器对透明度进行操作,实现文本透明度渐变的效果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class MyBind extends Component { constructor(props){ super (props); this .state={ opacity:1.0 } } componentDidMount(){ this .timer=setInterval(function(){ var opacity=this .state.opacity; opacity-=.05 ; if (opacity<0.1 ){ opacity=1 } this .setState({ opacity:opacity }) }.bind(this ),100 ) } render(){ return ( <div style={{opacity:this .state.opacity}}> hello {this .props.name} </div> ) } }
09-Ajax请求 使用componentDidMount方法设置Ajax请求,等请求成功响应再渲染页面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class MyBind extends Component { constructor (props){ super (props); this .state={ username: '' , lastGistUrl: '' } } componentDidMount(){ $.get(this .props.source, function (result ) { var lastGist = result[0 ]; this .setState({ username: lastGist.owner.login, lastGistUrl: lastGist.html_url }); }.bind(this )); } render(){ return ( <div> {this .state.username}'s last gist is <a href={this.state.lastGistUrl}>here</a>. </div> ) } }
阮一峰老师用的是GitHub的api,好像已经挂了。。。。
10、创建项目 1 2 3 4 5 6 7 npm install create-react-app -gcreate-react-app React-Mock- Demo cd React-Mock- Demo npm install npx create-react-app react-mock- demo/ /注意不要又-又驼峰cd react-mock- demo
不得不说npm装得真慢
11、暴露config
creat-react-app后,将配置文件暴露出来
参考文章: