1)state 是组件对象最重要的属性,值是对象(可以包含多个 key- value 的组合)
2)组件被称为 “状态机” ,通过更新组件的 state 来更新对应的页面显示(重新渲染组件)
1)组件中 render 方法中的 this 为组件实例对象
2)组件自定义方法中的 this 为 undefined ,如何解决?—
a、强制绑定 this ,通过函数对象中的 bind()
b、箭头函数
3)状态数据,不能直接修改或者更新。
1)例子 1
//1.创建组件
class Weather extends React.Component{
constructor(props){
super(props)
//初始化状态
this.state = {isHot:true}
}
render(){
//读取状态
console.log(this)
return <h1>今天天气很{this.state.isHot?"炎热":"凉爽"}</h1>
}
}
//2.渲染组件到页面
ReactDom.render(<Weather/>, document.getElementById("test"));
2)例子 2
//1.创建组件
class Weather extends React.Component{
constructor(props){
super(props)
//初始化状态
this.state = {isHot:true}
}
render(){
//读取状态
const {isHot} = this.state
return 今天天气很{isHot?"炎热":"凉爽"}
}
}
//2.渲染组件到页面
ReactDom.render( , document.getElementById("test"));
3)例子 3
//1.创建组件
class Weather extends React.Component{
constructor(props){
super(props)
//初始化状态
this.state = {isHot:true}
}
render(){
//读取状态
const {isHot} = this.state
//注意 : 1、react 中的绑定点击事件必须是onClick 不能是 onclick
//2、不能写带有括号的这种赋值 onClick={Demo()},只需要把 函数名称 给事件就好,react 会帮你调用
return <h1 onClick={demo}>今天天气很{isHot?"炎热":"凉爽"}</h1>
}
}
//2.渲染组件到页面
ReactDom.render(<Weather/>, document.getElementById("test"));
function demo(){
// 无法获取到 this
console.log("标题被点击了");
}
4)例子4
//1.创建组件
class Weather extends React.Component{
constructor(props){
super(props)
//初始化状态
this.state = {isHot:true}
}
render(){
//读取状态
const {isHot} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot?"炎热":"凉爽"}</h1>
}
changeWeather(){
// changeWeather 放在了哪里?---Weather 的原型对象上,供 Weather 的实例使用
// 通过 Weather 实例调用 changeWeather 时, changeWeather 中的 this 就是 Weather 实例
// 由于 changeWeather 是作为 onClick 的回调,所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式, 所以 changeWeather 中的 this 为 undefined
console.log(this);
}
}
//2.渲染组件到页面
ReactDom.render(<Weather/>, document.getElementById("test"));
5)例子5---->类中方法的 this 指向
//1.创建组件
class Weather extends React.Component{
//构造器调用几次?---->1次
constructor(props){
super(props)
//初始化状态
this.state = {isHot:true}
//解决 changeWeather 中的 this 指向问题
this.changeWeather = this.changeWeather.bind(this)
}
//render 调用几次?---->1+n 次,1 是初始化的那一次,n 是状态更新的次数
render(){
//读取状态
const {isHot} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot?"炎热":"凉爽"}</h1>
}
//changeWeather 调用几次?----> 点击几次就调用几次
changeWeather(){
// changeWeather 放在了哪里?---Weather 的原型对象上,供 Weather 的实例使用
// 通过 Weather 实例调用 changeWeather 时, changeWeather 中的 this 就是 Weather 实例
// 由于 changeWeather 是作为 onClick 的回调,所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式, 所以 changeWeather 中的 this 为 undefined
//console.log(this);
//获取原来的 isHot 的值,下面两行代码可以正常更改值,但是 react 的 状态不可以直接更改
const isHot = this.state.isHot;
//严重注意, 状态{state} 不可直接更改,下面这行就是直接更改
//this.state.isHot = !isHot; //这是错误的写法
console.log(this); // Weather 的实例对象
//严重注意:状态必须经过 setState 进行更改,且更新是一种合并,不是替换
this.setState({isHot:!isHot});
}
}
//2.渲染组件到页面
ReactDom.render(<Weather/>, document.getElementById("test"));
6)例子6—>state 的简写方式
//1.创建组件
class Weather extends React.Component{
//构造器调用几次?---->1次
constructor(props){
super(props)
this.state = {isHot:true}
this.changeWeather = this.changeWeather.bind(this)
}
//render 调用几次?---->1+n 次,1 是初始化的那一次,n 是状态更新的次数
render(){
//读取状态
const {isHot} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot?"炎热":"凉爽"}</h1>
}
//changeWeather 调用几次?----> 点击几次就调用几次
changeWeather(){
const isHot = this.state.isHot;
this.setState({isHot:!isHot});
}
}
//2.渲染组件到页面
ReactDom.render(<Weather/>, document.getElementById("test"));
1)每个组件对象都会有 props(properties 的简写)属性;
2)组件标签的所有属性都保存在 props 中
class Person extends React.Components {
render(){
return (
<ul>
<li>姓名:tome</li>
<li>性别:女</li>
<li>年龄:18</li>
</ul>
)
}
}
//2.渲染组件到页面
ReactDom.render(<Person/>, document.getElementById("test"));
class Person extends React.Components {
render(){
return (
<ul>
<li>姓名:{this.props.name}</li>
<li>性别:{this.props.gender}</li>
<li>年龄:{this.props.age}</li>
</ul>
)
}
}
//2.渲染组件到页面
ReactDom.render(<Person name="tome" gender="女" age="18"/>, document.getElementById("test"));
class Person extends React.Components {
render(){
const {name,gender,age} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{gender}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
//2.渲染组件到页面
ReactDom.render(<Person name="tome" gender="女" age="18"/>, document.getElementById("test"));
3)批量传入 props 值,需要所有的字段都是一样的
class Person extends React.Components {
render(){
const {name,gender,age} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{gender}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
//2.渲染组件到页面
const p = {name="tome", gender="女", age="18"}
ReactDom.render(<Person {...p}/>, document.getElementById("test"));
4) … 展开运算符
<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];//连接两个数组
console.log(arr3)
//在函数中使用
function sum (...numbers){
return numbers.reduce((preVal,curVal)>{
return preVal+curVal;
})
}
console.log(sum(1,2,3,4))
// ... 运算符不可以展开一个对象,但是在最外层加一个 花括号 可以复制一个对象(不会影响原对象---深克隆)
let person = {name:"tom",age:18}
let person2 = {...person}
person.name ="jerry";
console.log(person)
console.log(person2)
</script>
class Person extends React.Components {
render(){
const {name,gender,age} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{gender}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
//2.渲染组件到页面
//加规则---需要引入 prop-type 用于对组件标签属性进行(类型,必要性)限制
Person.propType = {
name:PropTypes.string // name name:PropTypes.string必须是字符串类型 ,name:PropTypes.string.isRequired 必传name 值。
}
Person.defaultProps = {
name:"大黄" //名字不传的时候 ,默认值
}
ReactDom.render(<Person name="tome" gender="女" age="18"/>, document.getElementById("test"));
class Person extends React.Components {
static propType = {
name:PropTypes.string // name name:PropTypes.string必须是字符串类型 ,name:PropTypes.string.isRequired 必传name 值。
}
static defaultProps = {
name:"大黄" //名字不传的时候 ,默认值
}
render(){
const {name,gender,age} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{gender}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
ReactDom.render(<Person name="tome" gender="女" age="18"/>, document.getElementById("test"));
1)通过标签属性从组件外 向组件内传递变化的数据
2)注意:组件内部不要修改 props 数据
组件内中的标签可以定义 ref 属性来标识自己
1)字符串形式的 ref(最新的react 不推荐使用了,有可能是会被移除)
<script type="text/babel">
//创建组件
class Demo extends React.Component{
showData=()=>{
const {input1}=this.refs;
alert(input1.value)
}
showData2=()=>{
const {input2}=this.refs;
alert(input2.value)
}
render(){
return {
<div>
<input ref='input1' type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input ref='input2' onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
</div>
}
}
}
ReactDom.render(<Demo/>, document.getElementById("test"));
</script>
2)回调函数形式的ref
<input ref=(currentNode)=>{this.input2 = currentNode} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
<script type="text/babel">
//创建组件
class Demo extends React.Component{
showData=()=>{
alert(this.input1.value)
}
showData2=()=>{
alert(this.input2.value)
}
render(){
return {
<div>
<input ref=(currentNode)=>{this.input1 = currentNode} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input ref=(currentNode)=>{this.input2 = currentNode} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
</div>
}
}
}
ReactDom.render(<Demo/>, document.getElementById("test"));
</script>
回调形式的ref 中回调的使用次数
关于回调 refs 的说明: 如果 ref 回调函数是 以内联函数的方式定义的,在更新过程中她会被执行两次,第一次是传入参数 null ,然后第二次会传入参数 DOM 元素,这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的,通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要的。
<script type="text/babel">
//创建组件
class Demo extends React.Component{
state = {isHot:true}
changeWeather()=>{
const {isHot} = this.state;
//更新状态
this.setState({isHot:!isHot})
}
showInfo=()=>{
alert(this.input1.value)
}
render(){
const {isHot} = this.state;
return {
<div>
<h2>今天天气很{isHot?'炎热':'凉爽'}</h2>
<button onClick={this.changeWeather}>点我切换天气</button>
<input ref=(currentNode)=>{this.input1 = currentNode;console.log("@",currentNode)} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showInfo}>点我提示输入的数据</button>
</div>
}
}
}
ReactDom.render(<Demo/>, document.getElementById("test"));
</script>
render 中 jsx 的 注释写法:
{/**/}
<script type="text/babel">
//创建组件
class Demo extends React.Component{
/*
React.createRef 调用后可以返回一个容器,该容器可以存储 被 ref 所标识的节点,官方最推荐的一种写法
*/
myRef = React.createRef()
showData=()=>{
alert(this.input1.value)
}
showData2=()=>{
alert(this.input2.value)
}
render(){
return {
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input ref=(currentNode)=>{this.input2 = currentNode} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
</div>
}
}
}
ReactDom.render(<Demo/>, document.getElementById("test"));
</script>
<script type="text/babel">
//创建组件
class Demo extends React.Component{
/*
React.createRef 调用后可以返回一个容器,该容器可以存储 被 ref 所标识的节点,官方最推荐的一种写法
*/
myRef = React.createRef()
showData=()=>{
alert(this.input1.value)
}
showData2=()=>{
alert(this.input2.value)
}
render(){
return {
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input ref=(currentNode)=>{this.input2 = currentNode} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
</div>
}
}
}
ReactDom.render(<Demo/>, document.getElementById("test"));
</script>