React知识点
React
1、虚拟Dom
2、react
- 核心库(react,react-dom)
- React 是一个用于构建用户界面的 JAVASCRIPT 库。
- React 主要用于构建UI,很多人认为React是MVC中的V (视图)。
- React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站, 并于2013年5月开源
- React 拥有较高的性能,代码逻辑非常简单,越来越多的人开始关注使用它。
3.react的特点
- 声明式设计- React采用声明范式,可以轻松描述应用。
- 高效 -React通过对DOM的模拟,最大限度地减少与DOM的交互
- 灵活 - React可以与知己的库或框架很好地配合
- JSX -JSX 是 JavaScript 语法的扩扎。React 开发不一定使用JSX,但我们建议使用它
- 组件 -通过 React 构建组件,使得代码更加容易得到服用,能够很好的应用在项目的开发中
- 单向响应的数据流 -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是什么?
- MVVM是Model-View-ViewModel的简写
- 它本质是MVC的改进版
- MVVM(Model-View-ViewModel)框架的由来是MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构框架
2、MVVM优点
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点
- 低耦合:视图(View)可以独立于Model变化和改变,一个ViewModel可以绑定到不同的’View’上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变
- 可重用性:你可以把一些视图逻辑放在一个ViewModel里面,让一个ViewModel里面,让很多view重用这段视图逻辑
- 独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于叶面设计,使用Expression Blend可以很容易设计界面并生成xml代码
- 可测试:界面素来是比较难于测试的,而现在测试可以针对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是什么?
- 是一个框架
- 跨组件通讯
分四块内容
- actionTypes
- actions =>{ type,payload}
- reducer
- store
redux三大原则
- 单一数据元
- State是只读的
- 使用纯函数来进行修改
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 、为什么要使用高阶组件?
- 为了代码的复用性,减少代码的冗余
- react 的启动到常用知识点
- 【React】知识点归纳:纯函数和高阶函数
- 关于React知识点
- React native最基础的入门知识点
- React-jsx、html、css基本知识点
- React Native系列——知识点总结贴
- 关于React.js的一些知识点(实时更新)
- React入门知识点清单
- React知识点
- React Native Android(二)Navigator知识点
- React零碎知识点回顾
- 【React】知识点归纳:redux
- React知识点梳理(持续更新中)
- 自学react-native之必备知识点(ES6+ReactJS+flexbox)
- React 知识点简介
- 值得收藏的React知识点-查漏补缺
- 总结react中遇到的坑和一些小的知识点
- react知识点学习(一)——定义CSS样式
- react-router知识点
- React-Native 知识点小结