您的位置:首页 > Web前端 > React

React知识点

2020-07-18 05:12 204 查看

React

1、虚拟Dom

2、react

  • 核心库(react,react-dom)
  • React 是一个用于构建用户界面的 JAVASCRIPT 库。
  • React 主要用于构建UI,很多人认为React是MVC中的V (视图)。
  • React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站, 并于2013年5月开源
  • React 拥有较高的性能,代码逻辑非常简单,越来越多的人开始关注使用它。

3.react的特点

  1. 声明式设计- React采用声明范式,可以轻松描述应用。
  2. 高效 -React通过对DOM的模拟,最大限度地减少与DOM的交互
  3. 灵活 - React可以与知己的库或框架很好地配合
  4. JSX -JSX 是 JavaScript 语法的扩扎。React 开发不一定使用JSX,但我们建议使用它
  5. 组件 -通过 React 构建组件,使得代码更加容易得到服用,能够很好的应用在项目的开发中
  6. 单向响应的数据流 -React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单

4、react-dom

  • 做dom用的 跑在浏览器端
  • 渲染/挂载

5、react-native

  • native 上面有个 web-view
  • 优点:流畅
  • 缺点:麻烦

6、改变this指向

7、react事件

e.currentTarget:绑定事件的dom
e.target:触发事件的dom
//阻止事件默认行为
e.preventDefault();
//阻止事件冒泡
e.stopPropagation();

8、组件

1.容器组件 // 有state(只能通过class来定义)
2.视图组件 // 没有state(渲染出来的,可以通过class和函数来定义)

9.获取元素

  • ref 获取dom(refer to缩写)
  • findDomNode 获取dom的实例

10、按需加载

封装一个loading组件

import React from 'react';
import '../../scss/index.css';
export default ()=>{
return <div className='load'>
<img src="/load.gif"/>
</div>
}

样式

.load{
width: 100%;
height: 100%;
background: rgba(0,0,0,.5);
position: fixed;
left:0;
top:0;
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
}

react.config.js

// 引入路由按需加载的依赖
import Loadable from 'react-loadable';

// 路由未加载完成时显示的load组件
import Loading from '../components/common/loading';

const Detail = Loadable({
loader:()=>import('../components/Detail'),
loading:Loading
})

const Index = Loadable({
loader:()=>import('../components/Index'),
loading:Loading
})

const Feilei = Loadable({
loader:()=>import('../components/include/Feilei'),
loading:Loading
})

11、定位

// 点击的时候调用这个方法
location(){  // 定位
let script = document.createElement('script');
script.src = 'http://pv.sohu.com/cityjson?ie=utf-8';
document.body.appendChild(script);
script.onload = ()=>{
this.setState({
city:window.returnCitySN.cname
})
}
}

JSX

1、jsx是什么?

  • React使用JSX来代替常规的JavaScript
  • JSX 是一个看起来很像XML的JavaScript 语法扩展
  • 我们不需要一定 JSX,但它有以下优点

JSX执行更快,因为它在编译为 JavaScript 代码后进行了优化
它是类型安全的,在编译过程中就能发现很多错误
使用JSX编写模板更加简单快速

MVVM

1、MVVM是什么?

  1. MVVM是Model-View-ViewModel的简写
  2. 它本质是MVC的改进版
  3. MVVM(Model-View-ViewModel)框架的由来是MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构框架

2、MVVM优点

MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点

  1. 低耦合:视图(View)可以独立于Model变化和改变,一个ViewModel可以绑定到不同的’View’上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变
  2. 可重用性:你可以把一些视图逻辑放在一个ViewModel里面,让一个ViewModel里面,让很多view重用这段视图逻辑
  3. 独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于叶面设计,使用Expression Blend可以很容易设计界面并生成xml代码
  4. 可测试:界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

Props

1、和props相关

  • 只读,不准修改
  • compoWillReceiveProps/生命周期
  • propTypes
  • defaultProps
  • defaultProps
  • children

2、类型检查

import PropTypes from 'prop-types';

List.propTypes = {
list:PropTypes.array/object/number/string
}

2、默认值

List.defaultProps = {
list:[{},{},{}]
}

React生命周期

旧版

新版

import React, { Component } from 'react'

