文章目录
事件对象
默认情况下,react会传递一个事件对象到事件的处理函数,这个事件对象是一个合成事件对象。
const onAdd=(e)=>{console.log(e)}
return <button onClick={onAdd }>点击</button>
使用事件对象阻止默认事件、阻止冒泡。
const onAdd=(e)=>{
e.preventDefault();//阻止默认事件
e.stopPropagation()//阻止事件冒泡
console.log(e);
}
return <div onClick={()=>{console.log('div的点击事件被触发')}}>
<a onClick={onAdd } href="#">点击</a>
</div>
通过事件对象获取输入的值。
return <input onChange={(e)=> {console.log(e.target.value)}}/>
事件处理程序传递参数
const onAdd = (param) => {
return (e)=>{
console.log(param)
console.log(e)
}
}
return <button onClick={onAdd('hello')}>点击</button>
或者
const onAdd = (param, e) => {
console.log(param)
console.log(e)
}
return <button onClick={(e) => onAdd('hello', e)}>点击</button>
函数组件与 class 组件
函数组件
可以使用首字母为大写的名称定义一个函数,并且让这个函数返回一个 React 元素。
这类组件被称为“函数组件”。
function Home() {
return <h1>Hello, txc</h1>
}
类组件
可以使用ES6 的 class来定义组件,通过定义render函数来返回react元素。
class Home extends React.Component {
render() {
return <h1>Hello, txc</h1>;
}
}
渲染组件
使用组件,直接像使用普通标签那样使用就可以了。
<App/>
class组件中的事件处理
类组件中的 this 指向类的实例,在render函数中可以通过 this 访问该类的实例的属性。
class App extends React.Component{
onAdd(){
console.log('点击事件发生了')
}
render(){
return <div>
<button onClick={this.onAdd}>点击</button>
</div>
}
}
提示:
在 JavaScript 中,class 的方法默认不会绑定 this
class App extends React.Component {
onSum(num1,num2){
return num1+num2
}
onAdd() {
//直接在函数内访问this,是访问不到的,为Undefined
console.log(this)
this.onSum(1,2)
}
render() {
return <div>
<button onClick={this.onAdd}>点击</button>
</div>
}
}
手动绑定函数中 this 的指向
1、方法一:在render函数中绑定
class App extends React.Component {
onSum(num1,num2){
return num1+num2
}
onAdd() {
//直接在函数内访问this,是访问不到的
console.log(this)
console.log(this.onSum(1,2))
}
render() {
return <div>
<button onClick= {this.onAdd.bind(this)}>点击</button>
</div>
}
}
方法二:在类的构造函数中绑定
class App extends React.Component {
constructor(){
super()
//因为在类的构造函数中也可以访问this
this.onAdd=this.onAdd.bind(this)
}
onSum(num1,num2){
return num1+num2
}
onAdd() {
console.log(this)
console.log(this.onSum(1,2))
}
render() {
console.log(this)
return <div>
<button onClick={this.onAdd}>点击</button>
</div>
}
}
方法三:使用箭头函数
class App extends React.Component {
onSum(num1,num2){
return num1+num2
}
onAdd=()=> {
console.log(this)
console.log(this.onSum(1,2))
}
render() {
console.log(this)
return <div>
<button onClick={this.onAdd}>点击</button>
</div>
}
}
组件关系
App.js
function App() {//App组件是Home组件跟Welcome的子组件
return <div>
<Home/>
<Welcome/>
</div>
}
引用其它组件的组件叫做父组件,被引用在其它组件界面的组件叫做子组件。
组件的props
组件与组件之间是可以交互的,可以互相传递数据的。
我们可以通过 props 属性让父组件向子组件传递数据。
1、函数的组件的props
return (
<div>
<Child title="xiaotong"/>
</div>
)
export default function Child(props) {
return (
<div>
<h3>欢迎欢迎~ 热烈欢迎!</h3>
<p>{ props.title }</p>
</div>
)}
2、class的组件的props
render() {
const info={title:'首页',desc:'这里是网站的首页,也是默认启动页面'}
return (
<div>
<Child info={info}/>
</div>
)
}
import React from 'react'
export default class Child extends
React.Component {
render() {
const {title,desc}=this.props.info
return <div>
<h3>{ title }</h3>
<p>{ desc }</p>
</div>
}
}
提示:
组件可以接受任意 props,包括基本数据类型,React 元素以及函数。
提示:
组件无论是使用函数声明还是通过 class 声明,都决不能修改自身的 props,props具有只读性。
子组件向父组件传递数据
子组件向父组件传递数据,依然可以利用props实现。
props对于数据类型没有限制,那么就可以利用props传递函数,然后在子组件中调用传递进来的函数,并且在调用的时候传递数据。
// Parent.js
import React, { Component } from 'react'
import Child from "./Child"
export default class Parent extends
Component {
onChange=(data){
console.log(data)
}
render() {
return (
<div>
<h3>Parent</h3>
<Child onChange={ this.onChange }/>
</div>
)
}
}
// Child.js
import React, { Component } from 'react'
export default class Child extends Component
{
onChange=(e)=>{
this.props.onChange&&this.props.onChange(e.target.value)
}
render() {
return (
<div>
<h3>Child</h3>
<input onChange={ this.onChange }/>
</div>
)
}
}
组件组合
组件当中也是可以嵌套其它元素或者组件的。
<Home>
<div>一些要放在home组件当中的内容</div>
<p>xxxxxx</p>
</Home>
通过 props.children 获取组件内部嵌套的内容。
function Home (props){
return <div>
<h3>这是home页面</h3>
{/* 最红props.children会被替换为嵌套的内容 */}
{props.children}
</div>
}
提示:
组合也同样适用于以 class 形式定义的组件。
组件状态State
State 与 props 类似,但是 state 是组件私有的,并且完全受控于所属的组件。
使用 State的目的 :管理组件内部状态,并且当组件内部状态发生变化的时候,重新渲染页面。
1、初始化并使用state
1.1、在类的构造函数中为 state 赋初值,并且通过 this.state 访问数据。
import React from 'react'
export default class StateTest extends React.Component {
constructor() {
super();
this.state = {date: new Date()};
}
render() {
return <p>{ this.state.date }</p>
}
}
2、使用 this.setState() 更新state并让页面重新渲染
import React from 'react'
export default class StateTest extends
React.Component {
constructor() {
super();
this.state = { date: new Date() };
}
onChange = () => {
this.setState({ date: new Date()
})
}
render() {
return <div>
<p> {this.state.date.toLocaleTimeString()}</p>
<button onClick= {this.onChange}>更新state</button>
</div>
}
}
提示
一般我们只在类组件里面使用 state ,函数组件当中不使用 state ,所以有的时候把类组件叫做有状态组件,函数组件叫 做无状态组件。
思考:State与Props的区别
State:负责组件内部的状态管理
Props:负责组件与组件之间的数据交互
State的更新
1、更改state,不要直接修改 state
this.state.date=new Date()
//这样的代码是不会生效的
提示:
只有使用setState页面才会重新渲染。
2、使用 setState 去更新state
2.1、setState 是异步的
this.setState({ date: new Date() })
//上面setState之后,下面的代码是没法获取到更新后的state的
console.log(this.state.date.toLocaleTimeString())
解决方案,直接给setState传递回调函数。
this.setState({ date: new Date() }, (state)=>{
console.log(state.date.toLocaleTimeString())
})
或者
this.setState({ date: new Date() })
this.setState((state)=>{
console.log(state.date.toLocaleTimeString())
})
3、setState 会合并state
当你调用 setState() 的时候,React 会把你提供的对象合并到当前的 state。
constructor() {
super();
this.state = { date: new Date(),title:'今天的天气真不错' };
}
onChange = () => {
this.setState({ date: new Date() })
//在这里直接设置为{date:new Date},则与原来的{date:new Date,title:'今天的天气很不错合并'},不会直接干掉title属性,只会替换date属性的值
}
setState重新渲染组件跟子组件
1、调用setState,组件的render方法会被重新调用,从而重新渲染页面
onChange = () => {
this.setState({ date: new Date()
})
}
render() {
return <div>
<p> {this.state.date.toLocaleTimeString()}</p>
<button onClick= {this.onChange}>更新state</button>
</div>
}
2、调用setState,子组件也会被重新渲染
//StateTest.js
import React from 'react'
import StateTestChild from './StateTestChild';
export default class StateTest extends React.Component {
constructor() {
super();
this.state = { date: new Date(),title:'今天的天气真不错' };
}
onChange = () => {
this.setState({ date: new Date()
})
}
render() {
return <div>
<p> {this.state.date.toLocaleTimeString()}</p>
<button onClick= {this.onChange}>更新state</button>
<StateTestChild date= {this.state.date.toLocaleTimeString()}/>
</div>
}
}
//StateTestChild.js
export default function StateTestChild(props){
return <div>
<h3>我是子组件</h3>
子组件的时间:{props.date}
</div>
}
基于props初始化state
//StateTestChild.js
export default class StateTestChild extends
React.Component{
constructor(props){
//如果不给super传入props,则在constructor中没法使用this.props
super(props)
//使用Props传过来的数据,初始化state
this.state={desc:'现在的时间是'+props.date}
}
render(){
return <div>
<h3>我是子组件</h3>
{/* 这里直接使用state状态 */}
子组件的时间:{this.state.desc}
</div>
}
}
提示:
构造函数当中的参数可以获取props。
class 组件应该始终使用 props 参数来调用父类的构造函数。