| 3 min read

React-360 源码阅读【3】

上一篇简单说了下 scripts 目录究竟用来做什么,今天我们开始进入到正题,我们看下Libraries 下究竟做了什么;

其实和 react-native 下的目录一致,罗列我们可用的组件和模块文件;比如:

  • Pano
  • Camera
  • Sound
  • ...

我们看下入口文件 react-360.js

const React360 = {
  // React Native overrides
  get View() {
    return require('View');
  },
  get Image() {
    return require('Image');
  },
  get Text() {
    return require('Text');
  },

  // VR Components and modules
  get AmbientLight() {
    return require('AmbientLight');
  },
  get Box() {
    return require('Box');
  },
  get LiveEnvCamera() {
    return require('LiveEnvCamera');
  },
  get Cylinder() {
    return require('Cylinder');
  },
  get CylindricalPanel() {
    return require('CylindricalPanel');
  },
  get QuadPanel() {
    return require('QuadPanel');
  },
  get Plane() {
    return require('Plane');
  },
  get Sphere() {
    return require('Sphere');
  },
  get DirectionalLight() {
    return require('DirectionalLight');
  },
  get PointLight() {
    return require('PointLight');
  },
  get SpotLight() {
    return require('SpotLight');
  },
  get Model() {
    return require('Model');
  },
  get Pano() {
    return require('Pano');
  },
  get Prefetch() {
    return require('Prefetch');
  },
  get Scene() {
    return require('Scene');
  },
  get Sound() {
    return require('Sound');
  },
  get Video() {
    return require('Video');
  },
  get VideoPano() {
    return require('VideoPano');
  },
  get VideoControl() {
    return require('VideoControl');
  },
  get MediaPlayerState() {
    return require('MediaPlayerState');
  },
  get VrAnimated() {
    return require('VrAnimated');
  },
  get VrButton() {
    return require('VrButton');
  },
  get VrHeadModel() {
    return require('VrHeadModel');
  },
  get VrSoundEffects() {
    return require('VrSoundEffects');
  },

  get Environment() {
    return require('Environment');
  },

  // React VR-specific utilities
  get asset() {
    return require('asset');
  },
  get staticAssetURL() {
    return require('staticAssetURL').default;
  },
  get texture() {
    return require('texture');
  },

  // Direct access to RN properties
  get Animated() {
    return require('Animated');
  },
  get AppRegistry() {
    return require('AppRegistry');
  },
  get AsyncStorage() {
    return require('AsyncStorage');
  },
  get NativeModules() {
    return require('NativeModules');
  },
  get StyleSheet() {
    return require('StyleSheet');
  },
};

module.exports = React360;

初一看,文件很明显,就是调用 React-360 模块,然后调用对应模块的代码;

比如我会在代码里面这么用:

import {View, Image} from 'react-360'

大家一看代码就知道了。这里其实关于 require 可能会有歧义;
似乎应该是

require('./View')

其实这里的 require 和 我们平常在 Node 当中用到的模块有些不一样;你可以在 Facebook 最新的项目 metro 里找到实现,当然这个我后面补一篇文章说下 metro

回到正题,我们可以把 Libraries 里面的模块和组件理解为整个 React-360 对外暴露的可以用到的部分。我们先从 最常用的组件 Components/View/View.vr.js 里面去看;

const EdgeInsetsPropType = require('EdgeInsetsPropType');
// 详见 https://github.com/facebook/react-native/blob/master/Libraries/Renderer/shims/NativeMethodsMixin.js
const NativeMethodsMixin = require('NativeMethodsMixin');
const PropTypes = require('prop-types');
const React = require('React');
const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
const ReactNativeViewAttributes = require('ReactNativeViewAttributes');
const StyleSheetPropType = require('StyleSheetPropType');
const UIManager = require('UIManager');
const ViewStylePropTypes = require('ViewStylePropTypes');

const createReactClass = require('create-react-class');
// https://github.com/facebook/react-native/blob/master/Libraries/ReactNative/requireNativeComponent.js 
// 需要阅读 https://github.com/facebook/react-native/blob/master/Libraries/Renderer/shims/createReactNativeComponentClass.js
const requireNativeComponent = require('requireNativeComponent');

const stylePropType = StyleSheetPropType(ViewStylePropTypes);


const AccessibilityTraits = [
  'none',
  'button',
  'link',
  'header',
  'search',
  'image',
  'selected',
  'plays',
  'key',
  'text',
  'summary',
  'disabled',
  'frequentUpdates',
  'startsMedia',
  'adjustable',
  'allowsDirectInteraction',
  'pageTurn',
];

const AccessibilityComponentType = [
  'none',
  'button',
  'radiobutton_checked',
  'radiobutton_unchecked',
];

...

我们从代码里看到了很多模块,而且很多模块是 React-Native 中所以这里面重点说几个文件;

requireNativeComponent.js

其实代码很简单, 在这之前需要先了解 createReactNativeComponentClass.js

import type {ViewConfigGetter} from './ReactNativeTypes';

// https://github.com/facebook/react-native/blob/master/Libraries/Renderer/shims/createReactNativeComponentClass.js
// 你可以将当前组件名称注册到某个地方,当加载 view 的配置时候则会出发你设置的回调
const {register} = require('ReactNativeViewConfigRegistry');

// 函数就是接受一个字符串也就是 component 的名称,然后可以接受 配置的回调函数
const createReactNativeComponentClass = function(
  name: string,
  callback: ViewConfigGetter,
): string {
  return register(name, callback);
};

module.exports = createReactNativeComponentClass;

接下来我们再来看 requireNativeComponent.js 就比较好理解了。

const createReactNativeComponentClass = require('createReactNativeComponentClass');
const getNativeComponentAttributes = require('getNativeComponentAttributes');

/**
 其实我们是通过一种映射,类似将 react-360 里面的组件 view 映射到本地运行时的 RTCView ,然后我们会将这些模块进行创建然后存储起来。
 *
 */
const requireNativeComponent = (uiViewClassName: string): string =>
  createReactNativeComponentClass(uiViewClassName, () =>
    getNativeComponentAttributes(uiViewClassName),
  );

module.exports = requireNativeComponent;

下一篇我们在继续讲 view 的代码吧。

You Can Speak "Hi" to Me in Those Ways