1. state
<div id="test"></div>
<script type="text/babel">
//1.创建组件
class Weather extends React.Component {
//构造器调用几次? ———— 1次
constructor(props) {
console.log('constructor');
super(props);
//初始化状态
this.state = { isHot: false, wind: '微风' };
//解决changeWeather中this指向问题
this.changeWeather = this.changeWeather.bind(this);
}
//render调用几次? ———— 1+n次 1是初始化的那次 n是状态更新的次数
render() {
console.log('render');
//读取状态
const { isHot, wind } = this.state;
return (
<h1 onClick={this.changeWeather}>
今天天气很{isHot ? '炎热' : '凉爽'},{wind}
</h1>
);
}
//changeWeather调用几次? ———— 点几次调几次
changeWeather() {
//changeWeather放在哪里? ———— Weather的原型对象上,供实例使用
//由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
//获取原来的isHot值
const isHot = this.state.isHot;
//状态(state)不可直接更改
//状态必须通过setState进行更新,且更新是一种合并,不是替换。
this.setState({ isHot: !isHot });
}
}
//2.渲染组件到页面
ReactDOM.render(<Weather />, document.getElementById('test'));
</script>
简写:
<div id="test"></div>
<script type="text/babel">
class Weather extends React.Component {
// 初始化状态
state = { isHot: false, wind: '微风' };
render() {
return (
<h1 onClick={this.changeWeather}>
天气{this.state.isHot ? '炎热' : '凉爽'},{this.state.wind}
</h1>
);
}
// 自定义方法:赋值语句+箭头函数
changeWeather = () => {
const isHot = this.state.isHot;
this.setState({ isHot: !isHot });
// console.log(this);
};
}
ReactDOM.render(<Weather />, document.getElementById('test'));
</script>
state
是组件对象最重要的属性,值是对象(可以包含多个key-value
的组合)- 组件自定义的方法中
this
为undefined
,解决:- 强制绑定
this
:通过函数对象的bind()
- 箭头函数
- 强制绑定
- 状态数据,不能直接修改或更新,要使用
setState()
方法
2. props
<div id="test"></div>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
//创建组件
class Person extends React.Component {
constructor(props) {
//构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
super(props);
console.log('constructor', this.props);
}
//对标签属性进行类型、必要性的限制
static propTypes = {
name: PropTypes.string.isRequired, //限制name必传,且为字符串
sex: PropTypes.string,
age: PropTypes.number,
};
//指定默认标签属性值
static defaultProps = {
sex: '男',
age: 18,
};
render() {
// console.log(this);
const { name, age, sex } = this.props;
//props是只读的
//this.props.name = 'jack' //此行代码会报错,因为props是只读的
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age + 1}</li>
</ul>
);
}
}
const p1 = { name: 'Tom', sex: '女', age: 20 };
//渲染组件到页面
ReactDOM.render(<Person {...p1} />, document.getElementById('test'));
</script>
- 每个组件对象都会有
props
属性 - 组件标签的所有属性都保存在
props
中 - 通过标签属性从组件外向组件内传递变化的数据
函数式组件使用props
:
<div id="test"></div>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<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, //限制name必传,且为字符串
sex: PropTypes.string, //限制sex为字符串
age: PropTypes.number, //限制age为数值
};
//指定默认标签属性值
Person.defaultProps = {
sex: '男', //sex默认值为男
age: 18, //age默认值为18
};
const p1 = { name: 'Tom', sex: '女', age: 20 };
//渲染组件到页面
ReactDOM.render(<Person {...p1} />, document.getElementById('test'));
</script>
3. refs
不要过度使用ref
:发生事件的事件源和要操作的元素是同一个时,可以不使用ref
。
通过onXxx
属性指定事件处理函数:
- React使用的是自定义事件,,而不是使用的原生DOM事件——兼容性
- React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)——高效
1. 字符串形式
<div id="test"></div>
<script type="text/babel">
//创建组件
class Demo extends React.Component {
//打印左侧输入框的数据
showData = () => {
console.log(this);
const { input1 } = this.refs;
console.log(input1.value);
};
//打印右侧输入框的数据
showData2 = () => {
const { input2 } = this.refs;
console.log(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. 回调函数形式
<div id="test"></div>
<script type="text/babel">
//创建组件
class Demo extends React.Component {
//展示左侧输入框的数据
showData = () => {
const { input1 } = this;
alert(input1.value);
};
//展示右侧输入框的数据
showData2 = () => {
const { input2 } = this;
alert(input2.value);
};
render() {
return (
<div>
<input ref={currentNode => (this.input1 = currentNode)} type="text" placeholder="点击按钮提示数据" />
<button onClick={this.showData}>点我提示左侧的数据</button>
<input
onBlur={this.showData2}
ref={currentNode => (this.input2 = currentNode)}
type="text"
placeholder="失去焦点提示数据"
/>
</div>
);
}
}
//渲染组件到页面
ReactDOM.render(<Demo a="1" b="2" />, document.getElementById('test'));
</script>
3. createRef
创建ref
容器
<div id="test"></div>
<script type="text/babel">
//创建组件
class Demo extends React.Component {
myRef = React.createRef();
myRef2 = React.createRef();
//展示左侧输入框的数据
showData = () => {
console.log(this.myRef.current.value);
};
//展示右侧输入框的数据
showData2 = () => {
console.log(this.myRef2.current.value);
};
render() {
return (
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />
<button onClick={this.showData}>点我提示左侧的数据</button>
<input onBlur={this.showData2} ref={this.myRef2} type="text" placeholder="失去焦点提示数据" />
</div>
);
}
}
//渲染组件到页面
ReactDOM.render(<Demo a="1" b="2" />, document.getElementById('test'));
</script>
React.createRef()
调用后可以返回一个容器,该容器可以存储被ref
所标识的节点,该容器只能存一个节点