export default class LifeCycle extends Component {
//// props = {age:10,name:'计数器'}
static defaultProps = {
name:'计数器'
}
constructor(props){
//Must call super constructor in derived class before accessing 'this' or returning from derived constructor
super();//this.props = props;
this.state = {number:0,users:[]};//初始化默认的状态对象
console.log('1. constructor 初始化 props and state');

}
//componentWillMount在渲染过程中可能会执行多次
componentWillMount(){
console.log('2. componentWillMount 组件将要挂载');
//localStorage.get('userss');
}
//componentDidMount在渲染过程中永远只有执行一次
//一般是在componentDidMount执行副作用,进行异步操作
componentDidMount(){
console.log('4. componentDidMount 组件挂载完成');
fetch('https://api.github.com/users').then(res=>res.json()).then(users=>{
console.log(users);
this.setState({users});
});
}
shouldComponentUpdate(nextProps,nextState){
console.log('Counter',nextProps,nextState);
console.log('5. shouldComponentUpdate 询问组件是否需要更新');
return true;
}
componentWillUpdate(nextProps, nextState){
console.log('6. componentWillUpdate 组件将要更新');
}
componentDidUpdate(prevProps, prevState)){
console.log('7. componentDidUpdate 组件更新完毕');
}
add = ()=>{
this.setState({number:this.state.number});
};
render() {
console.log('3.render渲染,也就是挂载')
return (
<div style={{border:'5px solid red',padding:'5px'}}>
<p>{this.props.name}:{this.state.number}</p>
<button onClick={this.add}>+</button>
<ul>
{
this.state.users.map(user=>(<li>{user.login}</li>))
}
</ul>
{this.state.number%2==0&&<SubCounter number={this.state.number}/>}
</div>
)
}
}
class SubCounter extends Component{
constructor(props){
super(props);
this.state = {number:0};
}
componentWillUnmount(){
console.log('SubCounter componentWillUnmount');
}
//调用此方法的时候会把新的属性对象和新的状态对象传过来
shouldComponentUpdate(nextProps,nextState){
console.log('SubCounter',nextProps,nextState);
if(nextProps.number%3==0){
return true;
}else{
return false;
}
}
//componentWillReceiveProp 组件收到新的属性对象
componentWillReceiveProps(){
console.log('SubCounter 1.componentWillReceiveProps')
}
render(){
console.log('SubCounter  2.render')
return(
<div style={{border:'5px solid green'}}>
<p>{this.props.number}</p>
</div>
)
}
}

1、componentDidMount()

组件挂在完成之后触发的生命周期 相当于vue的mounted

componentDidMount(){
setInterval(()=>{
// 修改state的唯一方法
// @param 要修改的数据
// @param 修改完成之后的回调函数
this.setState({
index:this.state.index++
},()=>{
consloe.log(this.state.index)
})
},1000)
}

2、componentWillMount()

组件挂在之前 相当于vue的beforeMount

3、componentWillReceiveProps(nextProps)

组件将要接收新的props vue没有这个生命周期可以用watch来实现类需求

// 和props相关的唯一一个生命周期
// 执行完成之后,this.props指向新的props
componentWillReceiveProps(nextProps){
// 旧的props   this.props
// 新的props   nextProps
}

4、shouldComponentUpdate(nextProps,nextState)

通过返回值判断组件是否需要更新,用于react优化,vue没有 true更新,false不更新

shouldComponentUpdate(nextProps,nextState){
// 旧的props   this.props
// 新的props   nextProps
// 旧的State   this.state
// 新的state   nextState
// 返回值是Boolean  默认true
}

5、componentWillUpdate()

组件将要更新 相当于vue的beforeUpdate

6、componentDidUpdate()

组件更新完成 相当于vue的updated

7、componentWillUnmout()

组件将要卸载

8、unmountComponentAtNode

卸载组件

ReactDom.unmountComponentAtNode(document.getElementById('root'))

9、分为三个阶段

首次使用一个组件类时会有getDefaultProps
对于组件类的所有后续应用没有getDefaultProps
1、getDefaultProps
2、getInitialState
3、componentWillMount
4、render
5、componentDidMount

2、更新阶段(存在期)

1. componentWillReceiveProps
2. shouldComponentUpdate
3. componentWillUpdate
4. render
5. componentDidUpdate

3、销毁&清理期

componentWillUnmount

React路由

1、react-router-dom

  • web前端用的

1、hash

改变地址 -> push     ->  window.location.hash=
-> replace  -> window.location.replace(url)
hashchange

