ReactXP چیست؟ (بخش پنجم)
باسلام و وقت بخیر.
در این مقاله و در بخش پنجم آموزش Reactxp به extension (افزونه) های موجود در آن می پردازیم. بنابراین با ما در مجموعه ABLY همراه باشید.
"Reactxp چیست؟"
ReactXP چیست؟ (بخش پنجم) | آموزش برنامه نویسی
برنامه نویسی ReactXP
extension در Reactxp
کتابخانه ReactXP بسیار سبک وزن طراحی شده که در آن API ها، پلت فرم ها و اجزای "اولیه" که تقریباً در هر برنامه مورد نیاز است، وجود دارد. کارکردی که کمتر مورد نیاز است، در قالب extension های اختیاری ارائه می شود.
2 نوع از extension (افزونه ها)
- API های اضافی یا کامپوننت های "اولیه" که پیاده سازی های جداگانه ای برای هر یک از سیستم عامل های پشتیبانی شده دارند.
- کامپوننت های سطح بالا که حاوی کد خاصی از پلتفرم نیستند، اما بر پایه های سطح پایین تر به منظور ارائه قابلیت های جدید (به طور معمول پیچیده تر) هستند.
- افزونه ها به صورت جداگانه از طریق بسته های npm منتشر می شوند. آنها معمولاً با پیشوند " reactxp-" شروع می شوند.
افزونه های اولیه ReactXP
برای استفاده از یک افزونه اولیه در برنامه خود، آن را به package.json خود اضافه کنید (مانند هر ماژول npm دیگر). سپس آن را در بالای ماژول کدی که می خواهید از آن استفاده کنید، وارد کنید.
در اینجا یک مثال از نحوه استفاده از فرمت فرضی است که توانایی پخش ویدئو را به صورت متقابل پلتفرم فراهم می کند:
import RXVideoPlayer from 'reactxp-videoplayer';
class MyVideoPanel extends RX.Component {
render() {
return (
<RXVideoPlayer
source={ this.props.source }
showControls={ true }
onProgress={ this._onVideoProgress }
onEnded={ this._onVideoEnded }
/>
);
}
}
پیاده سازی یک افزونه "اولیه" جدید
یک افزونه " اولیه " جدید (یا کامپوننت یا فضای نامی API) باید رابط کاربری متقابل پلتفرم و پیاده سازی خاص پلتفرم این رابط را برای هر یک از سیستم عامل های پشتیبانی شده توسط ReactXP داشته باشد. در بعضی موارد، این پیاده سازی ممکن است بین چند پلتفرم به اشتراک گذاشته شود.
کامپوننت های سطح بالا تر ReactXP
استفاده از اجزای سطح بالاتر همانند استفاده از هر مولفه دیگر در React است. از آنجا که این اجزاء بر پایه های ReactXP متقابل پلتفرم ساخته شده اند، آنها همچنین به صورت cross-platform کار می کنند.
مطلب مرتبط: کامپوننت ها در Reactxp
extension ها در ReactXP
- Database
ReactXP یک API ذخیره سازی (Storage API ) برای خواندن و نوشتن کلید / ارزش (key/value) ساده فراهم می کند. بسیاری از برنامه ها نیازهای ذخیره سازی پیچیده تر را دارند. برای این، یک بسته بندی پایگاه داده بدون SQL ایجاد شده است که در React Native و در مرورگرها کار می کند.
- ImageSvg
این کامپوننت یک تصویر را با فرمت SVG نشان می دهد که می تواند از یک منبع محلی یا از شبکه باشد.
مسیر (ها) با استفاده از قالب رشته استاندارد SVG و در یک کامپوننت SvgPath مشخص شوند.
- نصب: npm install reactxp-imagesvg
ImageSvg Props
style: RX.ImageSvgStyleRuleSet | RX.ImageSvgStyleRuleSet[] = [];
// Color and opacity of fill; default values are provided by SVG
fillColor: color;
fillOpacity: number;
// Preserve aspect ratio or stretch?
preserveAspectRatio: boolean = true;
// Color, width and opacity of stroke; default values are provided by SVG
strokeColor: color;
strokeWidth: number;
strokeOpacity: number;
// Tooltip for image
title: string = undefined;
// Bounding box
viewBox: string = undefined;
// Shadow
webShadow: boolean = false; // web-specific
SvgPath Props
d: string = undefined;
// Color and opacity of fill; default values are provided by SVG
fillColor: color;
fillOpacity: number;
// Color, width and opacity of stroke; default values are provided by SVG
strokeColor: color;
strokeWidth: number;
strokeOpacity: number;
Methods
متدی ندارد
مثال:
);
- Navigator
این جزء یک پشته مجازی از "کارت" را برای برنامه فراهم می کند که تماس گیرنده می تواند نوع و جهت انیمیشن را کنترل کند.
هنگامی که یک کارت جدید ارائه می شود، Navitator روش renderScene را فراخوانی می کند و اجازه می دهد که تماس گیرنده محتویات را رندر کند. کارت ها بوسیله "مسیرها" شناسایی می شوند که حاوی شناسه منحصر به فرد و پارامترهای پیکربندی هستند که رفتار رفت و آمد را کنترل می کنند.
هنگامی که یک ناویگاتور برای اولین بار نصب می شود، پشته خالی است. تماس گیرنده باید صبر کند تا مقدار آن کامل شود، سپس لیست مسیرهای ارائه را مشخص نماید.
- نصب: npm install reactxp-navigator
Types
// Specifies the behavior when transitioning from one
// card to another within the stack.
enum NavigatorSceneConfigType {
FloatFromRight,
FloatFromLeft,
FloatFromBottom,
Fade,
FadeWithSlide
}
// Provides information about a card and how it should
// be presented when pushed onto the stack or popped
// off the stack.
interface NavigatorRoute {
// Uniquely identifies the card
routeId: number;
// Animation parameter
sceneConfigType: NavigatorSceneConfigType;
// Optional gesture response distance override;
// 0 is equivalent to disabling gestures;
// works only on React Native platforms
gestureResponseDistance?: number;
// Optional custom scene config;
// works only on React Native platforms
customSceneConfig?: CustomNavigatorSceneConfig;
}
Props
// Style to apply to the card
cardStyle: ViewStyleRuleSet = undefined;
// Called to render the specified scene
renderScene: (route: NavigatorRoute) => JSX.Element = undefined;
// Called when a transition between cards is complete
transitionCompleted: () => void = undefined;
Methods
getCurrentRoutes(): Types.NavigatorRoute[];
// Replaces the current list of routes with a new list
immediatelyResetRouteStack(
nextRouteStack: Types.NavigatorRoute[]): void;
// Pops the top route off the stack
pop(): void;
// Pops zero or more routes off the top of the stack until
// the specified route is top-most
popToRoute(route: Types.NavigatorRoute): void;
// Pops all routes off the stack except for the last
// remaining item in the stack
popToTop(): void;
// Push a new route onto the stack
push(route: Types.NavigatorRoute): void;
// Replaces the top-most route with a new route
replace(route: Types.NavigatorRoute): void;
// Replaces an existing route (identified by index) with
// a new route
replaceAtIndex(route: Types.NavigatorRoute, index: number): void;
// Replaces the next-to-top-most route with a new route
replacePrevious(route: Types.NavigatorRoute): void;
مثال:
این نمونه نشان می دهد که چگونه یک برنامه می تواند از Navigator برای ارائه یک پشته با دو کارت استفاده کند و به کاربر اجازه می دهد بین آنها حرکت کند. برای یک نمونه کامل از کار، برنامه نمونه Hello-World را ببینید.
MainPanel,
SecondPanel
};
class App extends RX.Component<null, null> {
private _navigator: RX.Navigator;
componentDidMount() {
// Now that the app is mounted, specify the initial
// navigator route.
this._navigator.immediatelyResetRouteStack([{
routeId: NavigationRouteId.MainPanel,
sceneConfigType: RX.Types.NavigatorSceneConfigType.Fade
}]);
}
render() {
return (
<RX.Navigator
ref={ this._onNavigatorRef }
renderScene={ this._renderScene }
/>
);
}
private _onNavigatorRef = (naviator: RX.Navigator) => {
// Stash away a reference to the mounted navigator
this._navigator = navigator;
}
private _renderScene = (route: NavigatorRoute) => {
switch (navigatorRoute.routeId) {
case NavigationRouteId.MainPanel:
return (
<MainPanel
onPressNavigate={ this._onPressNavigate }
/>
);
case NavigationRouteId.SecondPanel:
return (
<SecondPanel
onNavigateBack={ this._onPressBack }
/>
);
}
return null;
}
// Called when the user presses a button on the MainPanel
// to navigate to the SecondPanel.
private _onPressNavigate = () => {
this._navigator.push({
routeId: NavigationRouteId.SecondPanel,
sceneConfigType:
RX.Types.NavigatorSceneConfigType.FloatFromRight,
customSceneConfig: {
hideShadow: true
}
});
}
// Called when the user presses a back button on the
// SecondPanel to navigate back to the MainPanel.
private _onPressBack = () => {
this._navigator.pop();
}
}
Experimental Types
این انواع فقط برای سیستم عامل React Native اعمال میشوند و در حال حاضر به «Navigator Experimental» متصل هستند. برخی از این انواع ممکن است در آینده نزدیک از بین بروند، بنابراین با احتیاط استفاده کنید.
// Additional options that affect card transitions
type CustomNavigatorSceneConfig = {
// Optional transition styles
transitionStyle?: (sceneIndex: number,
sceneDimensions: Dimensions) =>
NavigationTransitionStyleConfig;
// Optional overrides for duration, easing, and timing
transitionSpec?: NavigationTransitionSpec;
// Optional cardStyle override
cardStyle?: ViewStyleRuleSet;
// Optionally hide drop shadow
hideShadow?: boolean;
// Optionally flip the visual order of the last two scenes
presentBelowPrevious?: boolean;
};
// Parameters to control transition animations
type NavigationTransitionSpec = {
duration?: number;
easing?: Animated.EasingFunction;
};
// Parameters to control transition appearance
type NavigationTransitionStyleConfig = {
// By default, input range is defined as [index - 1, index, index + 1];
// Input and output ranges must contain the same number of elements
inputRange?: number[];
opacityOutput: number | number[];
scaleOutput: number | number[];
translateXOutput: number | number[];
translateYOutput: number | number[];
};
Experimental Props
این Props فقط برای سیستم عامل React Native اعمال میشوند و در حال حاضر به «Navigator Experimental» متصل هستند. برخی از این Props ممکن است در آینده نزدیک از بین بروند، بنابراین با احتیاط استفاده کنید.
// Called after the user swipes back in the stack and the transition
// is complete
navigateBackCompleted: () => void;
// Called when a transition begins; works only
// on native
transitionStarted: (progress?: RX.AnimatedValue,
toRouteId?: string, fromRouteId?: string,
toIndex?: number, fromIndex?: number) => void = undefined;
- REST Client
REST Client، API های شبکه اصلی (Network APIs) را برای تعیین اتصال شبکه فراهم می کند.
برای اطلاعات بیشتر به سایت گیت هاب SimpleRestClients مراجعه کنید.
- نصب: npm install simplerestclients
مثال:
id: string;
firstName: string;
lastName: string;
}
class MyRestClient extends GenericRestClient {
constructor(private _appId: string) {
super('https://myhost.com/api/v1/');
}
// Override _getHeaders to append a custom header with the app ID.
protected _getHeaders(options: ApiCallOptions): { [key: string]: string } {
let headers = super._getHeaders(options);
headers['X-AppId'] = this._appId;
return headers;
}
// Define public methods that expose the APIs provided through
// the REST service.
getAllUsers(): SyncTasks.Promise {
return this.performApiGet('users');
}
getUserById(id: string): SyncTasks.Promise {
return this.performApiGet('user/' + id);
}
setUser(user: User): SyncTasks.Promise {
return this.performApiPut('user/' + user.id, user);
}
}
- Video
این کامپوننت قابلیت های پخش ویدئو، ارائه کنترل های اختیاری برای پخش، مکث و غیره را ارائه می دهد.
- نصب: npm install reactxp-video
Types
// Used to return progress information in the onProgress callback
interface VideoProgress {
currentTime: number;
playableDuration: number;
atValue?: number;
target?: number;
atTimeScale?: number;
}
// Used to return information about the video once its metadata
// has been loaded; returned by the onLoadedData callback
interface VideoInfo {
duration?: number;
naturalSize?: {
width: number;
height: number;
};
}
Props
// Alternate text to display if the image cannot be loaded
// or by screen readers
accessibilityLabel: string = undefined;
// Authentication token to include in request (not supported
// on some React Native implementations)
authToken: string = undefined;
// Should video playback loop to beginning after it completes?
loop: boolean = false;
// Called when the video is paused for buffering
onBuffer: () => void = undefined;
// Called when enough of the video has been loaded that playback
// is possible
onCanPlay: () => void = undefined;
// Called when enough of the video has been loaded that playback
// can proceed all the way to the end without buffering pauses
onCanPlayThrough: () => void = undefined;
// Called when the video playback reaches the end
onEnded: () => void = undefined;
// Called when the video cannot be loaded
onError: () => void = undefined;
// Called when the video's metadata has been loaded; returns
// information about the video
onLoadedData: (info: VideoInfo) => void = undefined;
// Called when the video data is starting to load
onLoadStart: () => void = undefined;
// Called periodically when the video is playing; reports
// progress information
onProgress: (progress: VideoProgress) => void = undefined;
// Indiciates which portion of the video should be pre-loaded
// when the component is mounted
preload: 'auto'|'metadata'|'none' = 'none';
// Determines how to resize the image if its natural size
// does not match the size of the container
resizeMode: 'contain'|'cover'|'stretch' = 'contain';
// Displays controls for play, pause, etc.
showControls: boolean = false;
// Source of video (URL)
source: string;
// See below for supported styles
style: ViewStyleRuleSet | ViewStyleRuleSet[] = [];
Methods
// Mutes or unmutes the sound for the video
mute(muted: boolean): void;
// Pauses the video
pause(): void;
// Plays the video at its current position
play(): void;
// Seeks to the specified position (specified in seconds)
seek(position: number): void;
مثال:
<RX.Video
source={ 'http://mydomain.com/coolvideo.mp4' }
/>
);
- VirtualListView
این کامپوننت یک لیست عمودی از آیتم ها را نشان می دهد که قسمت قابل مشاهده از لیست "پورت نمایش" نام دارد و به صورت مجازی است. به این معنی که فقط آیتم هایی را نشان می دهد که در پورت نمایش قرار دارند.
هر آیتم در لیست توسط یک شیء VirtualListViewItemInfo توصیف می شود. فهرست این آیتم توسط یک لیست مرتب شده در پرونده itemList منتقل می شود. وقتی یک مورد به نظر می رسد، با استفاده از callback renderItem رندر می شود. فیلد های اضافی را می توان به عنوان Caller به VirtualListViewItemInfo اضافه کرد. به عنوان مثال، گاهی اوقات مفید است که شامل اطلاعات شناسایی اضافی مانند نوع آیتم یا یک روش رندر خاص مورد باشد.
بر خلاف نمایش های دیگر لیست (مانند ListView ارائه شده در React Native)، این جزء از لیست آیتم ناهمگن با ارتفاع های مختلف و انواع کاملاً متفاوت پشتیبانی می کند.
ارتفاع برای هر مورد باید مشخص شود. به طور پیش فرض، این ارتفاع فرض دقیق و ثابت است. اگر ارتفاع شیء را نمی دانید و یا ممکن است تغییر کند، ارتفاع را می توان در زمان اجرا اندازه گیری کرد. استفاده از این گزینه خطرناک است، بنابراین در صورت امکان، باید از آن اجتناب شود.
این گزینه به صورت اختیاری از انیمیشن آیتم ها پشتیبانی می کند.
- نصب: npm install reactxp-virtuallistview
مثال:
from 'reactxp-virtuallistview';
// Extend VirtualListViewItemInfo to include display text
interface FruitListItemInfo extends VirtualListViewItemInfo {
text: string;
}
interface FruitListState {
items: FruitListItemInfo[];
}
const _headerItemHeight = 20;
const _fruitItemHeight = 32;
const _headerItemTemplate = 'header';
const _fruitItemTemplate = 'fruit';
class FruitListView extends RX.Component {
constructor() {
super();
this.state = {
items: [{
key: 'header1',
height: _headerItemHeight,
text: 'Domstic Fruits',
template: _headerItemTemplate
}, {
key: 'bannana',
height: _fruitItemHeight,
text: 'Banana',
template: _fruitItemTemplate
}, {
key: 'apple',
height: _fruitItemHeight,
text: 'Apple',
template: _fruitItemTemplate
}]
};
}
render() {
return (
<VirtualListView
itemList={ this.state.items }
renderItem={ this._renderItem }
animateChanges={ true }
skipRenderIfItemUnchanged={ true }
/>
);
}
private _renderItem(item: FruitListItemInfo, hasFocus?: boolean) {
const viewStyle = RX.Styles.createViewStyle({
height: item.height,
backgroundColor: item.template === _headerItemTemplate ?
'#ddd' : '#fff',
alignItems: 'center'
}, false);
return (
{ item.text }
);
}
}
Interfaces
// A string that uniquely identifies this item.
key: string;
// Specifies the known height of the item or a best guess if the
// height isn't known.
height: number;
// Specifies that the height is not known and needs to be measured
// dynamically. This has a big perf overhead because it requires a
// double layout (once offscreen to measure the item). It also
// disables cell recycling. Wherever possible, it should be avoided,
// especially for perf-critical views.
measureHeight?: boolean;
// Specify the same "template" string for items that are rendered
// with identical or similar view hierarchies. When a template is
// specified, the list view attempts to recycle cells whose templates
// match. When an item scrolls off the screen and others appear on
// screen, the contents of the cell are simply updated rather than
// torn down and rebuilt.
template: string;
// Is the item navigable by keyboard or through accessibility
// mechanisms?
isNavigable?: boolean;
}
Props
itemList: VirtualListViewItemInfo[];
// Callback for rendering item when it becomes visible within view port.
renderItem: (item: VirtualListViewItemInfo, hasFocus?: boolean) =>
JSX.Element | JSX.Element[];
// Optional padding around the scrolling content within the list.
padding?: number;
// If true, allows each item to overflow its visible cell boundaries;
// by default, item contents are clipped to cell boundaries.
showOverflow?: boolean;
// Should the list animate additions, removals and moves within the list?
animateChanges?: boolean;
// By default, VirtualListView re-renders every item during the render.
// Setting this flag to true allows the list view to re-render only
// items from itemList whose descriptor has changed, thus avoiding
// unnecessary rendering. It uses _.isEqual to perform this check. In
// this mode, renderItem should not depend on any external state, only
// on VirtualListViewItemInfo, to render item.
skipRenderIfItemUnchanged?: boolean;
// Pass-through properties for scroll view.
keyboardDismissMode?: 'none' | 'interactive' | 'on-drag';
keyboardShouldPersistTaps?: boolean;
disableScrolling?: boolean;
scrollsToTop?: boolean; // iOS only, scroll to top on status bar tap
disableBouncing?: boolean; // iOS only, bounce override
scrollIndicatorInsets?: { top: number, left: number,
bottom: number, right: number }; // iOS only
onScroll?: (scrollTop: number, scrollLeft: number) => void;
// Logging callback to debug issues related to the VirtualListView.
logInfo?: (textToLog: string) => void;
Methods
// Scrolls the view to the specified top value (specified in pixels).
scrollToTop(animated = true, top = 0);
منبع: microsoft.github.io
"منتشر شده در سایت ABLY"