一、 基本理解和使用
1、使用React开发者工具调试
2、定义组件
2.1、定义函数式组件
2.1.1、执行了ReactDOM. render( …之后,发生了什么?
1.React解析组件标签,找到了``MyComponent``组件。
2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面史。
<!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>函数组件</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 此处一定要写babel -->
<script type="text/babel">
//1.创建函数式组件
function MyCompoent(){
console.log(this);//此处的this是undefined, 因为babel编译后开启了严格模式
return <h2>我是用函数式定义的组件(适用于简单组件的定义)</h2>
}
//2.渲染组件到页面
ReactDOM.render(<MyCompoent/>,document.getElementById('test'))
/*
执行了ReactDOM. render( <MyComponent/>.......之后,发生了什么?
1.React解析组件标签,找到了MyComponent组件。
2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面史。
*/
</script>
</body>
</html>
2.2、定义类式组件
2.2.1、执行了ReactDOM. render( MyComponent…之后,发生了什么?
2.2.1.1、React解析组件标签,找到了``MyComponent``组件。
2.2.1.2、发现组件是使用类定义的,随后``new出了该类的实例``,并通过该实例调用到了``原型上的render的方法``
2.2.1.3、将render返回的虚拟DOM转为真实DOM,随后呈现在页面中
2.2.2、render的疑惑🤔
2.2.2.1、render是放在哪里的?-MyComponent的原型对象上,供实例使用
2.2.2.2、render中的this
是谁?-MyComponent的的实例对象。MyComponent组件实例对象
<!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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 此处一定要写babel -->
<script type="text/babel">
// 1.创建类式组件
class MyComponent extends React.Component {
//构造器继承过来了
render() {
console.log('render中的实例对象:',this);
// render是放在哪里的?-MyComponent的原型对象上,供实例使用。
// render中的this是谁?-MyComponent的的实例对象。MyComponent组件实例对象
return <h2>我是用类式定义的组件(适用于复杂组件的定义)</h2>
}
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById('test'))
/*
执行了ReactDOM. render( <MyComponent/>.......之后,发生了什么?
1.React解析组件标签,找到了MyComponent组件。
2.发现组件是使用类定义的,随后new出了该类的实例,并通过该实例调用到了原型上的render的方法
3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面中
*/
</script>
</body>
</html>
二、组件的三大核心属性
1、❤️state❤️
1.1、初始化显示页面
<!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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 此处一定要写babel -->
<script type="text/babel">
//1.创建组件
class Weather extends React.Component{
constructor(props){
super(props)
//初始化状态
this.state={isSchool:false}
}
render() {
console.log(this);
return <h1>我想去{this.state.isSchool?'清华大学':'北京大学'}</h1>
}
}
//2.渲染组件到页面
ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>
</body>
</html>
1.2、this指向问题(点击文本)
解决changeSchool指向问题
类中的方法默认开启了局部的严格模式
,所以changeWeather中的this为undefined
this.changeSchool = this.changeSchool.bind(this)
<!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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 此处一定要写babel -->
<script type="text/babel">
//1.创建组件
class School extends React.Component {
constructor(props) {
super(props)
//初始化状态
this.state = { isSchool: false }
//解决changeSchool指向问题
this.changeSchool = this.changeSchool.bind(this)
}
render() {
console.log(this);
return <h1 onClick={this.changeSchool}>我想去{this.state.isSchool ? '清华大学' : '北京大学'}</h1>
}
changeSchool() {
//changeWeather放在哪里?一Weather的原型对象 上,供实例使用
//由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
// console.log(this.state.isSchool);
console.log(this);
}
}
//2.渲染组件到页面
ReactDOM.render(<School />, document.getElementById('test'))
</script>
</body>
</html>
1.3、state里面不能直接修改状态
3.1.3.1、目标
:点击文本修改页面状态
3.1.3.2、里面的constructor、render、changeSchool
分别被调用了几次
constructor
调用了几次?-----1 次
render
调用了几次?-----1+n次
1是初始化的那次 n
是状态更新的次数
changeSchool
调用了几次?----点击了几次就调用几次
3.1.3.3、严重注意
状态不能直接更改,要借助内置的API。state状态必须通过setState修改,且更新是合并,不是替换
<!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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 此处一定要写babel -->
<script type="text/babel">
//1.创建组件
class School extends React.Component {
//构造器调用了几次?-----1 次
constructor(props) {
console.log('constructor');
super(props)
//初始化状态
this.state = { isSchool: false ,name:'qxt'}
//解决changeSchool指向问题
this.changeSchool = this.changeSchool.bind(this)
}
//render调用了几次?-----1+n次 1是初始化的那次 n是状态更新的次数
render() {
console.log('render');
console.log(this);
return <h1 onClick={this.changeSchool}>我想去{this.state.isSchool ? '清华大学' : '北京大学'},{this.state.name}</h1>
}
//changeSchool调用了几次?-----点几次调用几次
changeSchool() {
console.log('changeSchool');
//changeWeather放在哪里?一Weather的原型对象 上,供实例使用
//由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
// console.log(this.state.isSchool);
console.log(this);
// 获取原来的isSchool的值
const isSchool = this.state.isSchool
//严重注意:state状态必须通过setState修改,且更新是合并,不是替换
this.setState({isSchool:!isSchool})
console.log(this.state.isSchool);
// //严重注意:状态不能直接更改,要借助内置的API,下面这行是直接更改
//修改isSchool的状态 点击取反
// this.state.isSchool = !isSchool
}
}
//2.渲染组件到页面
ReactDOM.render(<School />, document.getElementById('test'))
</script>
</body>
</html>
1.4、state简写方式
3.1.4.1、注意
箭头函数
没有this ,里面的this
会去外层
找到那个this
自定义函数----类里面可以直接赋值
这里面的this去外面找this,就是School实例对象
<!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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 此处一定要写babel -->
<script type="text/babel">
//1.创建组件
class School extends React.Component {
//初始化状态
state = { isSchool: false, name: '邱勋涛' }
render() {
return <h1 onClick={this.changeSchool}>我想去{this.state.isSchool ? '北京电影学院' : '中央戏剧学院'}❤️{this.state.name}❤️</h1>
}
// 箭头函数没有this ,里面的this会去外层找到那个this
// 自定义函数----类里面可以直接赋值
// 这里面的this去外面找this,就是School实例对象
changeSchool=()=> {
const isSchool = this.state.isSchool
this.setState({ isSchool: !isSchool })
console.log(this);
}
}
//2.渲染组件到页面
ReactDOM.render(<School />, document.getElementById('test'))
</script>
</body>
</html>
调试工具反应会有延迟
…
1.4、总结
1.4.1、理解
1.state
是组件对象最重要
的属性, 值是对象(可以包含多个key-value
的组合)
2.组件
被称为"状态机
", 通过更新
组件的state来更新对应的页面
显示(重新渲染组件
)
1.4.2、强烈注意
1.组件中render方法中的this
为组件实例对象
2.组件自定义的方法中this
为undefined
,如何解决?
(a)强制绑定this: 通过函数对象的bind()
(b)箭头函数
3.状态数据,不能直接修改或更新
2、❤️props❤️
2.1、props的基本使用
2.1.1、需求: 自定义用来显示人员信息的组件
<!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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test1'></div>
<div id='test2'></div>
<div id='test3'></div>
<div id='test4'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 此处一定要写babel -->
<script type="text/babel">
//创建组件
class Person extends React.Component{
render() {
console.log(this);
return (
<ul>
<li>姓名:{this.props.name}</li>
<li>性别:{this.props.age}</li>
<li>年龄:{this.props.sex}</li>
</ul>
)
}
}
//渲染组件到页面
ReactDOM.render(<Person name="鹿晗" age='18' sex='男'/>,document.getElementById('test1'))
ReactDOM.render(<Person name="王嘉尔" age='20' sex='男'/>,document.getElementById('test2'))
ReactDOM.render(<Person name="胡歌" age='19' sex='男'/>,document.getElementById('test3'))
ReactDOM.render(<Person name="刘亦菲" age='16' sex='女'/>,document.getElementById('test4'))
</script>
</body>
</html>
2.1.2、props批量传递
2.1.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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test1'></div>
<div id='test2'></div>
<div id='test3'></div>
<div id='test4'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 此处一定要写babel -->
<script type="text/babel">
//创建组件
class Person extends React.Component{
render() {
console.log(this);
return (
<ul>
<li>姓名:{this.props.name}</li>
<li>性别:{this.props.age}</li>
<li>年龄:{this.props.sex}</li>
</ul>
)
}
}
//渲染组件到页面
ReactDOM.render(<Person name="鹿晗" age='18' sex='男'/>,document.getElementById('test1'))
ReactDOM.render(<Person name="王嘉尔" age='20' sex='男'/>,document.getElementById('test2'))
ReactDOM.render(<Person name="胡歌" age='19' sex='男'/>,document.getElementById('test3'))
const p={name:'刘亦菲',age:16,sex:'女'}
ReactDOM.render(<Person {...p}/>,document.getElementById('test4'))
</script>
</body>
</html>
2.1.2.2、对props进行限制
a、第一种方式
(React v15.5 开始已弃用)
Person.propTypes = {
// 限制名字 必须传 字符串
name: React.PropTypes.string.isRequired,
//限制性别 字符串
sex: React.PropTypes.string,
//限制年龄 数值
age: React.PropTypes.number,
//限制函数
speak:React.PropTypes.func
}
b、第二种方式
(新):使用prop-types库进限制(需要引入prop-types库
)
//对标签属性进行类型、必要性的限制
Person.propTypes = {
// 限制名字 必须传 字符串
name: PropTypes.string.isRequired,
//限制性别 字符串
sex: PropTypes.string,
//限制年龄 数值
age: PropTypes.number,
//限制函数
speak: PropTypes.func
}
c、props默认属性
Person.defaultProps = {
//sex 默认值 男
sex: '男',
//age 默认值 99
age: 99
}
d、组件类的构造函数
constructor(props){
super(props)
console.log(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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test1'></div>
<div id='test2'></div>
<div id='test3'></div>
<div id='test4'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入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>
<!-- 此处一定要写babel -->
<script type="text/babel">
//创建组件
class Person extends React.Component {
render() {
console.log(this);
const { name, age, sex } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{age + 1}</li>
<li>年龄:{sex}</li>
</ul>
)
}
}
//对标签属性进行类型、必要性的限制
Person.propTypes = {
// 限制名字 必须传 字符串
name: PropTypes.string.isRequired,
//限制性别 字符串
sex: PropTypes.string,
//限制年龄 数值
age: PropTypes.number,
//限制函数
speak: PropTypes.func
}
//指定默认标签属性
Person.defaultProps = {
//sex 默认值 不知道
sex: '不知道',
//age 默认值 99
age: 99
}
//渲染组件到页面
ReactDOM.render(<Person name="鹿晗" age={18} sex='男' speak={speak} />, document.getElementById('test1'))
ReactDOM.render(<Person name="王嘉尔" age={18} sex='男' />, document.getElementById('test2'))
ReactDOM.render(<Person name="胡歌" age={18} sex='男' />, document.getElementById('test3'))
const p = { name: 'jerry' }
ReactDOM.render(<Person {...p} />, document.getElementById('test4'))
function speak() {
console.log('我成功了');
}
</script>
</body>
</html>
2.1.2.3、props简写方式
把限制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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test1'></div>
<div id='test2'></div>
<div id='test3'></div>
<div id='test4'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入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>
<!-- 此处一定要写babel -->
<script type="text/babel">
//创建组件
class Person extends React.Component {
//对标签属性进行类型、必要性的限制
static propTypes = {
// 限制名字 必须传 字符串
name: PropTypes.string.isRequired,
//限制性别 字符串
sex: PropTypes.string,
//限制年龄 数值
age: PropTypes.number,
//限制函数
speak: PropTypes.func
}
//指定默认标签属性
static defaultProps = {
//sex 默认值 不知道
sex: '不知道',
//age 默认值 99
age: 99
}
render() {
console.log(this);
const { name, age, sex } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{age + 1}</li>
<li>年龄:{sex}</li>
</ul>
)
}
}
//渲染组件到页面
ReactDOM.render(<Person name="鹿晗" age={18} sex='男' speak={speak} />, document.getElementById('test1'))
ReactDOM.render(<Person name="王嘉尔" age={10} sex='男' />, document.getElementById('test2'))
ReactDOM.render(<Person name="胡歌" age={18} sex='男' />, document.getElementById('test3'))
const p = { name: 'jerry' }
ReactDOM.render(<Person {...p} />, document.getElementById('test4'))
function speak() {
console.log('我成功了');
}
</script>
</body>
</html>
2.1.2.4、类式组件中的constructor构造器与props
(1)、通常,在 React 中,构造函数仅用于以下两种情况:
a、通过给 this.state
赋值对象来初始化内部 state
。
b、为事件处理函数绑定实例
(2)、构造器是否接收props,是否传递给super,取决于:
是否希望在构造器中通过this访问props
constructor(props){
super(props)
console.log('constructor',this.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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test1'></div>
<div id='test2'></div>
<div id='test3'></div>
<div id='test4'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入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>
<!-- 此处一定要写babel -->
<script type="text/babel">
//创建组件
class Person extends React.Component {
constructor(props){
super(props)
console.log('constructor',this.props);
}
//对标签属性进行类型、必要性的限制
static propTypes = {
// 限制名字 必须传 字符串
name: PropTypes.string.isRequired,
//限制性别 字符串
sex: PropTypes.string,
//限制年龄 数值
age: PropTypes.number
}
//指定默认标签属性
static defaultProps = {
//sex 默认值 不知道
sex: '男',
//age 默认值 99
age: 32
}
render() {
console.log(this);
const { name, age, sex } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{age + 1}</li>
<li>年龄:{sex}</li>
</ul>
)
}
}
//渲染组件到页面
ReactDOM.render(<Person name="鹿晗" />, document.getElementById('test1'))
</script>
</body>
</html>
2.1.2.5、函数式组件使用props
(1)、函数式组件只能用props,对类式组件和refs都不能使用,原因是函数式组件可以传参数,接收了props,是一个对象
(2)、对props进行限制
把static
关键字改成函数名
Person即可,其他的不变
<!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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test1'></div>
<div id='test2'></div>
<div id='test3'></div>
<div id='test4'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入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>
<!-- 此处一定要写babel -->
<script type="text/babel">
function Person(props) {
console.log(props);
return (
<ul>
<li>姓名:{props.name}</li>
<li>性别:{props.age + 1}</li>
<li>年龄:{props.sex}</li>
</ul>
)
}
//对标签属性进行类型、必要性的限制
Person.propTypes = {
// 限制名字 必须传 字符串
name: PropTypes.string.isRequired,
//限制性别 字符串
sex: PropTypes.string,
//限制年龄 数值
age: PropTypes.number
}
//指定默认标签属性
Person.defaultProps = {
//sex 默认值 不知道
sex: '男',
//age 默认值 99
age: 32
}
//渲染组件到页面
ReactDOM.render(<Person name="鹿晗" />, document.getElementById('test1'))
</script>
</body>
</html>
3、❤️refs❤️
3.1、实现效果(ref 字符串类型 目前官方不推荐 以后会废弃)
3.1.1、需求: 自定义组件, 功能说明如下
1.点击按钮, 提示第一个输入框中的值
2. 当第2个输入框失去焦点时, 提示这个输入框中的值
3.2、理解Refs的字符串类型
(1)、组件内的标签可以定义ref属性来标识自己
(2)、ref 字符串类型
目前官方不推荐
以后会废弃
(3)、过时 API:String 类型的 Refs
如果你之前使用过 React,你可能了解过之前的 API 中的 string 类型的 ref 属性,例如 “textInput”。你可以通过 this.refs.textInput 来访问 DOM 节点。我们不建议使用它
,因为 string 类型的 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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 此处一定要写babel -->
<script type="text/babel">
// 1.创建组建
class Demo extends React.Component {
// 显示左侧输入框的数据
showData = () => {
const { leftInput } = this.refs
alert(leftInput.value)
}
// 显示右侧输入框的失去焦点的数据
loseFocus = () => {
const { rightInput } = this.refs
alert(rightInput.value)
}
render() {
return (
<div>
<input ref='leftInput' type="text" placeholder=" 点志按钮显示数据" />
<button onClick={this.showData}>点我提示左侧的数据</button>
<input ref='rightInput' onBlur={this.loseFocus} type="text" placeholder=" 失去焦点显示数据" />
</div>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo a='111' />, document.getElementById('test'))
</script>
</body>
</html>
3.3、回调函数形式的ref
关于回调 refs 的说明
如果 ref
回调函数是以内联函数
的方式定义的,在更新过程中它会被执行两次
,第一次传入参数 null
,然后第二次会传入参数 DOM 元素。这是因为在每次渲染时会创建一个新的函数实例,所以 React 清空旧的 ref 并且设置新的。通过将 ref 的回调函数定义成 class 的绑定函数的方式可以避免上述问题,但是大多数情况下它是无关紧要
的。
<input ref={ c=>this.leftInput=c}type="text" placeholder=" 点志按钮显示数据" />
<input ref={c=>this.rightInput=c} onBlur={this.loseFocus} type="text" placeholder=" 失去焦点显示数据" />
<!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>hello_react</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id='test'></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dmo 用于react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel 用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<!-- 此处一定要写babel -->
<script type="text/babel">
// 1.创建组建
class Demo extends React.Component {
// 显示左侧输入框的数据
showData = () => {
const { leftInput } = this
alert(leftInput.value)
}
// 显示右侧输入框的失去焦点的数据
loseFocus = () => {
const { rightInput } = this
console.log(this);
alert(rightInput.value)
}
render() {
return (
<div>
<input ref={ c=>this.leftInput=c}type="text" placeholder=" 点志按钮显示数据" />
<button onClick={this.showData}>点我提示左侧的数据</button>
<input ref={c=>this.rightInput=c} onBlur={this.loseFocus} type="text" placeholder=" 失去焦点显示数据" />
</div>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo a='111' />, document.getElementById('test'))
</script>
</body>
</html>
3.4、回调ref调用次数的问题
解决办法
:把里面的内联函数
变为外面的赋值函数
saveInput = (c)=>{
this.input1 = c;
console.log('@',c);
}
<input ref={this.saveInput} type="text"/>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3_回调ref中回调执行次数的问题</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
//创建组件
class Demo extends React.Component{
state = {isHot:false}
showInfo = ()=>{
const {input1} = this
alert(input1.value)
}
changeWeather = ()=>{
//获取原来的状态
const {isHot} = this.state
//更新状态
this.setState({isHot:!isHot})
}
saveInput = (c)=>{
this.input1 = c;
console.log('@',c);
}
render(){
const {isHot} = this.state
return(
<div>
<h2>今天天气很{isHot ? '炎热':'凉爽'}</h2>
{/*<input ref={(c)=>{this.input1 = c;console.log('@',c);}} type="text"/><br/><br/>*/}
<input ref={this.saveInput} type="text"/><br/><br/>
<button onClick={this.showInfo}>点我提示输入的数据</button>
<button onClick={this.changeWeather}>点我切换天气</button>
</div>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'))
</script>
</body>
</html>
3.5、React.createRef()
React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的
myRef = React.createRef()
myRef2 = React.createRef()
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input onBlur={this.showData2} ref={this.myRef2} type="text" placeholder="失去焦点提示数据"/>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4_createRef</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
//创建组件
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 onBlur={this.showData2} ref={this.myRef2} type="text" placeholder="失去焦点提示数据"/>
</div>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>
</body>
</html>
4、❤️React事件处理❤️
1.通过onXxx属性指定事件处理函数(注意大小写)
a.React使用的是自定义(合成)事件, 而不是使用的原生DOM事件-------为了更好的兼容性
b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)---为了高效
2.通过event.target得到发生事件的DOM元素对象--------不要过度使用ref
event
:发生事件的事件源
(事件对象)
发生事件的事件源
必须是同一个
,要不然找不到
showData2 = (event) => {
alert(event.target.value);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>4_createRef</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
//创建组件
class Demo extends React.Component {
/*
1.通过onXxx属性指定事件处理函数(注意大小写)
a.React使用的是自定义(合成)事件, 而不是使用的原生DOM事件-------为了更好的兼容性
b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)---为了高效
2.通过event.target得到发生事件的DOM元素对象--------不要过度使用ref
*/
/*
React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的
*/
myRef = React.createRef()
myRef2 = React.createRef()
//展示左侧输入框的数据
showData = () => {
alert(this.myRef.current.value);
console.log(this);
}
//展示右侧输入框的数据
showData2 = (event) => {
alert(event.target.value);
}
render() {
return (
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />
<button onClick={this.showData}>点我提示左侧的数据</button>
<input onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo a="1" b="2" />, document.getElementById('test'))
</script>
</body>
</html>
🌈🌈🌈今天的自学就到这啦🌈🌈🌈