2、browser/history

下面说说HashRouter和BrowserRouter上的参数

  • basename 路由的基础链接,用来部署到非根目录下,比如你需要将项目部署到 www.xxxx.com/web 下,则设置basename="/web"
  • getUserConfirmation 用来拦截Prompt组件,并且决定是否跳转
  • forceRefresh 用来设置是否强制浏览器整体刷新,默认值为false
  • keLength 用来设置location.key的长度,默认是6,可以自定义
改变地址 -> pushstate  -> window.history.pushState({}, `这是标题`, this.getAttribute('href'));
->  replacestate  -> window.history.replaceState({}, `这是标题`, this.getAttribute('href'));
popState

Prompt

Prompt是用来提示用户是否要跳转,给用户提示信息默认使用window.confirm,可以结合getUserConfirmation构建自定义提示信息

<Prompt message={location => {
return '请确认'
}}/>

如果直接返回true,则不会弹窗

Route

Route 是路由的一个原材料,它是控制路径对应显示组件

Router的参数:

  • path 跳转的路径
  • component 对应路径显示的组件
  • render 可以自己写route对象,和当前的route对象对比,如果匹配则跳转
  • exact 匹配规则,true的时候则精确匹配。
path url 是否开启 匹配结果
/a /a/b false yes
/a /a/b true no
  • sensitive 是否区分path的大小写
path url 是否开启 匹配结果
/a /a true yes
/a /A true yes
  • strict是否匹配后面的/
path url 是否开启 匹配结果
/a /a / true yes
/a /a/c true yes
/a /a true no

Router

低级路由,使用与任何路由组件,主要和redux深度集成,使用必须配合history对象,使用Router路由的目的是和状态管理库redux中的history同步对接

Link和NavLink

两者都是跳转路由,NavLink的参数更多些

Link的api
  • to有两种写法,表示跳转到那哪个路由 字符串写法
<Link to="/a"/>
  • 对象写法
<Link to={{
pathname: '/courses',
search: '?sort=name',
hash: '#the-hash',
state: { fromDashboard: true }
}}/>
  • replace 就是将push改成replace
  • innerRef 访问Link标签的dom
NavLink的api
  • Link的所有api
  • activeClassName 路由激活的时候设置的类名
  • activeStyle路由激活设置的样式
  • exact 参考Route,符合这个条件才会激活active类
  • strict 参考 Route,符合这个条件才会激活active类
  • isActive 接收一个回调函数,active状态变化的时候回触,返回false则中断跳转
const oddEvent = (match, location) => {
console.log(match,location)
if (!match) {
return false
}
console.log(match.id)
return true
}
<NavLink isActive={oddEvent} to="/a/123">组件一</NavLink>
  • location 接收一个location对象,当url满足这个对象的条件会跳转
<NavLink to="/a/123" location={{ key:"mb5wu3", pathname:"/a/123" }}/>

Redirect

Redirect重定向很简单,我们直接看代码即可

// 基本的重定向
<Redirect to="/somewhere/else" />

// 对象形式
<Redirect
to={{
pathname: "/login",
search: "?utm=your+face",
state: { referrer: currentLocation }
}}
/>

// 采用push生成新的记录
<Redirect push to="/somewhere/else" />

// 配合Switch组件使用,form表示重定向之前的路径,如果匹配则重定向,不匹配则不重定向
<Switch>
<Redirect from='/old-path' to='/new-path'/>
<Route path='/new-path' component={Place}/>
</Switch>

Switch

路由切换,只会匹配第一个路由,可以想象成tab栏
Switch内部职能包含Route、Rediect、Router

<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
</Switch>

withRouter

当一个非路由组件也想访问当前路由的match,location,history对象,那么withRouter将是一个非常好的选择,可以理解为将一个组件包裹成路由组件

import { withRouter } from 'react-router-dom'
const MyComponent = (props) => {
const { match, location, history } = this.props
return (
<div>{props.location.pathname}</div>
)
}
const FirstTest = withRouter(MyComponent);

history对象

用过vue的都知道,vue-router有组件形式的导航,也有编程式导航,那么react-router怎么使用api来控制路由的跳转状态呢。

在每个路由组件中我们可以使用this.props.history对象,也可以用withRouter包裹组件来获取,

在history中封装了push,replace,go等具体方法,具体如下

