01脚手架+JSX+条件渲染+循环渲染+样式处理+组件(函数组件+class类组件)+事件处理+state数据+表单处理(受控+非受控)
npm init -y
npm i react react-dom
2.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <!-- 1.引入 --> <script src="./node_modules/react/umd/react.development.js"></script> <script src="./node_modules/react-dom/umd/react-dom.development.js"></script> </head> <body> <div id="root"></div> <script> // 2.创建react元素 let myh1 = React.createElement("h1", null, "我是h1") // 3.渲染到页面 ReactDOM.render(myh1, document.getElementById("root")) </script> </body> </html>
npx create-react-app my-pro
npx 目的:提升包内提供的命令行工具的使用体验 (my-pro 自己定义的项目名称)
原来:先安装脚手架包,再使用这个包中提供的命令,现在:无需安装脚手架包,就可以直接使用这个包提供的命令
2.启动项目,在项目根目录执行命令:
cd my-pro
npm start
打开项目后只留下index.js即可(入口文件,相当于vue的main.js,App.js相当于vue的App.vue根基组件)
// 1 引入 react react-dom import React from 'react' import ReactDOM from 'react-dom' // 2 创建react元素 let mydiv=React.createElement("div",{className:"box"},'我是div') // 3 渲染到页面 ReactDOM.render(mydiv,document.getElementById("root"))
由于通过createElement()方法创建的React元素有一些问题,代码比较繁琐,结构不直观,无法一眼看出描述的结构,不优雅,用户体验不爽
JSX的概述:jsx 在js中可以写 html
import React from 'react' import ReactDom from 'react-dom' let mydiv = < h1 > 我是通过JSX创建的元素11</h1> ReactDom.render(mydiv, document.getElementById("root"))nt.getElementById("root"))
JSX 不是标准的ECMAScript语法,它是ECMAScript的语法拓展,需要使用babel编译处理后,才能在浏览器环境中使用 ,编译JSX语法的包: @bable/preset-react
特殊属性名:class -> className,for -> htmlFor,tabindex -> tabIndex
语法:{JavaScritp表达式}
let content = '插入的内容'
let h1 = <h1>我是通过JSX创建的元素+ {content}</h1>
注意:只能写简单的三元表达式、变量、+-*/%四则运算
在 react中 没有 v-if v-for类似的 指令 react写法类似 原生js
import React from 'react' import ReactDom from 'react-dom' // 条件渲染 let isLoading = false let mydiv = '' if (isLoading) { mydiv = < div > Loading... </div> } else { mydiv = < div > 加载完成 </div> } ReactDom.render(mydiv, document.getElementById("root"))
map()方法循环数组,把return后面的值组成一个新数组返回,尽量减少使用索引代表key
数组.map(function(item,index,arr){})
import React from 'react' import ReactDom from 'react-dom' // 循环渲染 let arr = [ { id: 1, name: '三国演义' }, { id: 2, name: '水浒传' }, { id: 3, name: '红楼梦' }, { id: 4, name: '西游记' }, ] // let mydiv = <ul > { // arr.map(function(item, index, arr) { // return <li key = { item.id } > 名字: { item.name } </li> // }) // } </ul> let mydiv = <ul > { arr.map(item => { return <li key = { item.id } > 名字: { item.name } </li> }) } </ul> ReactDom.render(mydiv, document.getElementById("root"))
.box { color: red; background-color: pink }
import React from 'react' import ReactDom from 'react-dom' import './index.css' // let mydiv=<div> // <p style={ {'color':'red',"backgroundColor":"pink"} }>123</p> // </div> let mydiv = <div > <p className = "box" > 123 </p> </div> ReactDom.render(mydiv, document.getElementById("root"))
5. React组件(函数组件+class类组件)
函数组件 1.首字母大写 2.必须有返回值 return return null
import React from 'react' import ReacrDOM from 'react-dom' // 函数组件 function Header() { return <div > 我是div </div> } ReacrDOM.render( < Header > </Header>,document.getElementById('root'))
class类组件
import React from 'react' import ReacrDOM from 'react-dom' // class类组件 class Header extends React.Component { render() { return <div > 我是div1 </div> } } ReacrDOM.render( < Header > </Header>,document.getElementById('root'))
ES6中的class类
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <script> // function Person() { // this.name = '建林', // this.money = '壹佰亿' // } // let p1 = new Person() // console.log(p1.money) //壹佰亿 class Person { name = '建林' money = '壹佰亿' } let p2 = new Person() console.log(p2.name) //建林 // class Son extends Person { // name = '思聪' // } class Son extends Person { constructor() { super() //超级也就是class Person this.name = '思聪' } } let p3 = new Son() console.log(p3.name) //思聪 </script> </body> </html>
独立组件
components/Footer.js
import React from 'react' export default class Footer extends React.Component { render() { return ( < div > 我是Footer组件 </div> ) } }
// 3 导出组件也可
//export default Footer
index.js
import React from 'react' import ReacrDOM from 'react-dom' import Footer from './components/Footer' ReacrDOM.render( < Footer> </Footer>,document.getElementById('root'))
事件绑定
语法:on+事件名称=事件处理函数,比如 onClick = function(){}
注意:React事件采用驼峰命名法
import React from 'react' import ReacrDOM from 'react-dom' class Header extends React.Component { clickHandeld() { console.log('别点了,疼死了') } render() { return ( //return 后面必须有东西 <button onClick = { this.clickHandeld } > 按钮点击 </button> //this指的是class Header ) } } ReacrDOM.render( < Header > </Header>,document.getElementById('root'))
React中的事件对象叫做:合成事件(兼容所有浏览器,无需担心跨浏览器兼容问题)
除兼容所有浏览器外,它还拥有和浏览器原生事件相同的接口,包括 stopPropagation()
和 preventDefault()
如果你想获取到原生事件对象,可以通过 nativeEvent
属性来进行获取
注意:this.clickHandeld后不加()否则会自动触发一次
import React from 'react' import ReacrDOM from 'react-dom' class Header extends React.Component { clickHandeld(e) { // console.log('别点了,疼死了') // e.preventDefault() //阻止行为 console.log(e.nativeEvent) // 获取原生事件对象 } render() { return ( //return 后面必须有东西 <button onClick = { this.clickHandeld } > 按钮点击 </button> ) } } ReacrDOM.render( < Header > </Header>,document.getElementById('root'))
-
Clipboard Events 剪切板事件
-
事件名 :onCopy onCut onPaste
-
属性 :DOMDataTransfer clipboardData
-
-
compositionEvent 复合事件
-
事件名: onCompositionEnd onCompositionStart onCompositionUpdate
-
属性: string data
-
-
Keyboard Events 键盘事件
-
事件名:onKeyDown onKeyPress onKeyUp
-
属性: 例如 number keyCode 太多就不一一列举
-
-
Focus Events 焦点事件 (这些焦点事件在 React DOM 上的所有元素都有效,不只是表单元素)
-
事件名: onFocus onBlur
-
属性: DOMEventTarget relatedTarget
-
-
Form Events 表单事件
-
事件名: onChange onInput onInvalid onSubmit
-
-
Mouse Events 鼠标事件
-
事件名:
onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit
onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave
onMouseMove onMouseOut onMouseOver onMouseUp
-
-
Pointer Events 指针事件
-
事件名:
onPointerDown onPointerMove onPointerUp onPointerCancel onGotPointerCapture
onLostPointerCapture onPointerEnter onPointerLeave onPointerOver onPointerOut
-
-
Selection Events 选择事件
-
事件名:onSelect
-
-
Touch Events 触摸事件
-
事件名:onTouchCancel onTouchEnd onTouchMove onTouchStart
-
-
UI Events UI 事件
-
事件名: onScroll
-
-
Wheel Events 滚轮事件
-
事件名:onWheel
-
属性:
number deltaMode
number deltaX
number deltaY
number deltaZ
-
-
Media Events 媒体事件
-
事件名:
onAbort onCanPlay onCanPlayThrough onDurationChange onEmptied onEncrypted
onEnded onError onLoadedData onLoadedMetadata onLoadStart onPause onPlay
onPlaying onProgress onRateChange onSeeked onSeeking onStalled onSuspend
onTimeUpdate onVolumeChange onWaiting
-
-
Image Events 图像事件
-
事件名:onLoad onError
-
-
Animation Events 动画事件
-
事件名:onAnimationStart onAnimationEnd onAnimationIteration
-
-
Transition Events 过渡事件
-
事件名:onTransitionEnd
-
-
Other Events 其他事件
-
事件名: onToggle
-
import React from 'react' import ReactDOM from 'react-dom' class My extends React.Component { // 方法一: // constructor() { // super() // this.state = { // count: 0 // } // } // 方法二: state = { count: 1 } render() { return <div > 计数器: { this.state.count } </div> } } ReactDOM.render( < My > </My>,document.getElementById("root"))
import React from 'react' import ReactDOM from 'react-dom' class My extends React.Component { // 方法一: // constructor() { // super() // this.state = { // count: 0 // } // } // 方法二: state = { count: 1 } render() { return ( <div> <div> 计数器:{ this.state.count}</div> <button onClick = { () => { this.setState({ count: this.state.count + 1 }) } }> +1 </button> </div> ) } } ReactDOM.render( <My> </My>,document.getElementById("root"))
import React from 'react' import ReactDOM from 'react-dom' class My extends React.Component { // 方法一: // constructor() { // super() // this.state = { // count: 0 // } // } // 方法二: state = { count: 1 } addCount(){ this.setState({ count: this.state.count + 1 }) } render() { return ( <div> <div> 计数器:{ this.state.count}</div> {/* <button onClick = {() => { this.setState({ count: this.state.count + 1 }) } }> +1 </button> */} <button onClick = {this.addCount}> +1 </button> </div> ) } } ReactDOM.render( <My> </My>,document.getElementById("root"))
在JSX中我们写的事件处理函数可以找到this,原因在于在JSX中我们利用箭头函数,箭头函数是不会绑定this,所以会向外一层去寻找,外层是render方法,在render方法里面的this刚好指向的是当前实例对象
1.改为箭头函数就不会报错了
addCount=()=>{ this.setState({ count: this.state.count + 1 }) }
2.在外层包裹箭头函数
<button onClick = {()=>{ this.addCount() }}> +1 </button>
3.bind改变this指向(现在this指向My)
<button onClick = {this.addCount.bind(this)}> +1 </button>
受控组件/表单(当没有onChange事件时,报错)
import React from 'react' import ReactDOM from 'react-dom' class My extends React.Component{ state={ username:'张三' } changevalue=(e)=>{ this.setState({ username:e.target.value }) } render(){ console.log(this.state) return( <div> <p>{this.state.username}</p> <input type="text" value={this.state.username} onChange={this.changevalue}></input> </div> ) } } ReactDOM.render(<My />,document.getElementById('root'))
非受控组件/表单----
调用 React.createRef() 方法创建ref对象
将创建好的 ref 对象添加到文本框中
通过ref对象获取到文本框的值
import React from 'react' import ReactDOM from 'react-dom' class App extends React.Component{ inputRef=React.createRef() getvalue=()=>{ console.log(this.inputRef) console.log(this.inputRef.current.value) } render(){ return<div> <input type="text" ref={this.inputRef} /> <button onClick={this.getvalue}>点击获取数值</button> </div> } } ReactDOM.render(<App />,document.getElementById("root"))