1.react.js:React核心库。
2.react-dom.js:提供操作DOM的react扩展库。
3.babel.min.js:解析JSX语法代码转为JS代码的库。
注意: 核心库必须在扩展库之前引入
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello_React</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>
<!-- 此处一定要写babel,不写默认是text/javascript -->
<!-- 使用babel用于将jsx转换为js -->
<script type="text/babel">
//1.创建虚拟dom
//jsx语法
const VDOM=<h1>大忽悠</h1>//此处一定不要写引号,因为不是字符串
//2.渲染虚拟dom到页面
ReactDOM.render(VDOM,document.getElementById("test"));
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello_React</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>
<!-- 此处一定要写babel,不写默认是text/javascript -->
<!-- 使用babel用于将jsx转换为js -->
<script type="text/babel">
//1.创建虚拟dom
const VDOM=<h1 id="test">大忽悠</h1>//此处一定不要写引号,因为不是字符串
//2.渲染虚拟dom到页面
ReactDOM.render(VDOM,document.getElementById("test"));
</script>
</body>
</html>
js创建虚拟dom,就不需要引入babel的js库来解析jsx语法了
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello_React</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,不写默认是text/javascript -->
<!-- 使用babel用于将jsx转换为js -->
<script type="text/javascript">
//1.创建虚拟dom
//标签名,标签属性,标签内容
const VDOM=React.createElement('h1',{id:'title'},'大忽悠');
//2.渲染虚拟dom到页面
ReactDOM.render(VDOM,document.getElementById("test"));
</script>
</body>
</html>
js写法:
<script type="text/javascript">
//1.创建虚拟dom
//标签名,标签属性,标签内容
const VDOM=React.createElement('h1',{id:'title'},
React.createElement('span',{id:'heihei'},'大忽悠'));
//2.渲染虚拟dom到页面
ReactDOM.render(VDOM,document.getElementById("test"));
</script>
jsx写法:
<!-- 引入babel,用于将jsx转换为js -->
<script type="text/javascript" src="./js/babel.min.js"></script>
<script type="text/babel">
//1.创建虚拟dom
//标签名,标签属性,标签内容
const VDOM=(
<h1 id='test'>
<span id='heihei'>大忽悠</span>
</h1>)
//2.渲染虚拟dom到页面
ReactDOM.render(VDOM,document.getElementById("test"));
</script>
babel会把jsx语法写的html标签内容,翻译为js写法,相当于一种语法糖
1.React提供了一些API来创建一种 “特别” 的一般js对象
const VDOM = React.createElement('xx',{id:'xx'},'xx')
上面创建的就是一个简单的虚拟DOM对象
2.虚拟DOM对象最终都会被React转换为真实的DOM
3.我们编码时基本只需要操作react的虚拟DOM相关数据, react会转换为真实DOM变化而更新界。
React.createElement(component, props, ...children)方法的语法糖
1)写法:var ele = < h1 >Hello JSX!< /h1 >
2)注意1:它不是字符串, 也不是HTML/XML标签
3)注意2:它最终产生的就是一个JS对象
1)遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
2)遇到以 { 开头的代码,以JS语法解析: 标签中的js表达式必须用{ }包含
<script type="text/babel">
const id="dhy";
const text="大忽悠和小朋友"
const VDOM=(
<h1 id={id}>
<span id='heihei'>{text}</span>
</h1>)
//2.渲染虚拟dom到页面
ReactDOM.render(VDOM,document.getElementById("test"));
</script>
class是ES6语法里面定义类的关键字
const VDOM=(
<h1 id={id}>
<span class='heihei'>{text}</span>
</h1>)
const VDOM=(
<h1 id={id}>
<span className='heihei'>{text}</span>
</h1>)
const VDOM=(
<h1 id={id}>
<font style={{color:'pink',fontSize:'29px'}}>小朋友</font>
</h1>)
此时最外层的div作为根标签
const VDOM=(
<div>
<h1 id={id}>
<font style={{color:'pink',fontSize:'29px'}}>小朋友</font>
</h1>
<h1 id={id+'1'}>
<font style={{color:'pink',fontSize:'29px'}}>大忽悠</font>
</h1>
</div>
)
错误,input标签没有闭合
const VDOM=(
<input type='text'>
)
正确,标签都闭合了
const VDOM=(
<input type='text'/>
)
(1):若小写字母开头,则将标签转换为html中同名标签元素,若html中无该标签对应的同名元素,则爆错 (2):若大写字母开头,react就去渲染对应的组件,若组件没有定义,则爆错
1.表达式: 一个表达式会产生一个值,可以放在任何一个需要值的地方 下面这些都是表达式: (1) a (2) a+b (3) demo(1) (4) arr.map() (5) function test(){} 2.语句(代码): (1)if(){} (2) for(){} (3)switch(){case:xxx}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello_React</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">
//模拟一些数据
const data=['dhy','xpy']
//创建虚拟DOM
const VDOM=
(
<div>
<h1>前端js框架列表</h1>
<ul>
{
//返回得到一个新数组
//由react遍历当前得到的新数组
data.map((item,index)=>
{
//读取遍历当前数组的变量值
//每个li必须有自己的唯一标识,即key对应的值,并且key值不可以重复
return <li key={index}>{item}</li>
})
}
</ul>
</div>
)
//2.渲染虚拟dom到页面
ReactDOM.render(VDOM,document.getElementById("test"));
</script>
</body>
</html>
1.理解:向外提供特定功能的js程序, 一般就是一个js文件
2.为什么要拆成模块:随着业务逻辑增加,代码越来越多且复杂。
3.作用:复用js, 简化js的编写, 提高js运行效率
1.理解:用来实现局部功能效果的代码和资源的集合(html/css/js/image等等)
2.为什么要用组件: 一个界面的功能更复杂
3.作用:复用编码, 简化项目编码, 提高运行效率
当应用的js都以模块来编写的, 这个应用就是一个模块化的应用
当应用是以多组件的方式实现, 这个应用就是一个组件化的应用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello_React</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">
//创建函数式组件
//函数组件的名字,首字母大写
function Demo()
{
//babel编译后,会开启严格模式,因此函数组件中的this指向undefined
console.log(this);
//必须有返回值
return <h1>函数组件</h1>
}
//渲染组件到页面
// 函数组件的标签首字母要大写,自闭合
ReactDOM.render(<Demo/>,document.getElementById('test'))
</script>
</body>
</html>
1.React解析组件标签,找到了MyComponent组件 2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转换为真实DOM,随后呈现在页面中
<script type="text/javascript">
//创建一个Person类
class Person
{
//构造器方法
constructor(name,age) {
//构造器中的this执行类的实例对象
this.name=name;
this.age=age;
}
//一般方法
speak()
{
//speak方法放在了类的原型对象上,供实例使用
//通过Person实例调用speak时,speak中的this就是Person实例
//模板字符串
console.log(`姓名:${this.name},年龄:${this.age}`);
}
}
//创建一个Student类,继承自Person
class Stu extends Person
{
constructor(name,age,grade) {
//此处必须调用父类的super方法
super(name,age);
this.grade=grade;
this.friend='小朋友';
}
//重写从父类继承过来的方法
speak()
{
console.log(`姓名:${this.name},年龄:${this.age}
,年级:${this.grade}`);
}
}
</script>
总结:
//创建类式组件---继承React.Component
class MyComponent extends React.Component
{
//render是放在MyComponent的原型对象上的,供实例使用
//this是MyComponent 的实例对象
//<==>MyComponent组件实例对象
render()
{
return <h2>类组件</h2>
}
}
//渲染组件到页面
ReactDOM.render(<MyComponent/>,document.getElementById('test'));
1.React解析组件标签,找到了MyComponent组件 2.发现组件是使用类定义的,随后调用该类的实例,并通过该实例调用到原型上的render方法 3.将render返回的虚拟DOM转换为真实DOM,随后呈现在页面中
1.默认展示天气炎热 或 凉爽
2.点击文字切换天气
常用的两种写法:
class Weather extends React.Component
{
constructor(props)
{
super(props)
//初始化状态
this.state={isHot:false}
}
render()
{
//读取状态
const {isHot}=this.state
return <h2 id="w">今天天气{isHot?'炎热':'凉爽'}</h2>
}
}
//渲染组件到页面
ReactDOM.render(<Weather/>,document.getElementById('test'));
const w1=document.getElementById('w');
w1.addEventListener('click',()=>{
console.log('标题被点击了');
})
const w2=document.getElementById('w');
w2.onclick=()=>{
console.log('标题被点击了');
}
推荐写法:
class Weather extends React.Component
{
constructor(props)
{
super(props)
//初始化状态
this.state={isHot:false}
}
render()
{
//读取状态
const {isHot}=this.state
return <h2 onClick={demo}>今天天气{isHot?'炎热':'凉爽'}</h2>
}
}
//渲染组件到页面
ReactDOM.render(<Weather/>,document.getElementById('test'));
function demo()
{
console.log('标题点击')
}
const { xxx } = this.state;
上面的写法是es6的写法,其实就相当于:
const xxx = this.state.xxx
开启了严格模式,那么方法里面的this为undefined
class A
{
s()
{
//s方法放在了类的原型对象上,供实例使用
//通过A的实例对象调用s方法时,s中的this就是A的实例
//否则为undefined
console.log(this)
}
}
const a=new A();
let b=a.s
b()
直接调用函数,函数中的this默认指向window,如果全局开启了严格模式,或者在函数体内部局部开启了严格模式,那么函数中的this为undefined
例如:
function a(){
'use strict'
console.log(this);
}
a();
function b(){
console.log(this);
}
b();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello_React</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">
// babel也会默认开启严格默认
class Weather extends React.Component
{
constructor(props)
{
super(props)
//初始化状态
this.state={isHot:false}
}
render()
{
//读取状态
const {isHot}=this.state
return <h2 onClick={this.changeWeather}>今天天气{isHot?'炎热':'凉爽'}</h2>
}
changeWeather()
{
//changeWeather放在weather的原型对象上,供实例使用
//由于changeWeather是作为onClick的回调
//所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式
//所以changeWeather中的this为undefined
console.log(this)
}
}
//渲染组件到页面
ReactDOM.render(<Weather/>,document.getElementById('test'));
</script>
</body>
</html>
// babel也会默认开启严格默认
class Weather extends React.Component
{
//构造函数里面的this指向调用的实例对象
constructor(props)
{
super(props)
//初始化状态
this.state={isHot:false}
//解决changeWeather中的this指向问题
this.changeWeather=this.changeWeather.bind(this)
}
render()
{
//读取状态
const {isHot}=this.state
//现在当前类上寻找changeWeather方法,找不到再去原型上找
return <h2 onClick={this.changeWeather}>今天天气{isHot?'炎热':'凉爽'}</h2>
}
changeWeather()
{
//changeWeather放在weather的原型对象上,供实例使用
//由于changeWeather是作为onClick的回调
//所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式
//所以changeWeather中的this为undefined
console.log(this)
}
}
//严重注意,状态state不可直接更改
//下面这行就是直接更改,下面是错误的写法
this.state.isHot=!isHot;
// babel也会默认开启严格默认
class Weather extends React.Component
{
//构造函数里面的this指向调用的实例对象
//构造器调用一次
constructor(props)
{
super(props)
//初始化状态
this.state={isHot:false,wind: '微风'}
//解决changeWeather中的this指向问题
this.changeWeather=this.changeWeather.bind(this)
}
//render调用1+n次
//1是初始化的那次
//n是状态更新的次数
render()
{
//读取状态
const {isHot,wind}=this.state
//现在当前类上寻找changeWeather方法,找不到再去原型上找
return <h2 onClick={this.changeWeather}>今天天气{isHot?'炎热':'凉爽'}
,{wind}</h2>
}
//事件触发几次,就调用几次
changeWeather()
{
//获取原来的isHot的值
const isHot=this.state.isHot;
//状态必须通过setState进行更新,且更新时一种合并,不是替换
this.setState({isHot:!isHot})
}
}
//渲染组件到页面
ReactDOM.render(<Weather/>,document.getElementById('test'));
点击后
class A
{
constructor(name) {
this.name=name;
}
//类中可以直接写赋值语句,相当于给实例对象增添了一个属性
//名为a,值为1
a=1
}
const a1=new A("大忽悠");
<script type="text/babel">
class Weather extends React.Component
{
//初始化状态
this.state={isHot:false,wind: '微风'}
render()
{
const {isHot,wind}=this.state
return <h2 onClick={this.changeWeather}>今天天气{isHot?'炎热':'凉爽'}
,{wind}</h2>
}
//自定义方法---要用赋值语句的形式+箭头函数
//箭头函数里面的this就是实例对象
//changeWeather此时是一个属性,指向一个方法,放在了实例对象上
changeWeather=()=>
{
const isHot=this.state.isHot;
this.setState({isHot:!isHot})
}
}
ReactDOM.render(<Weather/>,document.getElementById('test'));
</script>
1.state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
2.组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
1.组件中render方法中的this为组件实例对象
2.组件自定义的方法中this为undefined,如何解决?
a)强制绑定this: 通过函数对象的bind()
b)箭头函数
3.状态数据,不能直接修改或更新
效果:
class Person extends React.Component
{
render()
{
const {name,age}=this.props;
return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
ReactDOM.render(<Person name="bob" age="18"/>,document.getElementById('test'));
1.每个组件对象都会有props(properties的简写)属性
2.组件标签的所有属性都保存在props中
1.通过标签属性从组件外向组件内传递变化的数据
2.注意: 组件内部不要修改props数据
//展开数组
let arr1=[1,2,3]
let arr2=[4,5,6]
console.log(...arr1)
//连接数组
let arr3=[...arr1,...arr2]
//在函数中使用--只能作为最后一个参数使用
function sum(...nums)
{
return nums.reduce((preValue,curValue)=>{
return preValue+curValue
},0)//0是初始累加值
}
console.log(sum(1,2,3))
//构造字面量对象时使用展开语法
let person={name: 'tom',age: 18}
//展开对象必须在{}中使用
let per={...person}
console.log(per)
//合并对象
let per3={...person,name: 'jack'}
console.log(per3)
等同写法:
//展开对象必须在{}中使用
console.log({...person})
//合并对象
console.log({...person,name: 'jack'})
class Person extends React.Component
{
render()
{
const {name,age}=this.props;
return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
const p={name:'大忽悠',age: '18'}
//...p只能在标签里面使用,外部使用会报错
//babel可以解析标签里面的...p
ReactDOM.render(<Person {...p}/>,document.getElementById('test'));
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello_React</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></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>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="./js/prop-types.js"></script>
<script type="text/babel">
class Person extends React.Component
{
render()
{
const {name,age,speak}=this.props;
return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
//对标签属性进行类型,必要性的限制
Person.propTypes=
{
//限制name必须传,且为字符串
name:PropTypes.string.isRequired,
//限制年龄为数字类型
age:PropTypes.number,
//限制speak必须为函数类型
//这里用func表示函数类型,而不是function
//因为function是js中的关键字
speak: PropTypes.func
}
//指定默认标签属性值
//如果标签里面没传对应的属性,那么赋予属性默认值
Person.defaultProps=
{
age: 18
}
function speak()
{
return "dhy like xpy";
}
ReactDOM.render(<Person name="小盆友" age={3} speak={speak}/>,document.getElementById('test1'));
ReactDOM.render(<Person name="超级大忽悠"/>,document.getElementById('test2'));
const p={name:'大忽悠',age:18}
//...p只能在标签里面使用,外部使用会报错
ReactDOM.render(<Person {...p}/>,document.getElementById('test3'));
</script>
</body>
</html>
class Person extends React.Component
{
render()
{
const {name,age,speak}=this.props;
//props是只读的,下面写法会报错
this.props.name="匿名"
return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
</ul>
)
}
}
实例对象身上没有b属性,类身上才有
class A
{
constructor(a) {
this.a=a;
}
//给实例对象上身上添加属性
a=1;
static b=2
}
const a=new A(10);
console.log(a);
如何给类身上添加属性:
方法一:
class A
{
//给实例对象上身上添加属性
a=1;
}
//给class类自身加上属性
A.b=2;
console.log(A);
console.log(A.b)
方法二: static方法
class A
{
constructor(a) {
this.a=a;
}
//给实例对象上身上添加属性
a=1;
static b=2
}
console.log(A);
console.log(A.b);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello_React</title>
</head>
<body>
<!-- 准备好一个容器 -->
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></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>
<!-- 引入prop-types,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="./js/prop-types.js"></script>
<script type="text/babel">
class Person extends React.Component
{
render()
{
const {name,age}=this.props;
return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
</ul>
)
}
static propTypes=
{
name:PropTypes.string.isRequired,
age:PropTypes.number
}
static defaultProps=
{
age: 18
}
}
ReactDOM.render(<Person name="小盆友" age={3}/>,document.getElementById('test1'));
ReactDOM.render(<Person name="超级大忽悠"/>,document.getElementById('test2'));
</script>
</body>
</html>
如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。
在 React 组件挂载之前,会调用它的构造函数。在为 React.Component 子类实现构造函数时,应在其他语句之前前调用 super(props)。否则,this.props 在构造函数中可能会出现未定义的 bug。
constructor(props)
{
//构造器是否接受props,是否传递给super,取决于是否希望构造器中调用
//this访问props
super(props);
//如果super(),那么this.props是undefined
console.log(this.props)
}
//创建函数式组件
function Per(props)
{
const {name,age}=props
return (
<ul>
<li>{name}</li>
<li>{age}</li>
</ul>
)
}
Per.propTypes={
name:PropTypes.string.isRequired,
age:PropTypes.number
}
Per.defaultProps=
{
age: 18
}
//渲染组件到页面
ReactDOM.render(<Per name="大忽悠"/>,document.getElementById('test'))
1.内部读取某个属性值
this.props.name
2.对props中的属性值进行类型限制和必要性限制
第一种方式(React v15.5 开始已弃用):
Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number
}
第二种方式(新):使用prop-types库进限制(需要引入prop-types库)
Person.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.
}
3.扩展属性: 将对象的所有属性通过props传递
<Person {...person}/>
4.默认属性值:
Person.defaultProps = {
age: 18,
sex:'男'
}
5.组件类的构造函数
constructor(props){
super(props)
console.log(props)//打印所有属性
}
6.props为只读,不可以修改
7.函数式组件可以通过参数获取到props对象,然后进行操作,也可以进行类型和默认值操作
8.PropTypes大写的这个是导入js包后,全局新增的一个对象,而Person.propTypes是我们需要给类上添加的一个属性,react底层会去寻找当前类上名字相同的属性,然后进行遍历,设置对应的类型限制和默认值
//创建组件
class Demo extends React.Component
{
showData=()=>
{
//refs里面的input1属性对应input标签的dom对象
const{input1}=this.refs;
input1.value="大忽悠到此一游";
}
showData2=()=>
{
const{input2}=this.refs;
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'));
//创建组件
class Demo extends React.Component
{
showData=()=>
{
const{input1}=this;
input1.value="大忽悠到此一游";
}
showData2=()=>
{
const{input2}=this;
input2.value="呜呜呜";
}
// c就是当前的input标签的dom对象
//将其挂载到当前实例上的input1属性上
render()
{
return (
<div>
<input ref={c=>this.input1=c} type="text" placeholder='点击按钮提示数据'/>
<button onClick={this.showData}>点我提示左侧数据</button>
<input ref={c=>this.input2=c} onBlur={this.showData2} type="text" placeholder='失去焦点,提示数据'/>
</div>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'));
如下的内联函数,每次渲染都会创建一个新的,并且先清空之前的ref,传入null,第二次传入dom元素
<input ref={c=>this.input1=c} type="text" placeholder='点击按钮提示数据'/>
如果是class的绑定函数,那么react就知道当前绑定函数被调用过,不会新创建函数实例,也就不会在更新的时候调用对应的函数了
React 初学 - 回调ref中调用次数的问题 - 个人笔记26
createRef创建出来的容器,只能放一个dom元素,后放进去的dom元素会覆盖之前放入的dom元素
//创建组件
class Demo extends React.Component
{
//React.createRef调用后返回一个容器
//该容器可以存储ref所标识的节点,该容器是专人专用
//后来的覆盖之前的
myref=React.createRef()
showData=()=>
{
console.log(this.myref)
}
//将input标签放入myref容器中
//如果将button也放入myref容器中
//那么会覆盖之前的input
render()
{
return (
<div>
<input ref={this.myref} type="text" placeholder='点击按钮提示数据'/>
<button ref={this.myref} onClick={this.showData}>点我提示左侧数据</button>
</div>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'));
1.通过onXxx属性指定事件处理函数(注意大小写)
1)React使用的是自定义(合成)事件, 而不是使用的原生DOM事件----为了更好的兼容性
2)React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)---为了高效
2.通过event.target得到发生事件的DOM元素对象
当发生事件的元素正好是我们需要操作的元素时,ref可以不写,通过event可以获取到对应的dom元素
//创建组件
class Demo extends React.Component
{
showData=(event)=>
{
console.log(event.target)
}
render()
{
return (
<div>
<input ref={this.myref} type="text" placeholder='点击按钮提示数据'/>
<button onClick={this.showData}>点我提示左侧数据</button>
</div>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'));
//创建组件
class Demo extends React.Component
{
handleSubmit=(event)=>
{
//阻止表单提交
event.preventDefault()
const{nameInput,pwdInput}=this
//模板字符串
alert(`输入的用户名:${nameInput.value},输入的密码:${pwdInput.value}`)
}
render()
{
return(
<form onSubmit={this.handleSubmit}>
用户名: <input ref={c=>this.nameInput=c} type="text" name="username"/><br/>
密码: <input ref={c=>this.pwdInput=c} type="password" name="password"/><br/>
<button>登录</button>
</form>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'));
//创建组件
class Demo extends React.Component
{
//初始化状态
state={
name: '',
pwd: ''
}
//保存用户名到状态中
saveName=(event)=>
{
this.setState({name:event.target.value})
}
//保存密码到状态中
savePwd=(event)=>
{
this.setState({pwd:event.target.value})
}
handleSubmit=(event)=>
{
//阻止表单提交
event.preventDefault()
const{name,pwd}=this.state
alert(`输入的用户名:${name},输入的密码:${pwd}`)
}
render()
{
return(
<form onSubmit={this.handleSubmit}>
用户名: <input onChange={this.saveName} type="text" name="username"/><br/>
密码: <input onChange={this.savePwd} type="password" name="password"/><br/>
<button>登录</button>
</form>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'));
高阶函数:如果一个函数符合下面2个规范中的任何一个,那该函数就是高阶函数
let a='name'
let obj={name:"大忽悠"}
console.log(obj[a])
//下面是错误写法
console.log(obj.a)
//创建组件
class Demo extends React.Component
{
//初始化状态
state={
name: '',
pwd: ''
}
//保存表单数据到状态中
saveFormData=(dataType)=>{
return (event)=>
{
//[]是读取变量里面的值
this.setState({[dataType]:event.target.value})
}
}
handleSubmit=(event)=>
{
//阻止表单提交
event.preventDefault()
const{name,pwd}=this.state
alert(`输入的用户名:${name},输入的密码:${pwd}`)
}
render()
{
return(
<form onSubmit={this.handleSubmit}>
用户名: <input onChange={this.saveFormData('name')} type="text" name="username"/><br/>
密码: <input onChange={this.saveFormData('pwd')} type="password" name="password"/><br/>
<button>登录</button>
</form>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'));
onChange事件这里接收到的是saveFormData函数的返回值,因为saveFormData函数的返回值还是一个函数,onChange调用返回的函数时,会往里面传入一个event对象
//创建组件
class Demo extends React.Component
{
//初始化状态
state={
name: '',
pwd: ''
}
//保存表单数据到状态中
saveFormData=(dataType,event)=>{
//[]是读取变量里面的值
this.setState({[dataType]:event.target.value})
}
handleSubmit=(event)=>
{
//阻止表单提交
event.preventDefault()
const{name,pwd}=this.state
alert(`输入的用户名:${name},输入的密码:${pwd}`)
}
render()
{
return(
<form onSubmit={this.handleSubmit}>
用户名: <input onChange={(event)=>{this.saveFormData('name',event)}} type="text" name="username"/><br/>
密码: <input onChange={(event)=>{this.saveFormData('pwd',event)}} type="password" name="password"/><br/>
<button>登录</button>
</form>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo/>,document.getElementById('test'));