第二章 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 = namethis.age = age}speak(){console.log(`我叫${this.name},我年龄是${this.age}`);}}class Student extends Person {constructor(name,age,grade){super(name,age)this.grade = gradethis.school = '小帽学堂'}speak(){console.log(`我叫${this.name},我年龄是${this.age},我读的是${this.grade}年级`);this.study()}study(){console.log('我很努力的学习');}}class Car {constructor(name,price){this.name = namethis.price = price}a = 1wheel = 4static 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 = namethis.age = age}study(){console.log(this);}}const p1 = new Person('tom',18)p1.study() const x = p1.studyx()</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.statereturn <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>}changeWeather(){console.log('changeWeather');const isHot = this.state.isHotthis.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.statereturn <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>}changeWeather = ()=>{const isHot = this.state.isHotthis.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.propsreturn (<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.propsreturn (<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.propsreturn (<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} = propsreturn (<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>