###react安装
create-react-app是你开始构建一个全新单页面应用的最好方式
npm install -g create-react-app
create-react-app my-react-app
cd my-app
npm start
复制代码
// 1.render的含义就是把一个React元素渲染到指定的Dom容器中去;
// 2.react是一个用户构建界面的js库;
//jsx是JavaScript+html的混合写法
// render 函数里面额元素标签样式声明 className = class style={{backgroundColor:'red'}},
ReactDOM.render(
<div className="red" style={{backgroundColor:'red'}}>hello</div>,
document.querySelector('#root')
)
复制代码
React是由react元素和组件组成的;
2.组件定义的第一中方式函数(函数定义的组件是静态的,不能动)
## 组件定义的第一种方式是函数定义
import React from 'react';
import ReactDOM, {render} from 'react-dom';
**组件的首字母必须大写**
**组件定义完后可以像React元素一样使用**
函数组件的渲染过程:
1.封装props对象;
2.调用组件函数,得到返回的react标签元素;只有react元素才可以渲染页面;
3.ReactDOM把React元素转化成真是的dom元素,插入到指定的容器中;
默认我们给组件传递的属性,都会被一个对象接受,参数就是一个属性对象
let Message = (props) => {
console.log(props)//{msg: 'hell0', id: '2'}
return <h1>{props.msg}</h1>
}
render(<Message msg="hell0" id="2"/>,window.app)
复制代码
3.组件定义的第二种方式(通过类来声明组件)
import React,{Component} from 'react';// Component是react属性
import {render} from 'react-dom';
我们通过类声明组件,Clock类继承Component
class Clock extends Component {
constructor () {
super()
## 自定义组件状态对象
## 状态(state)可以用来存放组件内部一些变化的值,状态只能由内部初始化,内部改变;
this.state = {time: new Date().toLocaleString()}
}
// 声明周期函数
componentDidMount () {
setState有两个功能:
一是覆盖老的状态,
二是会从新调用render方法重新渲染
window.setInterval(() => {
this.setState({time: new Date().toLocaleString()})
},1000)
}
render方法指的是该组件如何渲染,一定要返回一个react元素,
而且只能返回一个react元素;
render(){
return <h1>{this.state.time}</h1>
}
}
render(
<Clock/>,document.querySelector('#root')
)
复制代码
4.react组件属性
import React, {Component} from 'react';
import {render} from 'react-dom';
import PropTypes from 'prop-types'
怎么定义属性,获取属性,传递属性,属性的类型
## 状态state:自己在组件内部定义的属性,在组件内部可以操作改变,外部不可操作,通过setState()方法修改state状态;
## 属性props:从组件外部传入到组件,在组件内部只可读,不可改变的;
class Person extends Component{
constructor () {
super()
// 为组件添加一个初始的状态
this.state = {happy: true}
}
// 指定默认属性对象的默认值
static defaultProps = {
name: 'wu ming'
}
// 如何定义组件传入的属性指定类型和必传性
static propTypes = {
name: PropTypes.string,
age: PropTypes.number.isRequired
}
handleClick = () => {
this.setState({
happy: !this.state.happy
})
}
// render方法是react的核心方法,dom渲染什么元素,就看render返回什么元素
##这里的render是组件的一个方法
render() {
//console.log(this)
let header = this.state.happy ? '开心': '不开心'
return (
<div>
<p>姓名:{this.props.name}</p>
<p>心情:{header}</p>
<button onClick={this.handleClick}>改变</button>
</div>
)
}
}
##这里的render是reactDom的属性,处理react里面的元素,处理成dom可以识别的dom元素,插入到指定的容器中;
render(<Person name="hello" age={100}/>,document.querySelector('#root'))
复制代码
5.受控组件DOM操作
import React, {Component} from 'react';
import {render} from 'react-dom';
##受控组件:就是input,checkbox,textare,form表单组件,实现数据的双向绑定(受当前状态控制)
##非受控组件:不受状态控制
## 1.input的value值等于state的val值,所以我们的input受state控制,只有我们的state里面的val发生改变我们的input值才会有所改变;
## 2.我们通过input onChange事件取到当前input的value值,然后在赋值给我们的state状态里面的val,进而我们input的value发生改变;
class Input extends Component {
constructor () {
super()
this.state = {val: ''}
}
handerChange = (event) => {
let val = event.target.value
this.setState({val})
}
// 元素渲染
render () {
return (
<div>
<p>{this.state.value}</p>
<input type="text" value={this.state.value} onChage={this.handerChange}>
</div>
)
}
}
##受控组件dom操作案例2
class Input extends Component {
constructor () {
super()
this.state = {a:'',b:'',result:''}
}
handleChangeA = (event) => {
this.setState({
a: parseInt(event.target.value),
result:parseInt(event.target.value) + this.state.b,
})
}
handleChangeB = (event) => {
this.setState({
b:parseInt(event.target.value),
result: this.state.a+parseInt(event.target.value),
})
}
// 渲染元素
render () {
return (
<div>
<input type="text" value={this.state.a} onChange={this.handleChangeA}/>+
<input type="text" value={this.state.b} onChange={this.handleChangeB}/>=
<input type="text" value={this.state.result} />
</div>
)
}
}
复制代码
6.非受控组件DOM操作
import React, {Component} from 'react';
import {render} from 'react-dom';
//受控组件:就是input,checkbox,textare,form表单组件,实现数据的双向绑定(受当前状态控制)
//非受控组件:
class Input extends Component {
constructor () {
super()
}
handleChangeA = (event) => {
//this.refs.result.value = parseInt(this.refs.a.value||0)+ parseInt(this.refs.b.value||0)
// 调用ref等于一个函数,react元素转化dom元素,渲染到页面,立即执行该函数,将渲染后的dom传入到该函数中;
this.result.value = parseInt(this.a.value||0)+ parseInt(this.b.value||0)
}
// 渲染元素,利用事件冒泡的机制传播绑定给父元素
// ref等于一个函数的时候,表示当前元素挂在到页面中之后会立即调用此函数,并传入渲染后的dom元素;
render () {
return (
<div onChange={this.handleChangeA}>
<input type="text" ref={ref=> this.a = ref}/>+
<input type="text" ref={ref => this.b = ref}/>=
<input type="text" ref={ref => this.result = ref} />
</div>
)
}
// render () {
// return (
// <div onChange={this.handleChangeA}>
// <input type="text" ref="a" />+
// <input type="text" ref="b" />=
// <input type="text" ref="result" />
// </div>
// )
// }
}
//这里的render是reactDom的属性,处理react里面的元素,处理成dom可以识别的dom元素,插入到指定的容器中;
render(<Input />,document.querySelector('#root'))
复制代码
7.复合组件
import React, {Component} from 'react';
import {render} from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css'
// 组件的嵌套(复合组件)
// 单项数据流:就是父组件像子组件传递参数;一层层传递,不可以直接传递给孙组件;
class Panel extends Component {
constructor () {
super()
this.state ={
col: ''
}
}
handleRed = () => {
this.setState({
col: 'red'
})
}
handleGreen = () => {
this.setState({
col: 'green'
})
}
render () {
return (
<div className="panel panel-default">
<button onClick={this.handleRed}>红</button>
<button onClick={this.handleGreen}>绿</button>
<PanelHead col={this.state.col} header = {this.props.hender}/>
<PanelBody col={this.state.col} body = {this.props.body}/>
<PanelFooter col={this.state.col} footer ={this.props.footer} />
</div>
)
}
}
class PanelHead extends Component {
render () {
return (
<div style={{color: this.props.col}} className="panel-heading">{this.props.header}</div>
)
}
}
class PanelBody extends Component {
render () {
return (
<div style={{color: this.props.col}} className="panel-body">{this.props.body}</div>
)
}
}
class PanelFooter extends Component {
render () {
return (
<div style={{color: this.props.col}} className="panel-footer">{this.props.footer}</div>
)
}
}
render(<Panel hender="tou" body="body2" footer="footer3"/>,document.querySelector('#root'))
复制代码
8.组件的声明周期函数
import React, {Component} from 'react';
import {render} from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css'
// 组件的声明周期 代码编写的顺序
class Counter extends Component {
constructor () {
super()
this.state = {num:0}
}
// 组件将要被挂载(react元素在插入页面之前)
componentWillMount () {
console.log('1.组件将要被挂在')
}
componentDidMount () {
console.log('3.组件挂载完成')
}
// 组件是否要因为props和state的变化要渲染,true为渲染,false则不渲染
shouldComponentUpdate (newProps,newState) {// 新的属性对象,新的状态对象
console.log('4.组件是否要更新,提供一个setState方法是否要触发render,重新渲染')
//它有一个返回值,返回true就渲染,执行render方法,刷新页面,否则就不渲染(我们用返回值来决定是否要刷新页面)
if (newState.num%5 === 0) {
return true
} else {
return false
}
}
componentWillUpdate () {
console.log('5.组件将要更新')
}
componentDidUpdate () {
console.log('6.组件更新完成')
}
handleClick = () => {
// setState方法是异步操作,切记不能在赋值后立即获取最新的state值,我们要在setState的第二个参数回调函数中获取
this.setState({
num: this.state.num+1
}, () => {
//console.log(this.state.num)
})
}
render () {
console.log('2.react元素插入页面,组件挂在到页面')
return (
<div style={{border: 'solid 1px red', margin: '10px'}}>
<p>{this.state.num}</p>
<button onClick={this.handleClick}>+</button>
<SubCounter num ={this.state.num}/>
</div>
)
}
}
// 子的组件
class SubCounter extends Component {
// 组件将要接受到新的属性对象,来自父组件的改变,将会重新执行render方法
componentWillReceiveProps () {
console.log('7.接受到父组件的变动,props变动')
}
shouldComponentUpdate (newProps,newState) {// 我们的newProps发生变化
if (newProps.num %10 === 0) {
return true
} else {
return false
}
}
render () {
// 我们的props的来自父组件的state状态
return (
<div style={{border: 'solid 1px green', margin: '10px'}}>
<p>{this.props.num}</p>
</div>
)
}
}
render(<Counter/>,document.querySelector('#root'))
复制代码