(一)组件化入门介绍
1.什么是组件化开发?
- 组件化开发其实就是分而治之的思想
- 我们可以将一个完整的界面拆分成多个小的界面, 每个小的界面就是一个组件,每个组件管理自己的状态(数据)和业务逻辑
- 这样做的既可以提高每个组件的复用性, 又可能降低每个组件的开发难度
- 如何定义组件
- 通过构造函数定义(函数组件, 无状态组件, 展示型组件)
- 通过类定义(类组件, 有状态组件, 逻辑组件)
- 编写组件
//**`index文件`** import ReactDOM from 'react-dom'; import React from 'react'; import App from './App'; ReactDOM.render(<App/>, document.getElementById('root'));
//**`App.js文件`** import React from 'react'; import Header from './Components/Header.js' import Main from './Components/Main.js' import Footer from './Components/Footer.js' class App extends React.Component{ render(){ return ( <div> <Header/> <Main/> <Footer/> </div> ) } } export default App;
//Header.js文件 import React from 'react'; import './Header.css' function Header() { return ( <div className={'header'}>我是头部2</div> ) } export default Header;
//Main.js文件 import React from 'react'; import './Main.css' import Header from "./Header"; function Main() { return ( <div className={'main'}>我是中间2</div> ) } export default Main;
//Footer.js文件 import React from 'react'; import './Footer.css' import Main from "./Main"; function Footer() { return ( <div className={'footer'}>我是底部2</div> ) } export default Footer;
层级结构为
目录结构.png
(二)react组件优化
1. 为什么需要优化?那些地方存在一些性能消耗
父组件数据发生变化而子组件不发生改变父组件更新渲染子组件也需要同时重新渲染一遍
- 1.嵌套组件的render调用
默认情况下, 只要父组件render被调用, 那么所有后代组件的render也会被调用 - 2.当前存在的问题
如果我们只修改了父组件的数据, 并没有修改子组件的数据, 并且子组件中也没有用到父组件中的数据
那么子组件还是会重新渲染, 子组件的render方法还是会重新执行, 这样就带来了性能问题
https://zh-hans.reactjs.org/docs/react-component.html#shouldcomponentupdate
组件优化三部曲
一、优化进阶方法一:
通过shouldComponentUpdate
生命周期对比组件的当前state和nextstate中的数据是否一样判断是否需要重新渲染render
shouldComponentUpdate(nextProps, nextState, nextContext) { // return true; // return false; if(this.state.age !== nextState.age){ return true; } return false; }
class Home extends React.Component{ constructor(props){ super(props); this.state = { age : 18 } } shouldComponentUpdate(nextProps, nextState, nextContext) { if(this.state.age !== nextState.age){ return true; } return false; } render(){ console.log('Home-render被调用'); return ( <div> <p>{this.state.age}</p> </div> ) } } class App extends React.Component{ constructor(props){ super(props); this.state = { name : 'lnj' } } render(){ console.log('App-render被调用'); return ( <div> <p>{this.state.name}</p> <button onClick={()=>{this.btnClick()}}>APP按钮</button> <Home/> </div> ) } btnClick(){ this.setState({ name:''小单" }) } } export default App;
二-优化进阶方法二PureComponent(推荐)
方法二其实在优化就是进阶方法一的自动化版本
1.shouldComponentUpdate存在的问题
所有需要优化子组件都需要实现这个方法, 但这个方法并没有技术含量
2.解决方法
让组件继承于PureComponent, 让React自动帮我们实现
// class Home extends React.Component{ class Home extends React.PureComponent{ constructor(props){ super(props); this.state = { age : 18 } } /* shouldComponentUpdate(nextProps, nextState, nextContext) { if(this.state.age !== nextState.age){ return true; } return false; } */ render(){ console.log('Home-render被调用'); return ( <div> <p>{this.state.age}</p> </div> ) } } class App extends React.Component{ constructor(props){ super(props); this.state = { name : 'lnj' } } render(){ console.log('App-render被调用'); return ( <div> <p>{this.state.name}</p> <button onClick={()=>{this.btnClick()}}>APP按钮</button> <Home/> </div> ) } btnClick(){ this.setState({ name:'单佳兰' }) } } export default App;
三-优化进阶方法三(函数式组件React memo方法)
对于函数式组件来说:
- 没有继承关系
- 没有生命周期方法
- 函数组件的性能优化
对于类组件, 我们可以通过实现shouldComponentUpdate方法, 或者继承于PureComponent
来解决性能优化问题, 但是对于函数式组件, 是没有生命周期的, 是没有继承关系的
那么在函数式组件中如何解决性能优化问题呢? - 通过
React.memo()
高阶函数
React.memo()会返回一个优化后的组件给我们
const PurHome = React.memo(function() { console.log('Home-render被调用'); return ( <div> <p>Home</p> </div> ) });
class App extends React.Component{ constructor(props){ super(props); this.state = { name : 'HUST' } } render(){ console.log('App-render被调用'); return ( <div> <p>{this.state.name}</p> <button onClick={()=>{this.btnClick()}}>APP按钮</button> <PurHome/> </div> ) } btnClick(){ this.setState({ name:'CCNU' }) } } export default App;
state的注意点
1.state注意点
永远不要直接修改state中的数据 如果要修改state中的数据, 必须通过setState传递一个新的值
class App extends React.PureComponent{ constructor(props){ super(props); this.state = { age : 0 } } render(){ console.log('App-render被调用'); return ( <div> <p>{this.state.age}</p> <button onClick={()=>{this.btnClick()}}>APP按钮</button> </div> ) }
btnClick()实现的两种方法:
方法一:创建一个新对象
this.setState({ age:this.state.age + 1 })
方法二:修改原来的state(和state
永远不要修改的原则相违背,极其不推荐)
这种方法使用purecomponent不会更新界面,因为修改为state使得this.state=nextState,因此返回FALSE
btnClick(){ this.state.age = this.state.age + 1; this.setState(this.state); }