react:面向组件编程
面向对象--->面向模块--->面向组件
实现效果:
<MyComponent>
<h2>工厂函数组件(简单组件)</h2>
</MyComponent>
<MyComponent2>
<h2>ES6类组件(复杂组件)</h2>
</MyComponent2>
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>work3</title>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
//方式一.工厂函数组件(简单组件:没有状态的组件):
//1.定义组件
function MyComonent(){ //直接用"渲染"方法
return <h2>工厂函数组件(简单组件)</h2>
}
//2.渲染组件标签
React.render(<MyComonent />,document.getElementById("example1"))
//方式二:ES6类组件(复杂组件)
//1.定义组件:
class MyComponent2 extends React.Component { //定义了一个组件类的子类;创建实例
render(){ //这个类里有一个render(渲染)方法
return <h2>ES6类组件(复杂组件)</h2>
}
}
//2.渲染组件标签:
ReactDOM.render(<MyComonent2 />,document.getElementById("example2"))
</script>
</head>
<body>
<div id="example1"></div>
<div id="example2"></div>
</body>
</html>
在组件类里打印this:
class MyComponent2 extends React.Component { render(){ console.log(this) return <h2>ES6类组件(复杂组件)</h2> } }
有三个重要的属性方法:
props:多个属性的集合对象
refs:略过
state:状态
组件的三大属性:
属性一:state
理解:
1.state是组件对象最重要的属性,值是对象(可以包含多个数据)
2.组件被称作“状态机”,通过更新组件的state来更新对应的页面显示(重新渲染组件)
编码操作:
1.初始化状态:
constructor(props){ super(props) this.state={ //this代表组件对象;this.state给状态赋初值 stateProp1:value1, stateProp2:value2 } }
2.读取某个状态值:(读取state内部的某个属性的值)
this.state.statePropertyName
3.更新状态--->组件界面更新(react不会操作DOM只需更新状态)
this.setState({ //更新状态的方法 stateProp1:value1, stateProp2:value2 })
实例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>work4</title>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
//1.定义组件
class Like extends React.Component{
constructor(props){ //调用父类的构造函数
super(props) //传递props
this.state={ //初始化状态
isLikeMe:false //h2里面的内容是变化的,应该有一个布尔类型的标识,两种状态表示两种文本
}
//将新增方法的this强制绑定为组件对象,bind方法会产生一个新的函数
this.handleClick=this.handleClick.bind(this)
}
render(){
//读取状态
//写法一:
// const isLikeMe=this.state.isLikeMe;
//写法二:解构赋值
const {isLikeMe}=this.state
return <h2 onClick={this.handleClick}>{isLikeMe?'都暻秀':'D.O.'}</h2>
// 绑定事件
}
//注意;以上constructor,render方法为重写组件的方法,但是下面的是新增的方法,新增方法handleClick内部的this默认不是组件对象而是undefined
handleClick(){ //更新状态
//得到原先的状态并取反
const isLikeMe=!this.state.isLikeMe
// 设置新的状态
this.setState({isLikeMe:isLikeMe})
//ES6新语法,可以简写成:this.setState({isLikeMe})
}
}
//2.渲染组件标签
ReactDOM.render(<Like />,document.getElementById("example"))
</script>
</head>
<body>
<div id="example"></div>
</body>
</html>
注意:
ReactDOM.render(<Like />,document.getElementById("example"))
//如果没有子标签,这里标签写作:<like/>,如果有子标签则写作
ReactDOM.render(<like></like>,document.getElementById("example"))
注意:只要有状态的组件就不能用工厂函数组件
属性二:props
理解:
1.每个组件对象都会有props属性
2.组件标签的所有属性都保存在props
作用:
1.通过标签属性从组件外,向组件内传递变化的数据
2.注意:组件内部不要修改props
编码操作:
1.内部读取某个属性值
this.props.propertyName
2.对props中的属性值进行类型限制和必要限制
//老方法:
Person.propTypes={ name:React.PropTypes.string.isRequired, age:React.PropTypes.number.isRequired }
//新方法:
//prop-types库
Person.propTypes={
name:PropTypes.string.isRequired, //强调了字符串类型和必须项
age:PropTypes.number //只强调数字类型
}
3.扩展属性:将对象的所有属性通过props传递
<Person...{...person}/>
4.默认属性值
Person.defaultProps={ name:"Mary" }
5.组件类的构造函数
constructor(props){ super(props) console.log(props) //查看所有属性值 }
实现效果:一个组件实现多个标签
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>work5</title>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script src="../js/prop-types.js"></script>
<script type="text/babel">
//1.定义组件
//第一种定义方法
/*function Person(props) {
return(
<ul>
<li>姓名:{props.name}</li>
<li>性别:{props.age}</li>
<li>年龄:{props.sex}</li>
</ul>
)
}*/
//第二种定义方法:
class Person extends React.Component{
render(){
return(
<ul>
<li>姓名:{this.props.name}</li>
<li>性别:{this.props.age}</li>
<li>年龄:{this.props.sex}</li>
</ul>
)
}
}
//指定属性默认值
Person.defaultProps={
sex:'男',
age:18
}
//指定属性值的类型和必要性
Person.propTypes={
name:PropTypes.string.isRequired, //强调了字符串类型和必须项
age:PropTypes.number //只强调数字类型
}
//2.渲染组件标签
const p1={
name:'Tom',
age:100,
sex:'女'
}
//ReactDOM.render(<Person name={p1.name} age={p1.age} sex={p1.sex}/>,document.getElementById("example1"))
//简写方法:
ReactDOM.render(<Person {...p1}/>,document.getElementById("example1"))
const p2={
name:'Jack'
}
ReactDOM.render(<Person name={p2.name}/>,document.getElementById("example2"))
</script>
</head>
<body>
<div id="example1"></div>
<div id="example2"></div>
</body>
</html>
注意 ES6 ... 的作用:
1.打包
//定义方法的时候 function(...as){} //调用的时候 fn(1,2,3,4,5,6)
2.解包
const arr1=[1,2,3];
const arr2=[1,...arr1,4,5,6]
属性三:refs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>work6</title>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
//1.定义组件
class MyComponent extends React.Component{
constructor(props){
super(props)
this.showInput=this.showInput.bind(this)
this.handleBlur=this.handleBlur.bind(this)
}
render(){
return(
<div>
<!-- 第一种方法:不建议用-->
<!-- <input type="text" ref="content"/>-->
<!--第二种方法:ref成为了一个回调函数,第一次渲染时就会做,此函数是把当前的dom元素保存到组件对象里-->
<input type="text" ref={input=>this.input=input}/>
<button onClick={this.showInput}>提示输入</button>
<input type="text" placeholder="失去焦点提示内容" onBlur={this.handleBlur}/>
</div>
)
}
//自定义的方法
showInput(){
/*
第一种方法:
const input=this.refs.content;
console.log(input.value)
*/
//第二种方法:
console.log(this.input.value)
}
handleBlur(event){
console.log(event.target.value)
}
}
//2.渲染组件标签
ReactDOM.render(<MyComponent />,document.getElementById("example"))
</script>
</head>
<body>
<div id="example"></div>
</body>
</html>