History {
length: number;
action: Action;
location: Location;
push(path: Path, state?: LocationState): void; // 调用push前进到一个地址,可以接受一个state对象,就是自定义的路由数据
push(location: LocationDescriptorObject): void; // 接受一个location的描述对象
replace(path: Path, state?: LocationState): void; // 用页面替换当前的路径,不可再goBack
replace(location: LocationDescriptorObject): void; // 同上
go(n: number): void; // 往前走多少也页面
goBack(): void; // 返回一个页面
goForward(): void; // 前进一个页面
block(prompt?: boolean | string | TransitionPromptHook): UnregisterCallback;
listen(listener: LocationListener): UnregisterCallback;
createHref(location: LocationDescriptorObject): Href;
}

参考文档

2、react-router-native

  • native用的

3、HashRouter

哈希模式(#) 只存在浏览器端,服务器会忽略
瞄点:不会刷新浏览器,跳转页面

4、BrowserRouter

浏览器模式(localhost:3000/tab) // 假的url,伪地址

5、路由封装

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {HashRouter as Router} from 'react-router-dom';

// 封装的类似于router-view的文件
import RouterView from './react/reactView';
// 路由配置
import config from './react/react.config';

ReactDOM.render(<Router>
<RouterView routes={config.routes}></RouterView>
</Router>,document.getElementById('root'));

react/reacView.jsx

import React from 'react';
import {Switch,Route,Redirect} from 'react-router-dom';

export default (props)=>{
return <Switch>{
props.routes.map((item,index)=>{
return <Route key={index} path={item.path} render={(props)=>{
if(item.children){
// 渲染组件
// ...props 展开路由信息传递下去
// item.children 把子路由配置传递下去
return <item.component {...props} routes={item.children}/>
}else{
return <item.component {...props}/>
}
}}></Route>
})
}
<Redirect exact from='/' to='/tab'></Redirect>
</Switch>
}

react/react.config.js

// 一级路由
import Tab from '../components/Tab.jsx';
import Detail from '../components/Detail.jsx';

// 二级路由
import Hot from '../components/include/Hot.jsx';
import Movie from '../components/include/Movie.jsx';
import My from '../components/include/My.jsx';

export default{
routes:[
{
path:'/tab',
component:Tab,
children:[
{
path:'/tab/hot',
component:Hot
}, {
path:'/tab/movie',
component:Movie
}, {
path:'/tab/my',
component:My
}
]
},{
path:'/detail',
component:Detail
}
]
}

components/Tab.js

import React,{Component} from 'react';
import {NavLink} from 'react-router-dom';

class Detail extends Component{
constructor(props){
super(props)
}

render(){
return <div>
<footer>
<NavLink to="/tab/hot">热映</NavLink>
<NavLink to="/tab/movie">电影</NavLink>
<NavLink to="/tab/my">我的</NavLink>
</footer>
</div>
}
}

export default Detail;

Redux

1、redux是什么?

  • 是一个框架
  • 跨组件通讯

分四块内容

  1. actionTypes
  2. actions =>{ type,payload}
  3. reducer
  4. store

redux三大原则

  1. 单一数据元
  2. State是只读的
  3. 使用纯函数来进行修改

2、provider

  • 只有一个属性,是store
  • 顶层容器

3、connect

  • 伪高阶函数
  • 4个参数
1、把redux中state映射成的props传递到组件中去   // 获取state数据
const mapStatetoProps = (state,ownProps)=>{
// state  redux存储的数据
// ownProps   组件调用时传过来的props
// 返回一个对象
}

2、把dispatch操作封装在当前函数里,传递到组件中   // 封装方法
const mapDispatchtoProps = (dispatch, ownProps)=>{
// 返回一个对象
return {
fetchList:()=>{
axios.get('路径')
.then(res=>{
// 触发dispatch
dispatch({
type:'FETCH_LIST',
payload:res.data
})
})
}
}

}

3、合并props
const mergeProps = (stateProps, dispatchProps, ownProps)=>{
// stateProps 是mapStateToProps的返回值
// dispatchProps 是mapDispatchtoProps的返回值
// ownProps 是调用时传入的props
return {...stateProps, ...dispatchProps, ...ownProps}

}

4、可选配置项
const options = {
pure:true
// pure:表示state需要深拷贝才会响应
// true 深拷贝(默认true 深拷贝)
// false 浅拷贝深拷贝都可以
}

4、reducer

  • 有两个参数:state action
  • 接受先前的state 和action,并且返回新的state

深拷贝和浅拷贝

  • 深拷贝 … 或者使用 JSON.parse(JSON.stringify())
  • 浅拷贝 Object.assign()

5、store

  • createStore接收两个参数

reducers 存储数据和修改数据

applyMiddleware应用的中间件

6、combineReducers //合并

import {combineReducers} from 'redux';
import cart from './cart';
import my from './my';

export default combineReducers({
cart,
my
})

Redux中间件

1、applyMiddleware

  • 方便调试,实时触发,线下使用
import {createStore,applyMiddleware} from 'redux';
import reducers from './reducers';
import Logger from 'redux-logger';

export default createStore(reducers, applyMiddleware(Logger))

2、redux-thunk

  • 目的:异步解决方案
  • 支持action的写法有对象变为函数
  • 可以发送多个dispatch
  • 改变action
  • 同时会帮助我们注入两个参数dispatch和getState
  • 在异步操作完成之后再触发dispatch操作
dispatch((dispatch, getState)=>{
// getState可以获取全局的state
dispatch({
type:"START"
})
fetch('/data.json')
.then(res=>res.json())
.then(success=>{
if(success){
dispatch({
type:"FETCH_LIST",
payLoad:success.arr
})
}else{
dispatch({
type:"FETCH_TAIL"
})
}
})
})

3、redux-saga

  • 拦截请求
  • 解决异步
  • 不会改变action
  • take拦截
  • takeEvery每次都拦截

参考链接

组件通信

需要组件之间进行通信的几种情况

  • 父组件向子组件通信
  • 子组件向父组件通信
  • 跨级组件通信
  • 没有嵌套关系组件通信

1、父组件向子组件通信

React中采用数据单向流动的方式,父组件向子组件传递是最常见的情况,父组件通过props向子组件传递数据

// 父组件
class App extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<Child name='tadpole' />
)
}
}

