网站专题策划方案,互联网站安全管理服务平台,网址大全下载,如何用框架做网站React16是一个实验版本#xff0c;除了测试它的新fiber架构外#xff0c;还添加了大量新功能。其他React.Suspense与React.lazy就是重磅中的重磅。随着前端的APP化#xff0c;不断集成功能#xff0c;页面越来越大#xff0c;bundle size以MB为单位#xff0c;我们需要拆…React16是一个实验版本除了测试它的新fiber架构外还添加了大量新功能。其他React.Suspense与React.lazy就是重磅中的重磅。随着前端的APP化不断集成功能页面越来越大bundle size以MB为单位我们需要拆分代码实现动态化加载非首屏功能。比日历城市选择器评论组件等等。动态加载在javascript模块加载规范中已经有草案并且被webpack, rollup所支持import(../components/Hello).then(Hello {console.log(Hello /);
});
相当于setTimeout模拟异步加载组件new Promise(resolve setTimeout(() resolve({// 来自另一个文件的函数式组件default: function render() {return divHello/div}}),3000)
).then(({ default: Hello }) {console.log(Hello /);
});
React16提供了lazy组件实现这个功能 var {lazy, Suspense} React;var OtherComponent lazy((){return new Promise(resolve setTimeout(() resolve({default: function Hello() { //export defaultreturn divHello/div}}),3000))});
上面只是一个方便大量测试的例子实际需要将 divHello/div 放到一个文件中使用import()语法引进来即 const OtherComponent React.lazy(() import(./OtherComponent));
OtherComponent.js的源码export default function Hello(){return divHello/div
}
接着我们实现将动态功能加进组件树就是所谓的条件渲染。这个功能由React.Suspense提供。在框架不提供这功能的情况下我们需要找一个父组件将这组件动态挂上去class MyComponent extends Component {constructor() {super();this.state {};// 动态加载import(./OtherComponent).then(({ default: OtherComponent }) {this.setState({ OtherComponent });});}render() {const { OtherComponent } this.state;return (div{/* 条件渲染 */}{ OtherComponent OtherComponent / }/div);}
}
但光是这样还是不行的因为单纯的动态加载会引起页面抖动我们需要loading将这个突兀的显示给缓解一下。于是这render需要改成render() {const { OtherComponent } this.state;return (div{OtherComponent ? OtherComponent /: Loading /}/div);}
如果有了Suspense组件我们就简单了不需要入侵已有的组件并且有地方挂这个loading。Suspense fallback{Loading /}OtherComponent //Suspense
需要注意的是lazy组件外面必须包着一个Suspense组件。从框架层面对用户体验提出了强制要求。下面是一个完整的例子!DOCTYPE html
htmlheadmeta charsetutf-8meta nameviewport contentwidthdevice-width
!--script srchttps://cdn.bootcss.com/react/16.7.0-alpha.2/umd/react.development.js/scriptscript srchttps://cdn.bootcss.com/react-dom/16.7.0-alpha.2/umd/react-dom.development.js/script
--script src./dist/React.js/script script typetext/javascript src./lib/babel.js/script/headbodydiv idroot classroot/divscript typetext/babelvar { lazy, Suspense } React;
var OtherComponent lazy(() {return new Promise(resolve setTimeout(() resolve({default: function render(props) {//export defaultreturn divHello,{props.name}/div;}}),3000));
});
var valueRef React.createRef()
class App extends React.Component {constructor(props){super(props)this.state {name: ruby}}updateName(){var name valueRef.current.value;this.setState({name})}render() {return (divpinput ref{valueRef} onChange{this.updateName.bind(this)} value{this.state.name} /{new Date-0}/pSuspense fallback{divloading.../div}OtherComponent name{this.state.name} //Suspense/div);}
}ReactDOM.render(App /, document.getElementById(root));/script/html最后说一下实现React官方是通过lazy组件主动抛错给上面Suspense组件接住的hack方式实现的https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberWorkLoop.js#L907-L1057lazy组件被读取时https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberLazyComponent.jsReact官方投入了近500行代码实现的再看一下anujs如何实现的。anujs的Suspense是异常简单就是一个虚拟组件甩手掌柜总是渲染它的孩子。它只负责挂loading。function Suspense(props){return props.children
}export {Suspense
}
lazy组件就是将用户函数再包一层封到一个LazyComponent组件中它会根据用户的promise决定是返回上层的suspense组件的fallback属性还是延期加载回来的组件。import { miniCreateClass, isFn, get } from react-core/util;
import { Component } from react-core/Component;
import { createElement } from react-core/createElement;
import { Suspense } from ./Suspense;var LazyComponent miniCreateClass(function LazyComponent(props, context) {this.props props;this.context context;this.state {component: null,resolved: false}var promise props.render();if(!promise || !isFn(promise.then)){throw lazy必须返回一个thenable对象}promise.then( (value) this.setState({component: value.default,resolved: true}))}, Component, {fallback(){//返回上层Suspense组件的fallback属性var parent Object(get(this)).returnwhile(parent){if( parent.type Suspense){return parent.props.fallback}parent parent.return}throw lazy组件必须包一个Suspense组件},render(){return this.state.resolved ? createElement(this.state.component) : this.fallback()}
});
function lazy(fn) {return function(){return createElement(LazyComponent, {render: fn})}
}
export {lazy
}
最后欢迎大家使用anujs 。一个迷你React框架支持react16 的所有新特性可以用于小程序中。RubyLouvre/anugithub.comnpm i anujs