React是一个用于构建用户界面的javaScript库,起源于facebook的内部项目,后续在13年开源了出来
新建挂载点
<div id="root">div>
React的引用
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js">script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js">script>
创建React元素并渲染到页面
<script>
// 参数一:元素名称;参数二:元素属性;参数三:元素的子节点
const title = React.createElement('h1', null, 'Hello React')
// 参数一:要渲染的react元素;参数二:挂载点
ReactDOM.render(title, document.getElementById('root'))
script>
初始化项目
npx create-react-app myreact
npm start
删除 src 目录下的 所有文件,然后创建 index.js 文件
导入react和react-dom两个包
import React from 'react'
import ReactDOM from 'react-dom'
创建元素
let h1 = React.createElement('h1', null, 'Hello 初辰')
渲染到页面
ReactDOM.render(h1, document.getElementById('root'))
使用 createElement() 方法创建复杂 dom 结构
const ul = React.createElement('ul', null,
React.createElement('li', null, 'Hello'),
React.createElement('li', null, 'React'),
React.createElement('li', null,
React.createElement('span', null, '我是'),
React.createElement('span', null, '初辰')
)
)
使用 JSX 语法创建复杂 dom 结构
const ul =
<ul>
<li>Helloli>
<li>Reactli>
<li>
<span>我是span>
<span>初辰span>
li>
ul>
由于通过 createElement() 方法创建的 React 元素有一些问题,代码比较繁琐,结构不直观,无法一眼看出描述的结构,不优雅,用户体验不爽
JSX是JavaScript XML 的简写,表示在JavaScript代码中写HTML格式的代码
优势:声明式语法更加直观,与HTML结构相同,降低了学习成本,提升开发效率
使用JSX语法创建react元素
let h1 = <h1>初辰通过JSX创建的元素h1>
使用ReactDOM来渲染元素
ReactDOM.render(h1,document.getElementById('root'))
/>
来结束JSX是来描述页面的结构,一般在编写业务逻辑渲染页面的时候,需要涉及到传递值,调用函数,判断条件,循环等,这一些在JSX中都能得到支持
语法:
{JavaScritp表达式}
例子:
let content = '插入的内容'
let h1 = <h1>初辰通过JSX创建的元素+ {content}h1>
根据不同的条件来渲染不同的JSX结构
let isShow = false
let text = ''
if (isShow === true) {
text = '初辰1'
} else {
text = '初辰2'
}
写JSX的条件渲染与我们之前编写代码的逻辑是差不多的,根据不同的判断逻辑,返回不同的 JSX结构,然后渲染到页面中
map ()
方法map()
遍历谁,就给谁添加key属性let arr = [
{id:1,name:'三国演义'},
{id:2,name:'水浒传'},
{id:3,name:'西游记'},
{id:4,name:'红楼梦'}
]
let ul = (<ul>
{arr.map(item => <li key={item.id}>{item.name}li>)}
ul>)
ReactDOM.render(ul,document.getElementById('root'))
行内样式 -style
在style
里面我们通过对象的方式传递数据
let ul = (<ul style={{ 'color': 'red', "backgroundColor": 'pink' }}>
{arr.map(item => <li key={item.id}>{item.name}li>)}
类名 -className
创建CSS文件 index.css
编写样式代码
.container {
text-align: center;
color: rgb(124, 11, 11);
background-color: rgb(105, 105, 243);
}
在js中进行引入,然后设置类名即可
import './index.css'
let ul = (<ul className='container'>
{arr.map(item => <li key={item.id}>{item.name}li>)}
ul>)
function Hello () {
return (
<div>这是初辰的第一个函数组件div>
)
}
利用ReactDOM.render()进行渲染
ReactDOM.render(<Hello />, document.getElementById('root'))
class
创建的组件React.Component
父类,从而可以使用父类中提供的方法或者属性render
方法render
方法中必须要有return
返回值class Hello extends React.Component {
render () {
return (
<div>这是初辰的第一个类组件div>
)
}
}
通过ReactDOM进行渲染
ReactDOM.render(<Hello />,document.getElementById('root'))
创建Hello.js, 在Hello.js 中导入React,创建组件,在Hello.js中导出
import React from 'react'
class fn extends React.Component {
render () {
return (
<div>单独抽离出来的 Hellodiv>
)
}
}
export default fn
在index.js中导入Hello组件,渲染到页面
import ReactDOM from 'react-dom';
import Hello from './hello'
ReactDOM.render(<Hello />, document.getElementById('root'))
onClick = function(){}
React
事件采用驼峰命名法class Hello extends React.Component {
clickHandle () {
console.log('点击了')
}
render () {
return (
<button onClick={this.clickHandle}>点我点我点我button>
)
}
}
stopPropagation()
和 preventDefault()
nativeEvent
属性来进行获取 clickHandle (e) {
console.log(e.nativeEvent)
}
事件 | 事件名 | 属性 |
---|---|---|
Clipboard Events 剪切板事件 | onCopy onCut onPaste | DOMDataTransfer clipboardData |
compositionEvent 复合事件 | onCompositionEnd onCompositionStart onCompositionUpdate | string data |
Keyboard Events 键盘事件 | onKeyDown onKeyPress onKeyUp | number keyCode |
Focus Events 焦点事件 | 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 | |
Image Events 图像事件 | onLoad onError | |
Animation Events 动画事件 | onAnimationStart onAnimationEnd onAnimationIteration |
state基本使用
this.state
来获取状态 state = {
count: 0
}
render () {
return (
<div>计数器 :{this.state.count}div>
)
}
addCount = () => {
this.setState({
count: this.state.count + 1
})
}
render () {
return (
<div>
<div>计数器 :{this.state.count}div>
<button onClick={this.addCount}>+1button>
div>
)
}
state
里面的值我们需要通过 this.setState()
来进行修改setState
导致了数据的变化,就会重新调用一次render
方法,重新渲染当前组件props
来实现props
的作用:接收传递给组件的数据props
接收数据,类组件通过 this.props
接收数据class App extends React.Component {
render () {
return (
<div>接收到的数据:{this.props.text}div>
)
}
}
ReactDOM.render( , document.getElementById('root'))
props
是只读属性,不能对值进行修改props
传递给super()
,否则,无法在构造函数中获取到props
,其他的地方是可以拿到的state
数据state
中的数据props
接收父组件中传递的数据class App extends React.Component {
render () {
return (
<div>接收到的数据:{this.props.text}div>
)
}
}
ReactDOM.render( , document.getElementById('root'))
class Fat extends React.Component {
getSonMsg = (msg) => {
console.log(msg);
}
render () {
return (
<Son getMsg={this.getSonMsg} />
)
}
}
class Son extends React.Component {
handleClick = () => {
this.props.getMsg('子元素的值')
}
render () {
return (
<button onClick={this.handleClick}>点我传值button>
)
}
}
ReactDOM.render(<Fat />, document.getElementById('root'))
如果出现层级比较多的情况下(例如:爷爷传递数据给孙子),我们会使用Context
来进行传递
使用步骤
调用 React.createContext()
创建 Provider(提供数据)
和 Consumer(消费数据)
两个组件
const {Provider,Consumer} = React.createContext()
使用Provider
组件作为父节点,设置value
属性,表示要传递的数据
<Provider value="李白"><Node />Provider>
哪一层想要接收数据,就用Consumer
进行包裹,在里面回调函数中的参数就是传递过来的值
<Consumer>{data => <span>子节点--{data}span>}Consumer>
children
属性: 表示组件标签的子节点,当组件标签有子节点时,props
就会有该属性children
属性与普通的props
一样,值可以使任意值(文本、react元素、组件、甚至是函数)function Fat (props) {
return (
<div>组件的子节点:{props.children}div>
)
}
ReactDOM.render(<Fat>初辰Fat>, document.getElementById('root'))
props
是外来的,无法保证组件使用者传入什么格式的数据props
的类型、格式等props
导致的错误,给出明确的错误提示,增加组件的健壮性import PropTypes from 'prop-types'
Fat.propTypes = {
name: PropTypes.string
}
安装
npm install --save react-router-dom
导入路由的三个核心组件: Router / Route / Link
React
应用只需要使用一次Router
: HashRouter
和BrowserRouter
HashRouter
: 使用URL的哈希值实现 (localhost:3000/#/first)BrowserRouter
:使用H5的history API实现(localhost3000/first)Link
会编译成a标签,而to属性会被编译成 a标签的href属性Route
组件:指定路由展示组件相关信息path
属性:路由规则,这里需要跟Link组件里面to属性的值一致component属性
:展示的组件Route
写在哪,渲染出来的组件就在哪import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
使用Router 组件包裹整个应用
使用Link组件作为导航菜单(路由入口)
首页
使用Route组件配置路由规则和要展示的组件(路由出口)
history
是React路由提供的,用于获取浏览器历史记录的相关信息push(path)
:跳转到某个页面,参数path
表示要跳转的路径go(n)
:前进或后退功能,参数n表示前进或后退页面数量this.props.history.push('/first')
注意:只有使用 Route 组件的导航,才拥有 history 属性。
withRouter
, 作用是将一个组件包裹进Route
里面, 然后react-router
的三个对象history
, location
, match
就会被放进这个组件的props属性中。所以withRouter
的作用就是, 如果我们某个东西不是一个Router
, 但是我们要依靠它去跳转一个页面, 就可以使用withRouter来做.import { withRouter } from 'react-router-dom'
.....
export default withRouter(fn)