// 子组件
function Child(props) {
return (
<div>{props.name}</div>
)
}

2、子组件想父组件通信

  • 利用回调函数
  • 利用自定义事件机制
// 父组件
class App extends React.Component {
constructor(props) {
super(props)
this.state = {data: ''}
}
// 自定义的回调事件
childValue = data => {
this.setState({data})
}
render() {
return (
<div>
子组件传递过来的值:{this.state.data}
<Child transferValue={this.childValue}/>
</div>
)
}
}

// 子组件
class Child extends React.Component {
constructor(props) {
super(props)
this.state = {data: ''}
}
valueChange = data => {
// 保证子组件中的值和传递过去的值一致
this.setState({
data: data.target.value
})
// 触发回调 传递给父组件
this.props.transferValue(data.target.value)
}
render() {
return (
<div>
子组件: <input vlaue={this.state.data} onChange={this.valueChange} />
</div>
)
}
}

3、跨级组件通信

  • 层层组件传递props
  • 使用Context

React 中遵循数据单向流动(自上而下)的规则,其实我们完全可以通过每级组件传递 props 的方式来实现跨级通信的目的。但是,在这个过程中,有些组件是不需要使用上级传递过来的 props 的,这种操作无疑是显得多余的,这个时候就引入了 Context

Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法,它设计目的就是为了共享那些对于一个组件树而言是“全局”的数据

// 创建一个Context对象
const InitContext = React.createContext()

class App extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
// 使用一个 Provider 来将当前的 context 传递给以下的组件树
<InitContext.Provider value='tadpole'>
<Child />
</InitContext.Provider>
)
}
}

function Child(props) {
return (
<LastComponent />
)
}

class LastComponent extends React.Component {
// 指定 contextType 读取当前的  context
static contextType = InitContext
render() {
return (
<div>name: {this.context}</div>
)
}
}

使用Context的注意点

  • 每个Context对象都会返回一个 Provider React 组件
  • 只有当组件所处的树中没有匹配到 Provider 时,其 defaultValue 参数才会生效,默认值为 undefined
  • 多个 Provider 也可以嵌套使用 ,里层的会覆盖外层的数据 Provider 接收一个 value 属性,传递给消费组件(React 会往上找到最近的 Provider,然后使用它的值)
  • 可以在任何生命周期中访问到,包括 render 函数中

文档链接

4、没有嵌套关系组件之间的通信

  • 找到共同的父组件
