第二章 React面向组件编程
一、基本理解和使用
1. 使用React开发者工具调试
2. 效果
2.1 函数式组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>1_函数式组件</title>
</head>
<body>
<div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
function MyComponent(){
console.log(this);
return <h2>我是用函数定义的组件(适用于【简单组件】的定义)</h2>
}
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
</script>
</body>
</html>
2.2 复习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>类的基本知识</title>
</head>
<body>
<script type="text/javascript" >
class Person {
constructor(name,age){
this.name = name
this.age = age
}
speak(){
console.log(`我叫${this.name},我年龄是${this.age}`);
}
}
class Student extends Person {
constructor(name,age,grade){
super(name,age)
this.grade = grade
this.school = '小帽学堂'
}
speak(){
console.log(`我叫${this.name},我年龄是${this.age},我读的是${this.grade}年级`);
this.study()
}
study(){
console.log('我很努力的学习');
}
}
class Car {
constructor(name,price){
this.name = name
this.price = price
}
a = 1
wheel = 4
static demo = 100
}
const c1 = new Car('奔驰c63',199)
console.log(c1);
console.log(Car.demo);
</script>
</body>
</html>
2.3 类式组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2_类式组件</title>
</head>
<body>
<div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class MyComponent extends React.Component {
render(){
console.log('render中的this:',this);
return <h2>我是用类定义的组件(适用于【复杂组件】的定义)</h2>
}
}
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
</script>
</body>
</html>
3. 注意
- 组件名必须首字母大写
- 虚拟DOM元素只能有一个根元素
- 虚拟DOM元素必须有结束标签
4. 渲染类组件标签的基本流程
- React内部会创建组件实例对象
- 调用render()得到虚拟DOM, 并解析为真实DOM
- 插入到指定的页面元素内部
二、组件三大核心属性1: state
1. 效果
2. 复习
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>原生事件绑定</title>
</head>
<body>
<button id="btn1">按钮1</button>
<button id="btn2">按钮2</button>
<button onclick="demo()">按钮3</button>
<script type="text/javascript" >
const btn1 = document.getElementById('btn1')
btn1.addEventListener('click',()=>{
alert('按钮1被点击了')
})
const btn2 = document.getElementById('btn2')
btn2.onclick = ()=>{
alert('按钮2被点击了')
}
function demo(){
alert('按钮3被点击了')
}
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>类方法中的this指向</title>
</head>
<body>
<script type="text/javascript" >
class Person {
constructor(name,age){
this.name = name
this.age = age
}
study(){
console.log(this);
}
}
const p1 = new Person('tom',18)
p1.study()
const x = p1.study
x()
</script>
</body>
</html>
3. 理解
- state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
- 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
4. 强烈注意
- 组件中render方法中的this为组件实例对象
- 组件自定义的方法中this为undefined,如何解决?
- 强制绑定this: 通过函数对象的bind()
- 箭头函数
- 状态数据,不能直接修改或更新
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>state</title>
</head>
<body>
<div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Weather extends React.Component{
constructor(props){
console.log('constructor');
super(props)
this.state = {isHot:false,wind:'微风'}
this.changeWeather = this.changeWeather.bind(this)
}
render(){
console.log('render');
const {isHot,wind} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
}
changeWeather(){
console.log('changeWeather');
const isHot = this.state.isHot
this.setState({isHot:!isHot})
console.log(this);
}
}
ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>state简写方式</title>
</head>
<body>
<div id="test"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Weather extends React.Component{
state = {isHot:false,wind:'微风'}
render(){
const {isHot,wind} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
}
changeWeather = ()=>{
const isHot = this.state.isHot
this.setState({isHot:!isHot})
}
}
ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>
</body>
</html>
三、组件三大核心属性2: props
1. 效果
- 需求: 自定义用来显示一个人员信息的组件
- 姓名必须指定,且为字符串类型;
- 性别为字符串类型,如果性别没有指定,默认为男
- 年龄为字符串类型,且为数字类型,默认值为18
2. 理解
- 每个组件对象都会有props(properties的简写)属性
- 组件标签的所有属性都保存在props中
3. 作用
- 通过标签属性从组件外向组件内传递变化的数据
- 注意: 组件内部不要修改props数据
4. 编码操作
4.1 内部读取某个属性值
this.props.name
4.2 对props中的属性值进行类型限制和必要性限制
- 第一种方式(React v15.5 开始已弃用):
Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number
}
- 第二种方式(新):使用prop-types库进限制(需要引入prop-types库)
Person.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number
}
4.3 扩展属性: 将对象的所有属性通过props传递
<Person {...person}/>
4.4 默认属性值
Person.defaultProps = {
age: 18,
sex:'男'
}
4.5 组件类的构造函数
constructor(props){
super(props)
console.log(props)
}
5. 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>props基本使用</title>
</head>
<body>
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Person extends React.Component{
render(){
const {name,age,sex} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age+1}</li>
</ul>
)
}
}
ReactDOM.render(<Person name="jerry" age={19} sex="男"/>,document.getElementById('test1'))
ReactDOM.render(<Person name="tom" age={18} sex="女"/>,document.getElementById('test2'))
const p = {name:'老刘',age:18,sex:'女'}
ReactDOM.render(<Person {...p}/>,document.getElementById('test3'))
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>展开运算符</title>
</head>
<body>
<script type="text/javascript" >
let arr1 = [1,3,5,7,9]
let arr2 = [2,4,6,8,10]
console.log(...arr1);
let arr3 = [...arr1,...arr2]
function sum(...numbers){
return numbers.reduce((preValue,currentValue)=>{
return preValue + currentValue
})
}
console.log(sum(1,2,3,4));
let person = {name:'tom',age:18}
let person2 = {...person}
person.name = 'jerry'
console.log(person2);
console.log(person);
let person3 = {...person,name:'jack',address:"地球"}
console.log(person3);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对props进行限制</title>
</head>
<body>
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
class Person extends React.Component{
render(){
const {name,age,sex} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age+1}</li>
</ul>
)
}
}
Person.propTypes = {
name:PropTypes.string.isRequired,
sex:PropTypes.string,
age:PropTypes.number,
speak:PropTypes.func,
}
Person.defaultProps = {
sex:'男',
age:18
}
ReactDOM.render(<Person name={100} speak={speak}/>,document.getElementById('test1'))
ReactDOM.render(<Person name="tom" age={18} sex="女"/>,document.getElementById('test2'))
const p = {name:'老刘',age:18,sex:'女'}
ReactDOM.render(<Person {...p}/>,document.getElementById('test3'))
function speak(){
console.log('我说话了');
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>props的简写形式</title>
</head>
<body>
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
class Person extends React.Component{
constructor(props){
super(props)
console.log('constructor',this.props);
}
static propTypes = {
name:PropTypes.string.isRequired,
sex:PropTypes.string,
age:PropTypes.number,
}
static defaultProps = {
sex:'男',
age:18
}
render(){
const {name,age,sex} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age+1}</li>
</ul>
)
}
}
ReactDOM.render(<Person name="jerry"/>,document.getElementById('test1'))
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>函数组件使用props</title>
</head>
<body>
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
function Person (props){
const {name,age,sex} = props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
Person.propTypes = {
name:PropTypes.string.isRequired,
sex:PropTypes.string,
age:PropTypes.number,
}
Person.defaultProps = {
sex:'男',
age:18
}
ReactDOM.render(<Person name="jerry"/>,document.getElementById('test1'))
</script>
</body>
</html>