anu
anu copied to clipboard
nanachi新的H5转译loader
首先从app.js开始转译
import React from '@react';
import './pages/index/index'; //pages页面全部变成config.pages中的字符串
import './pages/aaa/index'; // pages页面全部变成config.pages中的字符串
import './pages/bbb/index'; //pages页面全部变成config.pages中的字符串
class Global extends React.Component {
globalData = {}
static config = {
window: {
navigationBarBackgroundColor: '#00afc7',
backgroundTextStyle: 'light',
navigationBarTitleText: 'nanachi',
navigationBarTextStyle: 'white'
},
tabBar: {
list: [ {name: 'app',pagePath: "/pages/index"}]
}
};
onLaunch() {
//针对快应用的全局getApp补丁
if (this.$data && typeof global === 'object') {
var ref = Object.getPrototypeOf(global) || global;
var _this = this;
this.globalData = this.$def.globalData;
ref.getApp = function() {
return _this;
};
}
console.log('App launched');//eslint-disable-line
}
}
// eslint-disable-next-line
export default App(new Global());
转换成
import React from '@react';
import PageWrapper from '@component/PageWrapper/index';
import './pages/index/index'; //它们不会删掉,用于webpack打包
import './pages/aaa/index'; // 它们不会删掉,用于webpack打包
import './pages/bbb/index';
class Global extends React.Component {
globalData = {}
static config = {
window: {
navigationBarBackgroundColor: '#00afc7',
backgroundTextStyle: 'light',
navigationBarTitleText: 'nanachi',
navigationBarTextStyle: 'white'
},
tabBar: {
list: [ {name: 'app',pagePath: "/pages/index"}]
},
pages: [
'./pages/index/index',
'./pages/aaa/index',
'./pages/bbb/index';
]
};
onLaunch() {
console.log('App launched');//eslint-disable-line
}
componentWillMount(){
React.api.registerApp(this);// redirectTo等路由方法会调用Global的实例进行setState
this.onLaunch() ;
React.api.redirectTo(Global.config.pages[0])
}
render(){
return <PageWrapper app={this} path={this.state.path} query={this.state.query} />
}
}
window.onload = function (){
ReactDOM.render( <Global />, document.querySelector("#root" ))
}
React.api.registerApp, React.api.redirectTo 的实现
React.api.registerApp = function(app){
this.__app = app
}
React.api.redirectTo = function({url, success, fail, complete} ){
var [path, query] = getQuery(url) //自己实现
var appInstance = this._app;
var appConfig = appInstance.constructor.config;
if(appConfig.pages.indexOf(path) === -1){
throw "没有注册该页面: "+ path
}
appInstance.setState({
path,
query,
success,
fail,
complete
})
}
PageWrapper负责渲染titleBar, titleBar, 右上角菜单, 还应该监听页面的滚动
/*
.tabBar {
border-style: solid;
border-color: #ddd;
border-top-width: 1px;
position: fixed;
bottom: 0;
width: 100%;
height: 110px;
}
.tabBar .tab {
flex: 1;
margin: 10px;
flex-direction: column;
justify-content: center;
align-items: center;
}
.tabBar .tab image {
width: 45px;
height: 45px;
}
.tabBar .tab a {
margin: 10px;
border: 1px solid #eeeeee;
}
*/
import React from '../../ReactH5.js';
class PageWrapper extends React.Component{
constructor(props){
super(props);
this.$app = props.app;
this.state = {
tabBar: {
list: []
},
titleBar: { },
showTitleBar: true,
pagePath: "",
backgroundColor: "#ffffff"
}
setTitleAndTabs(this, this.$app);
}
componentWillUpdate(){
setTitleAndTabs(this, this.$app);
}
onSelected(item) {
if(item.selected){
return false;
}
var page = React.api.getCurrentPage();
if (page.onTabItemTap) {
page.onTabItemTap(item)
}
React.api.navigateTo({
url: item.pagePath
})
}
render(){
return (<div style={{
width:"100%",
paddingBottom: this.state.tabBar.list.length? '110px': '0px',
backgroundColor: this.state.backgroundColor}}>
<header style={{display: this.state.showTitleBar ? 'block': 'none'}}>
<div class="title" style={{
color: this.state.titleBar.textColor,
backgroundColor: this.state.titleBar.backgroundColor
}} >
{this.state.titleBar.text}
</div>
<div class="menu"></div>
</header>
{ !this.state.tabBar.list.length ?
null:
<main class="tabBar" style={{backgroundColor: this.state.tabBar.backgroundColor}}>
{ this.state.tabBar.list.map(
function(item ){
return <div class="tab" onClick={ this.onSelected.bind(this,item)}>
<img src={ item.selected ? item.selectedIconPath : item.iconPath } />
<span style={{
color: item.selected ? tabBar.selectedColor: tabBar.color ,
fontSize: "20px"
}}>
{item.text}
</span>
</div>
})
}</main> }
</div>)
}
}
function setTitleAndTabs(instance, app) {
var path = app.state.path;
var PageClass = React.api.__pages[path];
var appConfig = app.constructor.config || {}
var pageConfig = PageClass.config || {}
var mixin = Object.assign({
navigationBarTitleText: "",
navigationBarTextStyle: "white",
navigationBarBackgroundColor: "#000000"
}, appConfig, pageConfig);
instance.setState({
showTitleBar: mixin.navigationStyle !== "custom",
backgroundColor: mixin.backgroundColor || "#ffffff",
titleBar: {
text: mixin.navigationBarTitleText,
textColor: mixin.navigationBarTextStyle,
backgroundColor: mixin.navigationBarBackgroundColor,
}
})
var tabBar = pageConfig.tabBar || appConfig.tabBar;
if (tabBar && tabBar.list && tabBar.list.length) {
tabBar.backgroundColor = tabBar.backgroundColor || "#f9faf5";
tabBar.color = tabBar.color || "#000";
tabBar.selectedColor = tabBar.selectedColor || "#48adc4";
tabBar.list.forEach(function(el, i){
if(!el.pagePath){
console.warn(`tabBar.list[${i}] miss pagePath`, el);//eslint-disable-line
return
}
el.selected = trimPagePath(el.pagePath) === trimPagePath(instance.pagePath);
})
instance.setState({
tabBar: tabBar
})
}
}
export default PageWrapper
页面的转换
import React from '@react';
//import Welcome from '@components/Welcome/index';
import {GlobalTheme} from '@common/GlobalTheme';
import Layout from '@components/Layout/index';
import AnotherComponent from '@components/AnotherComponent/index';
import './index.scss';
class P extends React.Component {
componentDidMount() {
// eslint-disable-next-line
console.log('page did mount!');
}
render() {
this.props.anyVar = {color:'red'}
return <div class = 'page' >
<GlobalTheme.Provider value={this.props.anyVar}>
<Layout>
<AnotherComponent />
</Layout>
</GlobalTheme.Provider>
</div>
}
}
export default P;
变成
import React from '@react';
import {GlobalTheme} from '@common/GlobalTheme';
import Layout from '@components/Layout/index';
import AnotherComponent from '@components/AnotherComponent/index';
import './index.scss';
class P extends React.Component {
componentDidMount() {
// eslint-disable-next-line
console.log('page did mount!');
}
render() {
this.props.anyVar = {color:'red'}
return <div class = 'page' >
<GlobalTheme.Provider value={this.props.anyVar}>
<Layout>
<AnotherComponent />
</Layout>
</GlobalTheme.Provider>
</div>
}
}
export default P;
转换成
import React from "../../ReactH5.js";
import { GlobalTheme } from "../../common/GlobalTheme.js";
import Layout from '@components/Layout/index';
import AnotherComponent from '@components/AnotherComponent/index';
import './index.scss';
function P() {}
P = React.toClass(P, React.Component, {
componentDidMount: function () {
console.log('page did mount!');
},
render: function () {
return <div class = 'page' >
<GlobalTheme.Provider value={this.props.anyVar}>
<Layout>
<AnotherComponent />
</Layout>
</GlobalTheme.Provider>
</div>
},
classUid: "c1004"
}, {});
//Page(React.registerPage(P, "pages/index/index"));
React.registerPage(P, "pages/index/index")
export default P;
React.registerPage 的实现。
React.registerPage = function( PageClass, path){
this.api.__pages[path] = PageClass;
return PageClass;
}
组件不需要处理
我们需要动态生成一个页面来处理加webpack打包出来的js
页面组件与业务组件的事件都不用再处理
this.props.App.initAppConfig(AppConfig.config.window);
h5 AppConfig is not defined