三大组件App/Page/ViewPort

App - CRN app 入口

App 是一个组件,也是一个基类。

//App 类定义

import {Component} from 'react';

clas App extens Component {

}

每一个使用使用AppRegistry.registerComponent注册的组件都应该是一个 App 子类。改模块加载时会 new 出一个实例,我把这个实例称之为 app。(下文中出现的 app 都是指该 app 而不是 Native App)

//

Class HelloWorld extends App {

}


AppRegistry.registerComponent('HelloWorld', () =
>
 HelloWorld);

为什么业务方需要继承 App 组件?

App 作为一个入口组件主要提供了下面几个功能:

  • 初始化页面与管理页面渲染
  • 封装路由,管理路由配置
  • 与 Native 交互,绑定 Native 暴露的变量与方法,这些变量和方法的作用域与生命周期都与 app 一致
  • 处理侧滑返回,在 Native 侧滑返回(app 首页)与 RN 侧滑返回(非 app 首页)之间无缝自由切换
  • 集成 RN 原生导航栏,抹平平台差异。

所以,基于这些功能,业务方的入口组件需要继承 App 组件,否则业务开发需要自行去做这些成本巨大的工作。

除了继承,还有其他额外工作吗?

当然,你需要传入页面配置信息:

// main.js

import page1 from './src/Page1.js';
import page2 from './src/Page2.js';

const pages = [
    {
        component:page1,
        name:'page1',
        isInitialPage:true,
    },
    {
        component:page2,
        name:'page2',
    }
];

const navigationBarConfig = {
    hide:true, // 默认为 false
    backgroundColor:'rgb(1, 100, 200)', // 导航栏背景色
};

class HelloWorld extends App {
    constructor(props) {
        super(props);
        this.init({pages, navigationBarConfig});
    }
}

AppRegistry.registerComponent('HelloWorld', () =
>
 HelloWorld);

上面的代码就是一个完整的入口页面。

入口类HelloWorld仅需实现一下构造方法,并且调用一下init实例方法,传入pagesnavigationBarConfig参数,为了方便扩展,init方法的参数被设计为一个对象。

pages是一个数组,包含了当前 app 所有页面类配置信息,数组顺序并不是页面切换顺序。

pages的元素也是一个对象,代表一个 Page 类的配置:

{
    component:page1,
    name:'page1',
    isInitialPage:true,
 },

component是一个Page类名,根据这个类名实例化具体页面对象;

name页面名,页面切换时需要用到;

isInitialPage指定 app 首页,也可以在 URL 中指定,优先级:URL > 配置指定 > pages 数组第一个元素。

app 上的常量

app 会自动绑定到每个 Page 实例上,所以在每个页面中都是通过this.props.app访问到,app 上目前绑定了两个 Native 暴露的变量:

  • Bundle URL
  • Bundle URL Query (可以通过 URL 传入一些数据到 RN)
// 访问方式

this.props.app.URL;

this.props.app.URLQuery;

Page

app 对应整个AppRegistry.registerComponent注册组件的生命周期。

那么 Page 则对应每个页面。

// Page.js

class Page extends Component {

}

同样,Page 也是个基类,需要继承使用:

// Page1.js

class Page1 extends Page {

}

这里的 Page1 就是上面 App 配置里面引用的 Page1。

Page 提供哪些功能?

Page 封装了以下功能:

  • 页面切换(push/pop)
  • PV自动埋点
  • 页面生命周期自动管理

页面切换 push

继承了 Page 组件,你可以以最简单的方式区切换页面,完全不用关心导航组件。

// Page1.js

//切换到page2,这里的 page2 是之前配置里的页面
this.push('page2');

//也可以带参数到 page2
//page2 中通过 this.props.foo 访问
this.push('page2', {'foo':'bar'});

页面切换 pop

回退到上一个页面,如果使用了默认导航栏,切未自定义左侧返回按钮,那么会自动处理返回事件。如果需要手动调返回,那么只需要调用this.pop()即可。

// Page2.js

this.pop();

pop 回传参数

如果你需要传递数据到上一个页面,我建议的方式是上一个页面push过来时通过参数传第一个 callback 函数,手动 pop 之前通过回调上一个页面传过来的 callback 回传参数。

// Page2.js

this.props.callback(data);
this.pop();

PV自动埋点

按照产品统计标准,每次页面展示(包括从后一个页面回退回来)都会记录一次 PV。需要在 Page 子类中实现 pageId 函数:

// Page1.js

pageId() {
    return '62330005';
}

如果未实现 pageId 函数,则会使用 page name 作为 pageId 进行 PV 埋点。

ViewPort

ViewPort 可以理解为 Web 上的视口,页面展示的内容应该使用 ViewPort 包起来,因为 ViewPort 可以帮你做:

  • 根据导航栏的隐藏与否自动调整页面大小
  • 优化页面切换卡顿问题
// Page1.js

class Page1 extends Page {
    render() {
        return (

<
ViewPort
>
<
View style={styles.container}
>
<
Text style={styles.welcome}
>

                    Welcome to Page1

<
/Text
>
<
Text style={styles.instructions}
>

                    Shake or press menu button for dev menu

<
/Text
>
<
/View
>
<
/ViewPort
>

        );
    }

results matching ""

    No results matching ""