1、state
(1)state是组件对象最重要的属性,值是对象(可以包含多个key-value的组合)
(2)组件被称为“状态机”,通常更新组件的state来更新对应的页面显示(重新渲染组件)
注意!!!
(1)组件中render方法中的this为组件实例对象
(2)组件自定义的方法中this为undefined,如何解决?
a.强制绑定this:通过函数对象的bind()
b.箭头函数
(3) 状态数据,不能直接修改或更新
案例demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 1.引入react的核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2.渲染组件到页面 -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3.引入 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
//1.创建组件
class Weather extends React.Component {
//构造器调用几次?—— 1次
constructor(props) {
super(props)
this.state = { isHot: false } //初始化状态
//解决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的原型对象上,供实例使用
//由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
//类中的的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
//获取原来的isHot值
const isHot = this.state.isHot
//注意:状态在(state)不可直接更改,下面这行就是直接更改!!!!
// this.state.isHot = !isHot
//要借助一个内置的API去更改,状态必须通过setState进行更新,且更新是一种合并,不是替换
this.setState({ isHot: !isHot })
}
}
//2.渲染组件到页面
ReactDOM.render(<Weather />, document.getElementById("test"))
</script>
</body>
</html>
demo效果
点击切换天气状态
精简版代码
使用箭头函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 1.引入react的核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2.渲染组件到页面 -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3.引入 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
//1.创建组件
class Weather extends React.Component {
state = { isHot: false }
render() {
const { isHot } = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}</h1> //读取状态进行展示
}
//自动以方法 —— 要用赋值语句的形式 + 箭头函数
changeWeather = () => {
const isHot = this.state.isHot
this.setState({ isHot: !isHot })
}
}
//2.渲染组件到页面
ReactDOM.render(<Weather />, document.getElementById("test"))
</script>
</body>
</html>
2、props
注意props是只读的!
案例demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 1.引入react的核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2.渲染组件到页面 -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3.引入 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
//1.创建组件
class Person extends React.Component {
render() {
console.log(this);
const { name, age, gender } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{gender}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
//对标签属性进行类型限制、必要性的限制
Person.propTypes = {
name: PropTypes.string.isRequired, //限制name必传,且为字符串
gender: PropTypes.string, //限制gender为字符串
age: PropTypes.number,//限制age为数值
speak: PropTypes.func,//限制speak为函数
}
//指定默认标签属性值
Person.defaultProps = {
gender: '男', //性别默认值为男
age: 18, //年龄age默认值为18
}
function speak() {
console.log("xxx说话了!")
}
//2.渲染组件到页面
const p = { name: "Alice", age: 18, gender: "女" }
ReactDOM.render(<Person {...p} />, document.getElementById("test"))
</script>
</body>
</html>
props简写方式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 1.引入react的核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2.渲染组件到页面 -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3.引入 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
//1.创建组件
class Person extends React.Component {
//对标签属性进行类型限制、必要性的限制
static propTypes = {
name: PropTypes.string.isRequired, //限制name必传,且为字符串
gender: PropTypes.string, //限制gender为字符串
age: PropTypes.number,//限制age为数值
speak: PropTypes.func,//限制speak为函数
}
//指定默认标签属性值
static defaultProps = {
gender: '男', //性别默认值为男
age: 18, //年龄age默认值为18
}
render() {
console.log(this);
const { name, age, gender } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{gender}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
function speak() {
console.log("xxx说话了!")
}
//2.渲染组件到页面
const p = { name: "Alice", age: 18, gender: "女" }
ReactDOM.render(<Person {...p} />, document.getElementById("test"))
</script>
</body>
</html>
函数式组件使用props
(1)每个组件对象都会有props(properties的简写)属性
(2)组件标签的所有属性都保存在props中
作用:
- 通过标签属性从组件外向组件诶传递变化的数据
- 注意:组件内部不要修改props数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 1.引入react的核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 2.渲染组件到页面 -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 3.引入 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
//1.创建组件
function Person(props) {
console.log(props)
const { name, age, gender } = props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{gender}</li>
<li>年龄:{age}</li>
</ul>
)
}
//对标签属性进行类型限制、必要性的限制
Person.propTypes = {
name: PropTypes.string.isRequired, //限制name必传,且为字符串
gender: PropTypes.string, //限制gender为字符串
age: PropTypes.number,//限制age为数值
speak: PropTypes.func,//限制speak为函数
}
//指定默认标签属性值
Person.defaultProps = {
gender: '男', //性别默认值为男
age: 18, //年龄age默认值为18
}
//2.渲染组件到页面
const p = { name: "Alice", age: 18, gender: "女" }
ReactDOM.render(<Person {...p} />, document.getElementById("test"))
</script>
</body>
</html>
3、refs
3.1 字符串形式的ref
字符串形式的ref不推荐使用了~
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>1_字符串形式的ref</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 1.引入react的核心库 -->
<script type="text/javascript" src="../../js/react.development.js"></script>
<!-- 2.渲染组件到页面 -->
<script type="text/javascript" src="../../js/react-dom.development.js"></script>
<!-- 3.引入 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../../js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../../js/prop-types.js"></script>
<script type="text/babel">
//1.创建组件
class Demo extends React.Component {
//展示左侧输入框的数据
showData = () => {
console.log(this.refs.input1)
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>
)
}
}
//2.渲染组件到页面
ReactDOM.render(<Demo />, document.getElementById('test'))
</script>
</body>
</html>
3.2 回调函数形式的ref
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2_回调函数形式的ref</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 1.引入react的核心库 -->
<script type="text/javascript" src="../../js/react.development.js"></script>
<!-- 2.渲染组件到页面 -->
<script type="text/javascript" src="../../js/react-dom.development.js"></script>
<!-- 3.引入 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../../js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../../js/prop-types.js"></script>
<script type="text/babel">
//1.创建组件
class Demo extends React.Component {
//展示左侧输入框的数据
showData = () => {
// console.log(this.refs.input1)
const { input1 } = this
alert(input1.value)
}
//展示右侧输入框的数据
showData2 = () => {
const { input2 } = this
alert(input2.value)
}
render() {
return (
<div>
<input ref={(a) => { this.input1 = a }} type="text" placeholder="点击按钮提示数据" />
<button onClick={this.showData}>点我提示左侧的数据</button>
<input ref={(a) => { this.input2 = a }} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
)
}
}
//2.渲染组件到页面
ReactDOM.render(<Demo />, document.getElementById('test'))
</script>
</body>
</html>
3.3 createRef
缺点:需要创建多个ref,例如以下代码中的myRef和myRef2(“专人专用”)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3_createRef</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="test"></div>
<!-- 1.引入react的核心库 -->
<script type="text/javascript" src="../../js/react.development.js"></script>
<!-- 2.渲染组件到页面 -->
<script type="text/javascript" src="../../js/react-dom.development.js"></script>
<!-- 3.引入 babel 用于将 jsx 转为 js -->
<script type="text/javascript" src="../../js/babel.min.js"></script>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../../js/prop-types.js"></script>
<script type="text/babel">
//1.创建组件
class Demo extends React.Component {
/*React.createRef调用后可以返回一个容器,该容器可以存储被ref所表示的节点*/
myRef = React.createRef()
myRef2 = React.createRef()
//展示左侧输入框的数据
showData = () => {
alert(this.myRef.current.value)
}
//展示右侧输入框的数据
showData2 = () => {
alert(this.myRef2.current.value)
}
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>
)
}
}
//2.渲染组件到页面
ReactDOM.render(<Demo />, document.getElementById('test'))
</script>
</body>
</html>
(1) 通过onXxx属性指定事件处理函数(注意大小写)
a. React使用的是自定义(合成)事件,而不是使用原生DOM事件——为了更好的兼容性
b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)——为了高效
(2)通过event.target得到发生事件的DOM元素对象——不要过度使用ref!!!