import React from 'react'
import ReactDom from 'react-dom'

// 评论输入组件
class CommentData extends React.Component {
constructor(props) {
super(props)
this.state = { data: '123' }
}

commentChange = (data) => {
this.setState({
data: data.target.value
})
}

submit = () => {
this.props.newList(this.state)
}

render() {
return (
<div>
<textarea rows='6' cols='50' value={this.state.data} onChange={this.commentChange}></textarea>
<br />
<button onClick={this.submit}>发表评论</button>
</div>
)
}
}

// 评论列表显示组件
function CommentList(props) {
return (
<ul>
{
props.list.map((res, index) => {
return (
<li key={index}>
<p>用户{index + 1}</p>
<p>{res.data}</p>
</li>
)
})
}
</ul>
)
}

// 父组件
class Comment extends React.Component {
constructor(props) {
super(props)
this.state = {
title: 'commemt',
list: [
{data: '这个好棒啊!'},
{data: '我也是这么觉得'}
]
}
}
listChange = data => {
this.setState((state, props) => {
let list = state.list.push(data)
return list
})
}
render() {
let commentLists = <CommentList  list={this.state.list} />
let commentData = <CommentData newList={this.listChange} />
return (
<div>
<h1>{this.state.title}</h1>
<div>{commentData}</div>
<div>{commentLists}</div>
</div>
)
}
}

ReactDom.render(<Comment />, document.getElementById('app'))
  • 利用 Context API 进行通信,创建一个全局的可访问值

  • 利用events 创建自定义事件

一般情况下,第一种方式找到共同的父组件可能存在很多级的情况,不是很友好,第二种方式对于后期维护或者说对于组件的可复用性不是很友好,所以,我们试一下自定义事件这种方式

首先,我们需要一个 evevts这个包

npm install events -S

通过注册,触发事件来实现组件通讯

import { EventEmitter } from 'events'

const emitter = new EventEmitter()

// 组件A
class ComponentA extends React.Component {
constructor(props) {
super(props)
this.state = {msg: ''}
}
componentDidMount() {
// 组件挂载完毕的时候注册事件
this.eventEmitter = emitter.addListener('outputValue', msg => {
this.setState({msg})
})
}
componentWillUnMount() {
// 组件销毁之前移除事件
emitter.removeListener(this.eventEmitter)
}
render() {
return (
<div>
这是组件A
<div>组件B传递过来的数据:{ this.state.msg }</div>
</div>
)
}
}

// 组件B
class ComponentB extends React.Component {
constructor(props) {
super(props)
this.state = {value: ''}
}
valueChange = data => {
this.setState({
value: data.target.value
})
}
btnClick = () => {
// 触发自定义事件
emitter.emit('outputValue', this.state.value)
}
render() {
return (
<div>
这是组件B
<input value={this.state.value} onChange={this.valueChange}></input>
<button onClick={this.btnClick}>点击我传递信息</button>
</div>

)
}
}

高阶组件

1、什么是高阶组件?

  • 高阶组件就是一个 React 组件包裹着另外一个组件
  • 因为要访问它的内部状态,所以要用到继承
  • 高阶组件就是一个函数,它接受另外一个组件作为参数,并返回一个新的组件。
  • 当React组件被包裹时(warped),高阶组件会返回一个增强React组件。
  • 高阶组件让代码更具有复用性、逻辑性和抽象特性。

2、利用super传递下去

import React from 'react';
import Loding from '../common/loading';

// 侵入式
// 因为要访问它的内部状态,所以要用到继承,继承他的父级
export default (WrapComponent)=>{
return class extends WrapComponent{
render(){
if(this.state.isLoading){
return <Loding></Loding>
}else{
return super.render()
}
}
}
}

3、非侵入式

  • 利用…传递下
    hoc/widthAd.jsx
import React from 'react';

// 非侵入式
// WrapComponent 被包裹的组件
export default (WrapComponent)=>{
return class extends React.Component{
render(){
return <div>
<div>
<p>请下载淘票票</p>
<a href="https://dianying.taobao.com/">下载</a>
</div>
<WrapComponent {...this.props}/>
</div>
}
}
}

用的时候直接引入这个文件,然后抛出 export default widthAd(Tab)

4 、为什么要使用高阶组件?

  • 为了代码的复用性,减少代码的冗余

js继承的几种方式

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: