项目页面以组件形式层层搭起来,组件提高复用性,可维护性
目录
一、函数组件
二、类组件
三、 组件的事件绑定
四、获取事件对象
五、事件绑定传递额外参数
六、组件状态
初始化状态
读取状态
修改状态
七、组件-状态修改counter案例
八、this问题说明
九、总结
一、函数组件
目标:能够独立使用函数完成react组件的创建和渲染
函数组件概念:使用JS的函数(或者箭头函数)创建的组件,就叫做 函数组件
函数组件的创建和渲染
//函数组建的创建
//创建
function Hello(){return <div>hello这是一个函数组件</div>
}
- 组件的名称必须首字母大写,react内部会根据这个来判断是组件还是普通的HTML标签
- 函数组件必须有返回值,表示该组件的 UI 结构;如果不需要渲染任何内容,则返回 null
- 组件就像 HTML 标签一样可以被渲染到页面中。组件表示的是一段结构内容,对于函数组件来说,渲染的内容是函数的返回值就是对应的内容
- 使用函数名称作为组件标签名称,可以成对出现也可以自闭合
//函数组建的创建
//创建
function Hello(){return <div>hello这是一个函数组件</div>;
}//渲染 <Hello/> 自闭和
// <Hello></Hello>成对function App() {return (<div className="App">{/*渲染Hello组件 */}<Hello/><Hello></Hello></div>);
}export default App;
二、类组件
能够独立完成类组件的创建和渲染
- 类名称也必须以大写字母开头
- 类组件应该继承 React.Component 父类,从而使用父类中提供的方法或属性
- 类组件必须提供 render 方法render 方法必须有返回值,表示该组件的 UI 结构
// 引入React
import React from 'react'// 定义类组件
class HelloComponent extends React.Component{render(){return <div>这是个一个类组件</div>}
}function App() {return (<div className="App">{/*渲染Hello组件 */}<Hello/><Hello></Hello><HelloComponent/><HelloComponent></HelloComponent></div>);
}
三、 组件的事件绑定
前端开发所有交互都是基于事件
语法:
on + 事件名称 ={事件处理程序}
例如 :
function Hello(){const clickHandler = () =>{console.log('函数组件中的事件被触发了');}return <div onClick={clickHandler}>hello这是一个函数组件</div>
}
注意,react事件采用驼峰命名法
类组件中例子,注意回调函数的写法,标准写法,实际工作中的写法
class HelloComponent extends React.Component{//事件回调函数 类中有写法差别//回调函数不加const 这是标准写法,避免this指向问题//这样写,回调函数中的this 指向的是当前的组件实例对象clickHandler =()=>{console.log('类组件中的点击事件触发了');}render(){return <div onClick={this.clickHandler}>这是个一个类组件</div>}
}
四、获取事件对象
获取事件对象e只需要在事件的回调函数中补充一个形象e即可拿到
在函数组件中试一下,打印了一个对象,里面很多属性
function Hello(){const clickHandler = (e) =>{console.log('函数组件中的事件被触发了',e);}return <div onClick={clickHandler}>hello这是一个函数组件</div>
}
为事件加个跳转
右侧打印出,然后原页跳转了
如果只想打印,不想跳转,那就要拿到事件对象e去阻止默认行为
五、事件绑定传递额外参数
触发事件传递自定义参数怎么做?
改造事件绑定为箭头函数 在箭头函数中完成参数的传递
1、只需要一个额外参数 {clickHandler} 变成 {()=>clickHandler('自定义参数')}
2、既需要事件对象e也需要额外的参数 {(e)=>clickHandler(e,'自定义参数')}
function Testl(){const clickHandler=(msg)=>{console.log('函数组件的事件被触发了',msg)}return <div onClick={()=>clickHandler('this is msg')}>点击这里</div>
}
function Testl(){const clickHandler=(e,msg)=>{console.log('函数组件的事件被触发了',e, msg)}return <div onClick={(e) => clickHandler(e,'this is msg')}>点击这里</div>
}
类组件的事件绑定
整体和函数组件方式差别不大
唯一需要注意的是 因为处于class类语境下,所定义事件回调函数以及写法有不同
定义的时候: class Fields语法
使用的时候: 需要借助this关键词获取
import React from "react";
class CComponent extends React.Component {// class FieldsclickHandler1 = (e, num) => {// 这里的this指向的是正确的当前的组件实例对象// 可以非常方便的通过this关键词拿到组件实例身上的其他属性或者方法console.log(this);};clickHandler2() {// 这里的this 不指向当前的组件实例对象而指向undefined 存在this丢失问题console.log(this);}render() {return (<div><button onClick={(e) => this.clickHandler1(e, "123")}>click me 1</button><button onClick={this.clickHandler2}>click me 2</button></div>);}
}function App() {return (<div><CComponent /></div>);
}export default App;
六、组件状态
学习目标:能够为组件添加状态和修改状态的值
在React hook 出来之前,函数式组件是没有自己的状态的,这里统一通过类组件来学习
初始化状态、读取状态、修改状态、影响视图
初始化状态
- 通过class的实例属性state来初始化
- state的值是一个对象结构,表示一个组件可以有多个数据状态
class Counter extends React.Component {// 初始化状态state = {count: 0}render() {return <button>计数器</button>} }
读取状态
- 通过this.state来获取状态
class Counter extends React.Component {// 初始化状态state = {count: 0}render() {// 读取状态return <button>计数器{this.state.count}</button>} }
修改状态
//组件状态 类组件演示
import React from "react"
class TestComponent extends React.Component{//1.定义组件状态state={//这里可以定义各种属性,全是当前组件的状态name:'ggbond'}//事件回调函数
changName=()=>{//3.修改状态//注意不可以直接赋值修改,必须通过一个方法setStatethis.setState({name:'eebond'})
}render(){//使用状态return (<div>this is TestComponent当前name为:{this.state.name}<button onClick={this.changName}>修改name</button></div>)}
}//根组件
function App(){return (<div><TestComponent/></div>)
}
export default App
点击后
- 语法
this.setState({ 要修改的部分数据 })
- setState方法作用
- 修改state中的数据状态 2.更新UI
- 思想
数据驱动视图,也就是只要修改数据状态,那么页面就会自动刷新,无需手动操作dom - 注意事项
不要直接修改state中的值,必须通过setState方法进行修改
总结:
1.编写组件其实就是编写原生类或者函数
2.定义状态必须通过state实例属性的方法提供一个对象,名称是固定的就叫做state
3.修改state中的任何属性 都不可以通过直接赋值 ,必须走setState方法 ,这个方法来自于继承得到
4.这里的this关键词,很容易出现指向错误,注意规范写法
(事件回调函数 类中有写法差别,回调函数不加const 这是标准写法,避免this指向问题,这样写,回调函数中的this 指向的是当前的组件实例对象)
类组件现在很少用,但老项目维护需要,这里是巩固基础
七、组件-状态修改counter案例
//通过类组件修改状态的方式 counter
import React from "react"
class Counter extends React.Component{//通过state定义组件状态state={count:0}//huitiaohanshu changeCount =()=>{//修改state//react体系下 ‘数据不可变’ 要setStatethis.setState({count:this.state.count + 1})}render(){return (<button onClick={this.changeCount}>{this.state.count}click</button>)}
}//根组件
function App(){return (<div>{/*渲染counter */}<Counter /></div>)
}export default App
八、this问题说明
之前,写react很麻烦,需要时刻注意this指向哪里,但现在不是事了,随着js标准的发展,主流的写法已经变成了class fields,无需考虑太多this问题
import React from "react"
//this有问题的写法
class Test extends React.Component{constructor(){super()//用bind强行修正我们的this指向//相当于在类组件初始化阶段 就可以把回调函数的this修正到//永远指向当前组件实例对象this.handler=this.handler.bind(this)}handler(){console.log(this)//这里用this.setstate去修改数据还行吗?会报错//老辈会这样做 construtor强绑定一个}render(){return (<button onClick={this.handler }>click</button>)}
}//根组件
function App(){return (<div><Test/></div>)
}export default App
未修正前:
强行修正this指向后: 得到对象
还有一个做法
箭头函数
import React from "react"
//this有问题的写法
class Test extends React.Component{handler(){console.log(this)}render(){console.log('父函数里的this指向为:',this)return (//不用constructor修正,直接在时间绑定的位置//通过箭头函数 直接沿用父函数中的this指向也是可以的,这里父函数是render//那我们的箭头函数中的this直接沿用 也是<button onClick={()=> this.handler() }>click</button>)}
}//根组件
function App(){return (<div><Test/></div>)
}export default App
同样出来的也是对象
看下父函数this指向
注意
没必要用这两个修正方案,知道有这两个方法就行,只需要记住案例中的标准写法就行