1.state描述:
1.state是组件对象最重要的属性,值是对象,(可以包含多个,key-value的组合)
2.组件被称为“状态机”,通过更新组件的state来更新对应的页面显示(重新渲染组件)
3.严重注意,状态必须通过setState更新,且更新是一种合并,不是覆盖
1.2.state完整写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom用于支持react操作dom -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Weather extends React.Component{
// 构造器调用几次———— 有一个实例,只调用一次
constructor(props){
console.log('constructor');
super(props);
// 初始化状态
this.state = {
isHot:true,
wind:'微风'
};
// 解决changeWeather 中this的指向问题
this.changeWeather = this.changeWeather.bind(this);
}
// render调用几次? —— 1+n次 1是初始化的那次,n状态更新的次数
render(){
// 读取状态
console.log(this);
return <h1 onClick={this.changeWeather}>今天天气很{this.state.isHot?'炎热':'凉爽'},{this.state.wind} </h1>
}
// changeWeather调用几次? —— 点几次调用几次,点几次调用几次
changeWeather(){
// changeWeather放在哪里,————Weather的原型对象上
// 由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
// 类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
console.log(this);
// 获取原来的isHot值
const isHot = this.state.isHot;
// 严重注意状态(state)不可直接更改,下面就是直接更改,需要借助内置api进行更改
// this.state.isHot = !isHot; //错误写法
// console.log(this.state.isHot);
// 严重注意,状态必须通过setState更新,切更新是一种合并,不是覆盖
this.setState({isHot:!isHot})
}
}
// 2.渲染组件到页面
ReactDOM.render(<Weather/>,document.getElementById('test'));
</script>
</body>
</html>
点击事件有三种调用方式,react更推荐使用第三种,
<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>
1.3 state简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom用于支持react操作dom -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Weather extends React.Component{
// constructor(props){
// super(props);
// // this.state = {
// // isHot:true,
// // wind:'微风'
// // };
// // this.changeWeather = this.changeWeather.bind(this);
// }
// 初始化状态
state = { isHot:true, wind:'微风'};
render(){
return <h1 onClick={this.changeWeather}>今天天气很{this.state.isHot?'炎热':'凉爽'},{this.state.wind} </h1>
}
// 自定义方法————要用赋值语句+箭头函数
changeWeather = ()=>{
const isHot = this.state.isHot;
this.setState({isHot:!isHot})
}
}
ReactDOM.render(<Weather/>,document.getElementById('test'));
</script>
</body>
</html>
2.1对props进行限制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<!-- 引入react核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持 react操作dom-->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为 js-->
<script src="../js/babel.min.js"></script>
<!-- 引入prop-Types,用于对组件标签属性进行限制 -->
<script src="../js/prop-types.js"></script>
<script type="text/babel">
// 1.创建组件
class Person extends React.Component{
render(){
console.log(this);
// props是只读的
const {name,age,sex} = this.props;
// this.props.name='jack'
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age+1}</li>
</ul>
)
}
}
// 对标签属性进行类型,必要性的限制
Person.propTypes = {
name:PropTypes.string.isRequired, //限制name必传,且为字符串
sex:PropTypes.string, //限制sex为字符串
age:PropTypes.number, //限制age为数值
speak:PropTypes.func, //限制speak为函数
}
// 指定默认标签属性值
Person.defaultProps={
sex:'男', //sex的默认值为男
age:0 //age默认值为18
}
// 2.渲染组件到页面
ReactDOM.render(<Person name="tom" speak={speak} />,document.getElementById('test1'));
ReactDOM.render(<Person name="jerry" age={20} sex="男"/>,document.getElementById('test2'));
const p ={name:'老刘',age:18,sex:'女'};
// ReactDOM.render(<Person name={p.name} age={p.age} sex={p.sex}/>,document.getElementById('test3'));
ReactDOM.render(<Person {...p}/>,document.getElementById('test3'));
function speak(){
console.log('我说话了');
}
</script>
</body>
</html>
2.2props对限制的简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<!-- 引入react核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持 react操作dom-->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为 js-->
<script src="../js/babel.min.js"></script>
<!-- 引入prop-Types,用于对组件标签属性进行限制 -->
<script src="../js/prop-types.js"></script>
<script type="text/babel">
// 1.创建组件
class Person extends React.Component{
constructor(props){
// 构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
super();
console.log('constructor',this.props);
}
// 对标签属性进行限制,必要性的限制
static propTypes = {
name:PropTypes.string.isRequired, //限制name必传,且为字符串
sex:PropTypes.string, //限制sex为字符串
age:PropTypes.number, //限制age为数值
speak:PropTypes.func, //限制speak为函数
}
// 指定默认标签属性值
static defaultProps={
sex:'男', //sex的默认值为男
age:0 //age默认值为18
}
render(){
console.log(this);
// props是只读的
const {name,age,sex} = this.props;
// this.props.name='jack' //此行代码会报错,因为props是只读的
return (
<ul >
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age+1}</li>
</ul>
)
}
}
// 2.渲染组件到页面
ReactDOM.render(<Person name="tom" speak={speak} />,document.getElementById('test1'));
ReactDOM.render(<Person name="jerry" age={20} sex="男"/>,document.getElementById('test2'));
const p ={name:'老刘',age:18,sex:'女'};
// ReactDOM.render(<Person name={p.name} age={p.age} sex={p.sex}/>,document.getElementById('test3'));
ReactDOM.render(<Person {...p}/>,document.getElementById('test3'));
function speak(){
console.log('我说话了');
}
</script>
</body>
</html>
2.3函数式组件使用props
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持 react操作dom-->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为 js-->
<script src="../js/babel.min.js"></script>
<!-- 引入prop-Types,用于对组件标签属性进行限制 -->
<script src="../js/prop-types.js"></script>
<script type="text/babel">
// 1.创建组件
function Person(props){
console.log(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为数值
speak:PropTypes.func, //限制speak为函数
}
// 指定默认标签属性值
Person.defaultProps={
sex:'男', //sex的默认值为男
age:0 //age默认值为0
}
// 2.渲染组件到页面
ReactDOM.render(<Person name="jerry" sex="女" />,document.getElementById('test'));
</script>
</body>
</html>
3.1字符串形式的refs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持 react操作dom-->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为 js-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Demo extends React.Component{
render(){
return(
<div>
<input ref="input1" type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧数据</button>
<input ref="input2" onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
)
}
// 展示左侧输入框的数据
showData = ()=>{
// 函数体
console.log(this);
const {input1} =this.refs;
alert(input1.value);
}
// 展示右侧输入框的数据
showData2 = ()=>{
const {input2} = this.refs;
alert(input2.value);
}
}
// 2.渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'));
</script>
</body>
</html>
3.2回调函数形式的ref
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持 react操作dom-->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为 js-->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 1.创建组件
class Demo extends React.Component{
state = {isHot:true};
render(){
const {isHot} = this.state
return(
<div>
<h1 >今天天气很{isHot===true?'凉爽':'炎热'} </h1>
{/* <input ref={(cNode)=>{this.input1=cNode;console.log('#',cNode)}} type="text" placeholder="点击按钮提示数据"/> */}
<input ref={this.saveInput} type="text" placeholder="点击按钮提示数据" />
<button onClick={this.showData}>点我提示数据</button>
<button onClick={this.changeData}>点我切换天气</button>
</div>
)
}
saveInput = (cNode)=>{
this.input1 = cNode;
console.log('@',cNode);
}
changeData = ()=>{
const {isHot} = this.state
this.setState({isHot:!isHot});
}
// 展示左侧输入框的数据
showData = ()=>{
// 函数体
const {input1} =this;
alert(input1.value);
}
}
// 2.渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'));
</script>
</body>
</html>
3.3回调ref执行的次数问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 创建组件
class Demo extends React.Component{
state= {isHot:false}
render(){
return(
<div>
<h2>今天天气很{this.state.isHot?'炎热':'凉爽'}</h2>
<input type="text" ref={(currentNode)=>{this.input1=currentNode;console.log('#',currentNode)}} />
<button onClick={this.showInfo}>点我提示输入的数据</button>
<button onClick={this.changeWeather}>点我改变天气</button>
</div>
)
}
showInfo = ()=>{
const {input1} = this;
console.log(input1);
alert(input1.value);
}
changeWeather = ()=>{
const {isHot}= this.state;
console.log(this);
this.setState({isHot:!isHot});
}
}
// 渲染组件到页面
ReactDOM.render(<Demo/>, document.getElementById('test'));
</script>
</body>
</html>
ref先执行一次空,然后再得到真实的dom,这是因为react每次运行完都清空了ref
3.4createRef
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 创建容器 -->
<div id="test"></div>
<!-- 引入react基础库 -->
<script src="../js/react.development.js"></script>
<!-- 引入react-dom库 用于支持react操作dom -->
<script src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="../js/babel.min.js"></script>
<script type="text/babel">
// 创建组件
class Demo extends React.Component{
myRef = React.createRef();
myRef2 = React.createRef();
// react.createRef调用后可以返回一个容器,该容器可以存储被ref标记的节点
// 该容器是ref专用
render(){
return(
<div>
<input ref={this.myRef} type="text" placeholder="点击时触发"/>
<button onClick={this.showData}>点我提示左侧数据</button>
<input ref={this.myRef2} onBlur={this.showData2} type="text" placeholder="鼠标离开时触发" />
</div>
)
}
showData = ()=>{
alert(this.myRef.current.value);
}
showData2 = ()=>{
alert(this.myRef2.current.value);
}
}
// 渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'));
</script>
</body>
</html>