1.采用组件化模式,声明式编码,提高开发效率及组件复用率
2.在React Native中可以使用React语法进行移动端开发
3.使用虚拟DOM+优秀的Diffing算法,尽量减少与真实DOM的交互
虚拟dom:
1.本质式object类型的对象(一般对象)
2.虚拟dom比较‘轻’,真实dom比较‘重’,因为虚拟dom是react内部使用,无需真实dom这么个那么多的属性
3.虚拟dom最终会被react转化为dom,呈现在页面上
扩展:debugger 断点
jsx语法规则:
2.标签中混入js表达式的时候用{}
3.样式的类名指定不要用class,要用className
4.内联样式,要用style={ {key:value}}的形式去写
5.只有一个根标签
6.标签必须闭合 单标签可以写成
7.标签首字母
表达式:一个表达式会产生一个值,可以放在任何一个需要的地方
语句(代码)
简单组件是没有状态的
复杂组件是有状态的
使用步骤
const {Provider,Consumer} = React.createContext()
使用Provider组件作为组件的父节点
那一层想要接受父节点传来的数据用Consumer进行包裹,在里面回调函数中的参数就是传递过来的值
常见的约束规则
创建的类型: array、bool、func、number、object、string
React元素类型: element
必填项: isRequired
特定结构的对象: shape({})
执行时机:组件创建时(页面加载时)
执行顺序
触发时机
钩子函数 | 触发时机 | 作用 |
---|---|---|
constructor | 创建组件时,最先执行 | 1.初始化state 2.为事件处理程序绑定this |
render | 每次页面渲染时都会触发 | 渲染UI(注意不能调用setState()) |
componentDidMount | 组件挂载(完成dom渲染)后 | 1.发网络请求 2 .DOM操作 |
钩子函数 | 触发时机 | 作用 |
---|---|---|
render | 每次组件渲染都会触发 | 渲染UI |
componentDidUpdate | 组件更新(完成dom渲染)后 | 1.发送网络请求2.DOM操作 注意:如果要setState()必须放在一个if条件中 |
钩子函数 | 触发时机 | 作用 |
---|---|---|
componentWillUnmount | 组件卸载(从页面中消失) | 执行清理工作(比如:清理定时器等) |
执行过程
安装:
npm install --save react-router-dom
导入路由的三个核心组件: Router / Route / Link
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
使用Router 组件包裹整个应用
使用Link组件作为导航菜单(路由入口)
Router组件:包裹整个应用,一个React应用只需要使用一次
两种常用的Router: HashRouter和BrowserRouter
HashRouter: 使用URL的哈希值实现 (localhost:3000/#/first)
推荐 BrowserRouter:使用H5的history API实现(localhost3000/first)
Link组件:用于指定导航链接(a标签)
最终Link会编译成a标签,而to属性会被编译成 a标签的href属性
Route组件:指定路由展示组件相关信息
path属性:路由规则,这里需要跟Link组件里面to属性的值一致
component属性:展示的组件
Route写在哪,渲染出来的组件就在哪
const Second = (props) => {
function gotoPage () {
props.history.push('/first')
}
return (
页面二
)
}
给Route组件添加exact属性,让其变为精准匹配模式
精确匹配:只有当path和pathname完全匹配时才会展示改路由
作用以及使用
使用步骤
class Mouse extends React.Component {
// 鼠标位置状态
state = {
x: 0,
y: 0
}
// 监听鼠标移动事件
componentDidMount () {
window.addEventListener('mousemove', this.handleMouseMove)
}
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
render () {
// 向外界提供当前子组件里面的数据
return this.props.render(this.state)
}
}
class App extends React.Component {
render () {
return (
App
{
return X{mouse.x}
}} />
)
}
}
ReactDOM.render( , document.getElementById('root'))
推荐使用Children代替上面的的方法
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
class Mouse extends Component {
// 鼠标位置状态
state = {
x: 0,
y: 0
}
// 监听鼠标移动事件
componentDidMount () {
window.addEventListener('mousemove', this.handleMouseMove)
}
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
render () {
// 向外界提供当前子组件里面的数据
return this.props.children(this.state)
}
}
class App extends Component {
render () {
return (
鼠标移动
{({ x, y }) => 鼠标位置:{y}
}
)
}
}
ReactDOM.render( , document.getElementById('root'))
总结:
使用步骤
包装函数
// 定义一个函数,在函数内部创建一个相应类组件
function withMouse (WrappedComponent) {
// 该组件提供复用状态逻辑
class Mouse extends React.Component {
state = {
x: 0,
y: 0
}
// 事件的处理函数
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
// 当组件挂载的时候进行事件绑定
componentDidMount () {
window.addEventListener('mousemove', this.handleMouseMove)
}
// 当组件移除时候解绑事件
componentWillUnmount () {
window.removeEventListener('mousemove', this.handleMouseMove)
}
render () {
// 在render函数里面返回传递过来的组件,把当前组件的状态设置进去
return
}
}
return Mouse
}
哪个组件需要加强,通过调用 withMouse 这个函数,然后把返回的值设置到父组件中即可
function Position (props) {
return (
X:{props.x}
Y:{props.y}
)
}
// 把position 组件来进行包装
let MousePosition = withMouse(Position)
class App extends React.Component {
constructor(props) {
super(props)
}
render () {
return (
高阶组件
)
}
}