【React】第三部分 组件实例的三大核心属性
文章目录
3. 组件实例的三大核心属性
3.1 state
- state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
- 组件被称为”状态机”, 通过更新组件的state来更新对应的页面显示(重新渲染组件)
- 通过
this.setState()去修改数据
下面就举一个简单的例子来认识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>state</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="box"></div>
<!-- 下面需要按顺序进行引入 -->
<!-- 引入React核心库 -->
<script src="./react.development.js" type="text/javascript"></script>
<!-- 引入react-dom, 用来支持react去操作dom -->
<script src="./react-dom.development.js" type="text/javascript"></script>
<!-- 引入babel, 用来将jsx转化为js -->
<script src="./babel.min.js" type="text/javascript"></script>
<!-- 这里需要注意将type写成 text/babel-->
<script type="text/babel" >
class Weather extends React.Component{
constructor(props){
// 这行代码先不管,这里必须要写,后面会说
super(props)
// 初始化一个数据
this.state = {isHot:true}
// 解决changeWeather函数中this为undefined
this.changeWeather = this.changeWeather.bind(this)
// 解释一下上述的代码
/*
左侧this.changeWeather表示的是:在Weather的实例对象上添加一个属性为changeWeather
右侧this.changeWeather是去找这个函数,自身没有去原型对象上找,
找到了使用bind返回一个新的函数,并且修改this的指向
最后把这个函数赋值给实例对象上的changeWeather
*/
}
render(){
const {isHot} = this.state
return(
// 此时这里的this.changeWeather找的是实例对象上的,而不是原型对象上的
<h1 onClick={this.changeWeather}>今天天气很{isHot ? '热' : '冷'}</h1>
)
}
// 定义一个函数用来切换天气状态
changeWeather(){
/*
这里有个坑,此处的this为undefined,为什么呢?
分析:
changeWeather函数它是放在Weather原型对象上,供它的实例对象使用
由于在render函数中changeWeather函数是作为onClick的回调,是直接调用
在类中的方法默认是开启局部严格模式.所以changeWeather函数中的this为undefined
这里举个例子大家就更明白了
class demo {
say(){
console.log(this);
}
}
const d = new demo()
d.say() // 此时this指向的该类的实例对象
// 下面我做了一个操作
const x = d.say
x() // 此时this为undefined
根据上述同理可得为什么changeWeather中this的指向为undefined
*/
console.log(this);
// 需要调用setState对state中的数据进行修改,不能直接修改
this.setState({isHot:!this.state.isHot})
}
}
ReactDOM.render(<Weather/>,document.getElementById('box'))
</script>
</body>
</html>
注意点:
-
组件中render方法中的this也指向组件实例对象(也就是类的实例对象)
-
constructor构造器函数中的this也指向组件实例对象(也就是类的实例对象)
-
自定义组件中方法的this为undefined的解决办法?
(1) 强制绑定this,通过函数对象的bind()
(2) 箭头函数
-
状态数据不能够直接去修改或者更新
3.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>05-简化state写法</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="box"></div>
<!-- 下面需要按顺序进行引入 -->
<!-- 引入React核心库 -->
<script src="./react.development.js" type="text/javascript"></script>
<!-- 引入react-dom, 用来支持react去操作dom -->
<script src="./react-dom.development.js" type="text/javascript"></script>
<!-- 引入babel, 用来将jsx转化为js -->
<script src="./babel.min.js" type="text/javascript"></script>
<!-- 这里需要注意将type写成 text/babel-->
<script type="text/babel" >
class Weather extends React.Component{
render(){
return (
<h1 onClick={this.changeWeather}>今天天气很{this.state.isHot?'热':'冷'}</h1>
)
}
// 在类中可以写构造器函数,方法,也可以写赋值语句,但是不能写变量例如:let a = xx
// 在类中写赋值语句它会绑定在该类的实例对象上
// 如果是写自定义函数它会在该类的原型对象上,供实例对象使用,二者要区分
state = {isHot:true}
// 自定义函数 --- 这里需要使用赋值语句配合箭头函数
// 赋值语句将其绑在实例对象上,箭头函数用于改变this的指向
changeWeather = ()=>{
console.log(this);
// setState函数是合并数据而不是替换原有的数据
this.setState({isHot:!this.state.isHot})
}
}
ReactDOM.render(<Weather/>,document.getElementById('box'))
</script>
</body>
</html>
3.3 props
-
每个组件对象都会有props属性
-
组件标签的所有属性都会保存在props中
-
通过标签属性从组件外向组件内传递变化的数据
-
注意:组件内部不要修改props数据
-
读取传入的数据
this.props.xxx
<!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>props</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="box1"></div>
<div id="box2"></div>
<div id="box3"></div>
<!-- 下面需要按顺序进行引入 -->
<!-- 引入React核心库 -->
<script src="./react.development.js" type="text/javascript"></script>
<!-- 引入react-dom, 用来支持react去操作dom -->
<script src="./react-dom.development.js" type="text/javascript"></script>
<!-- 引入babel, 用来将jsx转化为js -->
<script src="./babel.min.js" type="text/javascript"></script>
<!-- 引入prop-types, 用来去限制props的类型 -->
<script src="./prop-types.js" type="text/javascript"></script>
<!-- 这里需要注意将type写成 text/babel-->
<script type="text/babel">
class Demo extends React.Component{
render(){
// 利用props取到传入的参数
let {name,age,gender} = this.props
return(
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
<li>性别:{gender}</li>
</ul>
)
}
}
// 指定标签属性的数据类型
Demo.propTypes = {
name:PropTypes.string.isRequired,
age:PropTypes.number,
gender:PropTypes.string,
speak:PropTypes.func
}
// 指定默认值
Demo.defaultProps = {
gender:'male',
age:18
}
// 在标签中写入即可传参
ReactDOM.render(<Demo name= 'Jack' age={18} gender="male" />,document.getElementById('box1'))
ReactDOM.render(<Demo name="Mark" age={35} gender="female" />,document.getElementById('box2'))
// 批量传递参数
let people = {name:'Jane',age:35,gender:"male"}
// 这是react的一个语法糖,否则按照扩展运算符是不能够去展开对象的
ReactDOM.render(<Demo {...people}/>,document.getElementById('box3'))
</script>
</body>
</html>
3.4 简化props
将在class类外添加的属性移到类中
利用static
<!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>props</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="box1"></div>
<div id="box2"></div>
<div id="box3"></div>
<!-- 下面需要按顺序进行引入 -->
<!-- 引入React核心库 -->
<script src="./react.development.js" type="text/javascript"></script>
<!-- 引入react-dom, 用来支持react去操作dom -->
<script src="./react-dom.development.js" type="text/javascript"></script>
<!-- 引入babel, 用来将jsx转化为js -->
<script src="./babel.min.js" type="text/javascript"></script>
<!-- 引入prop-types, 用来去限制props的类型 -->
<script src="./prop-types.js" type="text/javascript"></script>
<!-- 这里需要注意将type写成 text/babel-->
<script type="text/babel">
class Demo extends React.Component{
render(){
// 利用props取到传入的参数
let {name,age,gender} = this.props
return(
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
<li>性别:{gender}</li>
</ul>
)
}
// 根据上述所说的props,那么其实就是在给类身上加属性
// 那么就可以用到static去修饰
static propTypes = {
name:PropTypes.string.isRequired,
age:PropTypes.number,
gender:PropTypes.string,
speak:PropTypes.func
}
// 指定默认值
static defaultProps = {
gender:'male',
age:18
}
}
// 在标签中写入即可传参
ReactDOM.render(<Demo name= 'Jack' age={18} gender="male" />,document.getElementById('box1'))
ReactDOM.render(<Demo name="Mark" age={35} gender="female" />,document.getElementById('box2'))
// 批量传递参数
let people = {name:'Jane',age:35,gender:"male"}
// 这是react的一个语法糖,否则按照扩展运算符是不能够去展开对象的
ReactDOM.render(<Demo {...people}/>,document.getElementById('box3'))
</script>
</body>
</html>
3.5 在函数式组件子中使用props
在函数式组件中它本身是没有自己this,按理说是用不了这个三大核心属性,但是由于函数的特性可以传参数,所以可以使用props
它会将标签传入的参数收集成一个对象交给props
// 在函数式组件中使用props
function Test (props){
return (
<ul>
<li>姓名:{props.name}</li>
<li>年龄:{props.age}</li>
<li>性别:{props.gender}</li>
</ul>
)
}
// 指定标签属性的数据类型
Test.propTypes = {
name:PropTypes.string.isRequired,
age:PropTypes.number,
gender:PropTypes.string,
speak:PropTypes.func
}
// 指定默认值
Test.defaultProps = {
gender:'male',
age:18
}
ReactDOM.render(<Test name="LiLi" age={23} gender="male"/>,document.getElementById('box4'))
3.6 refs
在组件内可以通过ref属性来标识自己
第一种形式 – 字符串形式的ref
这种形式是最简单的,但是官方文档说以后可能会废除这种形式
class Demo extends React.Component{
render(){
return (
<div>
<input type="text" ref="inp"/>
<button onClick={this.testEvent}>点击我弹窗</button>
</div>
)
}
testEvent = ()=>{
// 通过实例对象上的refs来获取ref所标识的节点
alert(this.refs.inp.value);
}
}
ReactDOM.render(<Demo/>,document.getElementById('box'))
第二种形式 – 回调函数形式的ref
如下代码,回调函数中的参数c表示是当前节点,this.inp = c
把当前的节点放在实例对象上
class Demo extends React.Component{
render(){
return (
<div>
<input type="text" ref={c =>this.inp = c}/>
<button onClick={this.testEvent}>点击我弹窗</button>
</div>
)
}
testEvent = ()=>{
// 到实例对象身上找
alert(this.inp.value);
}
}
ReactDOM.render(<Demo/>,document.getElementById('box'))
第三种形式 – createRef创建ref容器
需要注意:
- 一个容器只对应一个节点
- 这种形式是官方最为推荐的写法
class Demo extends React.Component{
// 创建容器
box1 = React.createRef()
box2 = React.createRef()
render(){
return (
<div>
<input type="text" ref={this.box1}/>
<button onClick={this.testEvent} ref={this.box2}>点击我弹窗</button>
</div>
)
}
testEvent = ()=>{
// 在这里需要注意的是这个容器存储的结构是 {current:xxx}
alert(this.box1.current.value);
}
}
ReactDOM.render(<Demo/>,document.getElementById('box'))
总结
以上就是今天要讲的内容,希望对大家有所帮助!!!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/82870.html