react
react介绍:
起源Facebook的内部项目。13左右开源了,在github上搜索react源码。
官网:用于构建用户界面的 JavaScript 库
1)react采用组件化开发 前后端分离(管理系统) 首选react
2)react的生态比vue还好,技术非常成熟,非常适合做大型项目。
3)背景强大,react由Facebook团队维护
4)react使用比较简单,比vue难一点 api少一点
5)react可以更好理解vue vue3.0 提升前端认知
react是最流行(世界)的框架,vue是最火(中国)框架。
react生态:
全家桶,技术栈。
react.js vue.js
react-router vue-router
redux vuex
create-react-app vue-cli
axios axios
webpack webpack
andisn elementui
react的基本使用:
- 引入react.js核心文件 ,百度react.js的CDN,下载react.js文件
- 引入react-dom.js 提供dom操作的react扩展库 ,百度下载
- 创建虚拟DOM React.createElement()
- 把虚拟DOM渲染到内页面 ReactDOM.render();
使用虚拟DOM方式有两种:
- React.createElement() 不常用
- JSX 是一个语法糖
JavaScript and XML XML是一种自定义标签语言 ,jsx可以在HTML代码中写JS代码
基础代码
两种方式创建虚拟DOM
React.createElement()
React.createElement(1,2,3)
- 参数1:什么样的虚拟元素 虚拟DOM(本质就是JS对象)
- 参数2:虚拟DOM的属性
- 参数3:虚拟DOM的内容
let vDOM = React.createElement("h1",{title:"hello react"},"你好,react")
创建一个虚拟DOM 在创建虚拟DOM时,给虚拟DOM添加class属性时,不能写class,因为class是JS的关键字。你需要写成className 就代表了class。
let content = "hello react"
let vDom1 = React.createElement("h1",{className:"box"},content);
ReactDOM.render(vDom1,document.getElementById("root1"))
JSX
在react没有模板的概念,react中的JSX类似于VUE中的模板
不能叫真实DOM,叫JSX元素,或叫JSX对象,或叫虚拟DOM
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!--react.js是核心文件 类似于vue.js-->
<script src="../js/react.development.js"></script>
<!--react-dom.js提供dom操作的扩展库-->
<script src="../js/react-dom.development.js"></script>
<!--babel会把jsx转化成createElemtn写法-->
<script src="../js/babel.js"></script>
</head>
<body>
<div id="app">
</div>
<script type="text/babel">
// 在react没有模板的概念,react中的JSX类似于VUE中的模板
// 下面的代码,不能叫真实DOM,叫JSX元素,或叫JSX对象,或叫虚拟DOM
let vDOM = (<div>
<ul>
<li>vue</li>
<li>react</li>
</ul>
</div>)
ReactDOM.render(vDOM,document.getElementById("app"))
</script>
</body>
</html>
jsx中可以写表达式,不能放语句,需要用 { } 包起来,在JSX中,需要把JSX表达式放到一个{}中 才会解析,类似于vue中{{}}
ReactDOM.render(<h1>
<p>
<span>{1+1}</span>
</p>
</h1>,document.getElementById("root"))
可以放函数调用,{}中也可以放一个函数调用
function sum(){
return 123;
}
ReactDOM.render(<h1>
<p>
<span>{sum()}</span>
</p>
</h1>,document.getElementById("root"))
放三目运算符,{}也可以放一个三目运算符
let isLove = true;
ReactDOM.render(<h1>
<p>
<span>{isLove ? "是真爱":"是骗子"}</span>
</p>
</h1>,document.getElementById("root"))
想在JSX中写注释 /* */
注释也是JS的内容,只要是JS的内容,都要放到{}中的
JSX中只能使用多行注释 注释也需要放到一个{}中
let isLove = true;
ReactDOM.render(<h1>
<p>
{/* 这是一个注释 */}
<span>{isLove ? "是真爱":"是骗子"}</span>
</p>
</h1>,document.getElementById("root"))
在JSX中写行内样式,那样式需要写成对象的形式,对象是JS代码,需要放到{}中
let isLove = true;
ReactDOM.render(<h1>
<p>
<span style={{color:"red"}}>{isLove ? "是真爱":"是骗子"}</span>
</p>
</h1>,document.getElementById("root"))
渲染数组
let singer=[
{name:"周杰伦1",age:30},
{name:"周杰伦2",age:40},
{name:"周杰伦3",age:50},
{name:"周杰伦4",age:60},
]
ReactDOM.render(<ul>
<li>{singer[0].name}</li>
<li>{singer[1].name}</li>
<li>{singer[2].name}</li>
<li>{singer[3].name}</li>
</ul>,document.getElementById("root"))
使用map映射简化数组渲染
ReactDOM.render(<ul>{singer.map((item,index)=>
{return <li key={index}>{item.name}</li>})}</ul>,document.getElementById("root"))
循环数组
let vDOM = (
<ul>
{
arr.map((item,index)=><li key={item}>编号:{index+1}----姓名:{item}</li>)
}
</ul>
)
ReactDOM.render(vDOM,document.getElementById("app"))
JSX知识点
1) JSX本质就是一个虚拟DOM,最外层,必须使用根标签包一下。
2) JSX中的标签是成对出现的,如果是单标签,也必须闭合。
3) JSX中可以放JS代码,必须放到{}中。
4) {}中可以放表达式 {1+1} {sum()} {10>9} 不能放语句
5) JSX中只能使用多行注释,必须使用{}包起来 {/ * xxxx * /}
6) JSX中写行内样式,必须写成对象的形式,对象必须放到{} <h1 style={{color:"red"}}}></h1>
7) JSX中,写class属性,必须写成className,写for属性,必须写htmlFor
组件
在react中声明一个组件,有两种方式:
- 通过class类的形式
- 通过函数的形式
在react中为了和普通的html标签区分,组件的名字统一大写。只有大写了,react才能识别出你是一个组件。
一个组件中的jsx,必须有一个根标签。
通过类创建组件和通过函数创建组件区别:
- 通过类创建的组件中可以放数据(状态),这类组件叫有状态组件。
- 通过函数创建的组件不可以放数据(状态),这类组件叫无状态组件。
ReactDOM.render渲染组件的流程:
- 判断渲染的内容是否是组件,判定的依据首字母是否大写
- 如果是组件,判断出你这个组件是通过类创建的,还是通过函数创建的。
如果是函数创建的:得到函数的返回值 函数返回jsx —> 得到虚拟DOM。
如果是类创建的:调用render函数 render函数返回jsx —> 得到虚拟DOM - 转虚拟DOM,转化成真实DOM
- 把真实DOM插入到挂载点 插入到真实DOM。
通过类创建组件
使用class创建组件:
- 内部必须实现render方法,render方法必须return一个jsx。 ----> 虚拟DOM 本质是JS对象
- 必须继承React.Component
- 组件内部的数据,也可以由外部提供,内部需要重写construtor,参数是props,props就是接收外部的数据
还需要写super(props); 组件内部就可以使用this.props.xxx - class创建的组件的数据源也可以是props。
类中的 render() 是钩子函数,不需要自己调用,react内部会在合适的时机调用
return 会返回一个jsx
使用组件
class MyHeader extends React.Component{
render(){
return(<div><h1>头部组件</h1></div>)
}
}
class MyFooter extends React.Component{
render(){
return(<div><h1>尾部组件</h1></div>)
}
}
class MyWraper extends React.Component{
render(){
return(<div>
<MyHeader />
<MyFooter/>
</div>)
}
}
ReactDOM.render(<MYWraper />,document.getElementById("root"))
组件传参
class MyComponent extends React.Component{
constructor(props){
super(props)
}
render(){
let style = {
backgroundColor:"red",
width:400,
height:400
}
return(<div style={sryle}>
<h1>它的名字:{this.props.name}</h1>
</div>)
}
}
// name="wangcai" 表示传递给组件内部的数据是字符串,也可以加{}
// score="[10,20,30]" 这样写,表示传递给组件内部的也是字符串
// score=[10,20,30] 这样写不对 为了[]是JS代码,需要放到{},{[10,20,30]}
ReactDOM.render(<MyComponent name={"wangxai"} score={[10,20,30]}/>,document.getElementById("root"))
</script>
接收的数据校验,设置默认值
在头部标签< head >需要引入校验js文件,prop-types.js
<script src="../js/prop-types.js"></script>
class Shop extends React.Component{
constructor(props) {
super(props);
}
/*static propTypes = {
name:PropTypes.number.isRequired
}*/
static defaultProps = {
name:"wangcai"
}
render(){
return(
<div>
<a href={this.props.link}>{this.props.name}</a>
</div>
)
}
}
// ReactDOM.render(<Shop name="JD" link="http://www.baidu.com"/>,document.getElementById("root"))
ReactDOM.render(<Shop link="http://www.baidu.com"/>,document.getElementById("root"))
通过函数创建组件
使用函数创建组件:
- 必须return一个JSX 因为要根据JSX获取到一个虚拟DOM。
- 在使用此组件时,可以给组件内部传递数据,函数可以通过形参props来接收数据。
- 一个组件内部需要使用数据,我们可以在外面传入。一个组件的数据源可以是props
使用组件
// 不管是什么方式创建组件,组件名一定要大写
function Header(){ // 你要当成普通的组件,需要在函数中返回一个jsx
return(
<div>
<h1>我是header组件</h1>
</div>
)
}
ReactDOM.render(<Header />,document.getElementById("root"))
组件传参
function MyComponet(props){ // 问:JS的function中有this吗? 答:有 因为JS中的function也可以是类
return(
<div>
<h2>它的名字是:{props.name},年龄是:{props.age},分数是:{props.score}</h2>
</div>
)
}
ReactDOM.render(<MyComponet name="xq" age={100} score={["a","b"]} />,document.getElementById("root"))
组件是虚拟DOM的集合
function Artical() {
return(
<div>
<Header/>
<Content/>
<Footer/>
</div>
)
}
接收数据校验,指定默认值
需要引入校验js文件,prop-types.js
<script src="../js/prop-types.js"></script>
function Shop(props){
return(
<div>
<a href={props.link}>{props.name}</a>
</div>
)
}
Shop.propTypes={
name:PropTypes.string.isRequired,
link:PropTypes.string.isRequired
}
ReactDOM.render(<Shop name="淘宝网" link="http://www.taobao.com" />,document.getElementById("root"))
Shop.defaultProps={
name:"JD",
link:"http://www.jd.com"
}
ReactDOM.render(<Shop />,document.getElementById("root"))
组件的状态state
- 使用函数创建组件里面是没有state的,这类组件我们叫无状态组件。
- 使用class创建组件里面是可以有state的,这个组件我们叫有状态组件。
一个组件的数据源:
- 对于函数创建组件,数据源是props。
- 对于class创建的组件,数据源可以是props,也可以是state。
对于class创建的组件,state是核心,有人也把react组件当成一个状态机。
不需要外面输入数据,类似于vue中的data。
状态的使用
class Person extends React.Component{
constructor(props) {
super(props);
// 状态机
this.state = { // this.state是给创建出来的对象添加一个私有属性
name:"wangcai",
age:100,
sex:"男",
friend:"xiaoqiang"
}
}
render(){
return(
<div>
<h2>个人介绍</h2>
<p>姓名:{this.state.name}, 年龄:{this.state.age}, 性别:{this.state.sex},朋友:{this.state.friend}</p>
<p>--------------------</p>
<button onClick={()=>this._dealChangePerson()}>换一个人</button>
</div>
)
}
_dealChangePerson(){
// 更新状态机 当状态变化了,会自动调用render
this.setState({
name:"xiaohua",
age:100,
sex:"女",
friend:"xiaohong"
})
}
}
ReactDOM.render(<Person />,document.getElementById("root"))
props和state共存
class Person extends React.Component{
constructor(props) {
super(props);
// 状态机
this.state = { // this.state是给创建出来的对象添加一个私有属性
name:"wangcai",
age:100,
sex:"男",
friend:"xiaoqiang"
}
}
render(){
return(
<div>
<h2>个人介绍(state中的数据)</h2>
<p>姓名:{this.state.name}, 年龄:{this.state.age}, 性别:{this.state.sex},朋友:{this.state.friend}</p>
<button onClick={()=>this._dealChangePerson1()}>换一个人</button>
<p>--------------------------------------</p>
<h2>个人介绍(props中的数据,不要直接修改props接收的数据)</h2>
<p>姓名:{this.props.personObj.p_name}, 年龄:{this.props.personObj.p_age}, 性别:{this.props.personObj.p_sex},朋友:{this.props.personObj.p_friend}</p>
<button onClick={()=>this._dealChangePerson2()}>换一个人</button>
</div>
)
}
_dealChangePerson1(){
// 更新状态机 当状态变化了,会自动调用render
this.setState({
name:"xiaohua",
age:100,
sex:"女",
friend:"xiaohong"
})
}
_dealChangePerson2(){
/* this.setProps({ // 没有setProps
p_name : "xxxxx"
})*/
// this.props.personObj.p_name = "xxxxx"
}
}
let outData = {
p_name:"xiaobai",
p_age:666,
p_sex:"女",
p_friend:"xiaohei"
}
ReactDOM.render(<Person personObj={outData}/>,document.getElementById("root"))
如果要props中的数据时,因为props中的数据不能直接修改,需要将数据传到内部的state中,然后修改state的数据
class Person extends React.Component{
constructor(props) {
super(props);
let {p_name,p_age,p_sex,p_friend} = this.props.personObj;
// 状态机 把接收到的数据给state
this.state = { // this.state是给创建出来的对象添加一个私有属性
name:p_name,
age:p_age,
sex:p_sex,
friend:p_friend
}
}
render(){
let {name,age,sex,friend} = this.state
return(
<div>
<h2>个人介绍</h2>
<p>姓名:{name}, 年龄:{age}, 性别:{sex},朋友:{friend}</p>
<button onClick={()=>this._dealChangePerson()}>换一个人</button>
</div>
)
}
_dealChangePerson(){
// 更新状态机 当状态变化了,会自动调用render
this.setState({
name:"xiaohua",
age:100,
sex:"女",
friend:"xiaohong"
})
}
}
let outData = {
p_name:"xiaobai",
p_age:666,
p_sex:"女",
p_friend:"xiaohei"
}
ReactDOM.render(<Person personObj={outData}/>,document.getElementById("root"))
组件数据校验
通过prop-types.js进行校验
对于函数创建的组件校验方式:
Shop.propTypes={
name:PropTypes.string.isRequired,
link:PropTypes.string.isRequired
}
对于class创建的组件校验方式:
static propTypes = {
name:PropTypes.number.isRequired
}
计算器案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/prop-types.js"></script>
<script src="../js/babel.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
// HTML CSS JS
class Counter extends React.Component{
static propTypes = {
step:PropTypes.number
}
static defaultProps = {
step:1
}
constructor(props) {
super(props);
// 定义一个状态机
this.state = { res:0 }
}
render(){
let { res } = this.state
let { step } = this.props;
return(
<div>
<h3>结果是:{res}</h3>
<a href="http://www.baidu.com" onClick={(e)=>this._addNum(step,e)}>加{step}</a>
<p>-------------------------</p>
</div>
)
}
_addNum(step,e){
e.preventDefault(); // 阻止默认事件
// 更新状态机
this.setState({
res:this.state.res+step
})
}
}
let vDom = (
<div>
<Counter step={1}/>
<Counter step={2}/>
<Counter step={3}/>
<Counter />
</div>
)
ReactDOM.render(vDom,document.getElementById("root"))
</script>
</body>
</html>
表单数据处理
想获取输入框中的内容:
-
方式1:把非受控的输入框,变成受控的输入框,获取内容就是获取状态
-
方式2:获取DOM元素 input
传统操作:document.getelementByid(“input”); 不推荐的
ref,可以给dom元素起一个ref名字,通过this.
修改非控输入框
不受控的输入框:它里面的内容不受状态的控制
<input type="text" />
受控的输入框: 受状态的控制,输入框显示状态的内容,不能发生改变
<input type="text" value={this.state.content} />
修改非控输入框
class Add extends React.Component{
constructor(props){
super(props)
//定义了一个状态机
this.state={
content:"默认内容"
}
}
render(){
return(
<div>
非受控的:<input type="text" />
受控的:<input
type="text" value={this.state.content}
onChange={(e)=>this._dealChange(e)} />
<h3>{this.state.content}</h3>
</div>
)
}
//当输入框中的内容发生改变,会调用change事件
_dealChange(e){
// 更新状态机
this.setState({
content:e.target.value
})
}
}
ReactDOM.render(<Add />,document.getElementById("root"))
ref 获取DOM元素
方式一 :ref 后面跟字符串,已经淘汰了
- 第1步:< input ref=“item” type=“text” /> ref后面跟一个字符串
- 第2步:this.refs.item.value 获取输入框中的数据
class Add extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<div>
<input ref="item" type="text" />
<button onClick={()=>this._dealClick()}>获取dom</button>
</div>
)
}
_dealClick(){
console.log(this.refs.item) //获取DOM元素
console.log(this.refs.item.value) //获取输入框的内容
console.log(this.refs["item"].value)
}
}
ReactDOM.render(<Add />, document.getElementById("root"))
方式二:
ref后面跟上一个回调函数,回调函数的参数就是当前的DOM元素
//input 是形参,这个形参就是输入框
<input ref={(input)=>{
this.xxx = input; // 当前的DOM元素挂载到当前组件对象的xxx属性上面的
}} type="text" />
render(){
return(
<div>
<input ref={(input)=>{
this.xxx = input
}} type="text" />
<button onClick={()=>this._dealClick()}>获取DOM元素</button>
</div>
)
}
_dealClick(){
console.log(this.xxx)
console.log(this.xxx.value)
}
方式三:创建ref属性 常用
- this.ref1 = React.createRef(); ref1是一个私有属性
- < input ref={this.ref1} type=“text” />
- this.ref1.current.value 获取DOM元素中的内容
class Add extends React.Component{
constructor(props) {
super(props);
// 创建一个ref
this.ref1 = React.createRef(); // ref1是一个私有属性
}
render(){
return(
<div>
<input ref={this.ref1} type="text" />
<button onClick={()=>this._dealClick()}>获取DOM元素</button>
</div>
)
}
_dealClick(){
// console.log(this.ref1.current) //DOM元素
console.log(this.ref1.current.value) //输入框的值
}
}
ReactDOM.render(<Add />, document.getElementById("root"))
上面的ref的三种使用方式,都是用在html标签上面的,当前ref也可以用在组件上,
如果用在组件上,可以获取组件对象。 如果用在标签上,可以获取DOM元素。
本文介绍了React的基础知识,包括React的起源、特点及应用场合,并详细讲解了React的基本使用方法,如虚拟DOM的创建与渲染,以及如何通过类和函数创建组件。

791

被折叠的 条评论
为什么被折叠?



