├── .watchmanconfig
├── App.js
├── .gitignore
├── src
├── assets
│ └── icon.png
├── util
│ └── index.js
├── components
│ ├── Stories
│ │ ├── Footer.vue
│ │ ├── Story.vue
│ │ ├── index.vue
│ │ ├── Footer.js
│ │ ├── index.js
│ │ └── Story.js
│ ├── Header
│ │ ├── Left.vue
│ │ └── Left.js
│ └── TabView
│ │ ├── Scroller.vue
│ │ ├── index.vue
│ │ ├── Scroller.js
│ │ └── index.js
├── store
│ ├── mutations.js
│ ├── fetch.js
│ ├── actions.js
│ └── index.js
├── views
│ ├── WebSite.vue
│ ├── Home.vue
│ ├── WebSite.js
│ └── Home.js
└── index.js
├── .babelrc
├── jsconfig.json
├── App.test.js
├── app.json
├── .eslintrc
├── package.json
├── .flowconfig
└── README.md
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/App.js:
--------------------------------------------------------------------------------
1 | export { default } from './src';
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .expo/
3 | npm-debug.*
4 |
--------------------------------------------------------------------------------
/src/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SmallComfort/HackerNews/HEAD/src/assets/icon.png
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["babel-preset-expo"],
3 | "env": {
4 | "development": {
5 | "plugins": ["transform-react-jsx-source"]
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowJs": true,
4 | "allowSyntheticDefaultImports": true
5 | },
6 | "exclude": [
7 | "node_modules"
8 | ]
9 | }
--------------------------------------------------------------------------------
/src/util/index.js:
--------------------------------------------------------------------------------
1 | import { Dimensions } from 'react-native';
2 |
3 | export const SCREEN_WIDTH = Dimensions.get('window').width;
4 | export const SCREEN_HEIGHT = Dimensions.get('window').height;
5 |
6 | export function emptyFn() {}
--------------------------------------------------------------------------------
/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import App from './App';
3 |
4 | import renderer from 'react-test-renderer';
5 |
6 | it('renders without crashing', () => {
7 | const rendered = renderer.create().toJSON();
8 | expect(rendered).toBeTruthy();
9 | });
10 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "name": "HackerNews",
4 | "description": "A mobile app for Hacker News, powered by Vue and React Native",
5 | "sdkVersion": "17.0.0",
6 | "icon": "./src/assets/icon.png",
7 | "loading": {
8 | "icon": "./src/assets/icon.png",
9 | "hideExponentText": true
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/components/Stories/Footer.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
20 |
--------------------------------------------------------------------------------
/src/store/mutations.js:
--------------------------------------------------------------------------------
1 |
2 | export function SET_ACTIVE_TYPE (state, { type }) {
3 | state.activeType = type;
4 | }
5 |
6 | export function SET_LIST (state, { type, ids }) {
7 | state.lists[type] = ids;
8 | }
9 |
10 | export function SET_ITEMS (state, { items, type }) {
11 | state.items[type] = state.items[type]
12 | .concat(items)
13 | .reduce((acc, val) => {
14 | for (let i = 0, j = acc.length; i < j; i++) {
15 | if (acc[i].id === val.id) {
16 | return acc.splice(i, 1, val);
17 | }
18 | }
19 | acc.push(val);
20 | return acc;
21 | }, []);
22 | }
23 |
--------------------------------------------------------------------------------
/src/store/fetch.js:
--------------------------------------------------------------------------------
1 | const baseURL = 'https://hacker-news.firebaseio.com/v0';
2 |
3 | export function _fetch (path) {
4 | return fetch({
5 | method: 'GET',
6 | url: `${baseURL}/${path}.json`
7 | })
8 | .then((response) => response.json());
9 | }
10 |
11 | export function fetchIdsByType (type) {
12 | return _fetch(`${type}stories`);
13 | }
14 |
15 | export function fetchItem (id) {
16 | return _fetch(`item/${id}`);
17 | }
18 |
19 | export function fetchItems (ids) {
20 | return Promise.all(ids.map(id => fetchItem(id)));
21 | }
22 |
23 | export function fetchUser (id) {
24 | return _fetch(`user/${id}`);
25 | }
26 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["eslint:recommended"],
3 | "parserOptions": {
4 | "ecmaVersion": 6,
5 | "sourceType": "module",
6 | "ecmaFeatures": {
7 | "experimentalObjectRestSpread": true,
8 | "jsx": true
9 | }
10 | },
11 | "parser": "babel-eslint",
12 | "env": {
13 | "browser": true,
14 | "commonjs": true,
15 | "node": true,
16 | "es6": true
17 | },
18 | "rules": {
19 | "no-console": 0,
20 | "quotes": [2, "single"],
21 | "strict": [2, "never"],
22 | "semi": [2, "always"],
23 | "react/jsx-uses-react": 2,
24 | "react/jsx-uses-vars": 2,
25 | "react/react-in-jsx-scope": 2
26 | },
27 | "plugins": [
28 | "react",
29 | "html"
30 | ]
31 | }
--------------------------------------------------------------------------------
/src/views/WebSite.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
32 |
33 |
38 |
--------------------------------------------------------------------------------
/src/components/Header/Left.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
21 |
22 |
40 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { StatusBar, Platform } from 'react-native';
3 | import { StackNavigator } from 'react-navigation';
4 | import Home from './views/Home';
5 | import WebSite from './views/WebSite';
6 | import Left from './components/Header/Left';
7 |
8 | Home.navigationOptions = {
9 | title: 'Hacker News',
10 | headerTitleStyle: {
11 | color: '#ff6600'
12 | }
13 | };
14 |
15 | WebSite.navigationOptions = ({ navigation }) => {
16 | return {
17 | title: navigation.state.params.title,
18 | headerTitleStyle: {
19 | color: '#ff6600'
20 | },
21 | headerLeft:
22 | };
23 | };
24 |
25 | export default StackNavigator({
26 | Home: { screen: Home },
27 | WebSite: { screen: WebSite }
28 | }, {
29 | cardStyle: {
30 | paddingTop: Platform.OS === 'ios' ? 0 : StatusBar.currentHeight
31 | }
32 | });
33 |
34 |
--------------------------------------------------------------------------------
/src/store/actions.js:
--------------------------------------------------------------------------------
1 | import { fetchItems, fetchIdsByType } from './fetch';
2 |
3 | const LOAD_MORE_STEP = 10;
4 |
5 | // ensure data for rendering given list type
6 | export function FETCH_LIST_DATA ({ commit, dispatch }, { type }) {
7 | commit('SET_ACTIVE_TYPE', { type });
8 | return fetchIdsByType(type)
9 | .then(ids => commit('SET_LIST', { type, ids }))
10 | .then(() => dispatch('ENSURE_ACTIVE_ITEMS'));
11 | }
12 |
13 | // load more items
14 | export function LOAD_MORE_ITEMS ({ dispatch, state }) {
15 | state.counts[state.activeType] += LOAD_MORE_STEP;
16 | return dispatch('ENSURE_ACTIVE_ITEMS');
17 | }
18 |
19 | // ensure all active items are fetched
20 | export function ENSURE_ACTIVE_ITEMS ({ dispatch, getters }) {
21 | return dispatch('FETCH_ITEMS', {
22 | ids: getters.activeIds
23 | });
24 | }
25 |
26 | export function FETCH_ITEMS ({ commit, state }, { ids }) {
27 | const type = state.activeType;
28 | return ids.length
29 | ? fetchItems(ids).then(items => commit('SET_ITEMS', { items, type }))
30 | : Promise.resolve();
31 | }
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "HackerNews",
3 | "version": "0.1.0",
4 | "private": true,
5 | "devDependencies": {
6 | "babel-eslint": "^7.2.3",
7 | "eslint": "^4.0.0",
8 | "eslint-plugin-html": "^3.0.0",
9 | "eslint-plugin-react": "^7.1.0",
10 | "jest-expo": "~1.0.1",
11 | "react-native-scripts": "0.0.31",
12 | "react-vue-native-scripts": "0.0.2-rc1",
13 | "react-test-renderer": "16.0.0-alpha.6"
14 | },
15 | "main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
16 | "scripts": {
17 | "start": "react-native-scripts start",
18 | "compiler": "react-vue-native-scripts compiler",
19 | "eject": "react-native-scripts eject",
20 | "android": "react-native-scripts android",
21 | "ios": "react-native-scripts ios",
22 | "test": "node node_modules/jest/bin/jest.js --watch"
23 | },
24 | "jest": {
25 | "preset": "jest-expo"
26 | },
27 | "dependencies": {
28 | "expo": "^17.0.0",
29 | "react": "16.0.0-alpha.6",
30 | "react-native": "^0.44.0",
31 | "react-navigation": "^1.0.0-beta.11",
32 | "vuex": "^2.3.1",
33 | "react-vue": "0.0.3-rc1",
34 | "react-vue-helper": "0.0.3-rc1"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * reference
3 | * https://github.com/weexteam/weex-hackernews/tree/master/src/store
4 | */
5 |
6 | import Vue from 'react-vue';
7 | import Vuex from 'vuex';
8 | import * as actions from './actions';
9 | import * as mutations from './mutations';
10 |
11 | Vue.use(Vuex);
12 |
13 | const store = new Vuex.Store({
14 | actions,
15 | mutations,
16 |
17 | state: {
18 | activeType: 'top',
19 | items: {
20 | top: [],
21 | new: [],
22 | show: [],
23 | ask: [],
24 | job: []
25 | },
26 | counts: {
27 | top: 0,
28 | new: 0,
29 | show: 0,
30 | ask: 0,
31 | job: 0
32 | },
33 | lists: {
34 | top: [],
35 | new: [],
36 | show: [],
37 | ask: [],
38 | job: []
39 | }
40 | },
41 |
42 | getters: {
43 | // ids of the items that should be currently displayed based on
44 | // current list type and current pagination
45 | activeIds (state) {
46 | const { activeType, lists, counts } = state;
47 | const result = activeType ? lists[activeType].slice(counts[activeType], counts[activeType] + 10) : [];
48 | return result;
49 | },
50 |
51 | activeIndex (state) {
52 | const { activeType, lists } = state;
53 | const index = Object.keys(lists).indexOf(activeType);
54 | return index === -1 ? 0 : index;
55 | }
56 | }
57 | });
58 |
59 | export default store;
60 |
--------------------------------------------------------------------------------
/src/components/Stories/Story.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{item.score}}
5 |
6 |
7 | {{item.by}}
8 | {{item.title}}
9 |
10 |
11 |
12 |
13 |
35 |
36 |
68 |
--------------------------------------------------------------------------------
/src/components/Stories/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
74 |
75 |
80 |
--------------------------------------------------------------------------------
/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | ; We fork some components by platform
3 | .*/*[.]android.js
4 |
5 | ; Ignore "BUCK" generated dirs
6 | /\.buckd/
7 |
8 | ; Ignore unexpected extra "@providesModule"
9 | .*/node_modules/.*/node_modules/fbjs/.*
10 |
11 | ; Ignore duplicate module providers
12 | ; For RN Apps installed via npm, "Libraries" folder is inside
13 | ; "node_modules/react-native" but in the source repo it is in the root
14 | .*/Libraries/react-native/React.js
15 | .*/Libraries/react-native/ReactNative.js
16 |
17 | ; Additional create-react-native-app ignores
18 |
19 | ; Ignore duplicate module providers
20 | .*/node_modules/fbemitter/lib/*
21 |
22 | ; Ignore misbehaving dev-dependencies
23 | .*/node_modules/xdl/build/*
24 | .*/node_modules/reqwest/tests/*
25 |
26 | ; Ignore missing expo-sdk dependencies (temporarily)
27 | ; https://github.com/expo/expo/issues/162
28 | .*/node_modules/expo/src/*
29 |
30 | ; Ignore react-native-fbads dependency of the expo sdk
31 | .*/node_modules/react-native-fbads/*
32 |
33 | [include]
34 |
35 | [libs]
36 | node_modules/react-native/Libraries/react-native/react-native-interface.js
37 | node_modules/react-native/flow
38 | flow/
39 |
40 | [options]
41 | module.system=haste
42 |
43 | emoji=true
44 |
45 | experimental.strict_type_args=true
46 |
47 | munge_underscores=true
48 |
49 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
50 |
51 | suppress_type=$FlowIssue
52 | suppress_type=$FlowFixMe
53 | suppress_type=$FixMe
54 |
55 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-2]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
56 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-2]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
57 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
58 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
59 |
60 | unsafe.enable_getters_and_setters=true
61 |
62 | [version]
63 | ^0.42.0
64 |
--------------------------------------------------------------------------------
/src/components/Stories/Footer.js:
--------------------------------------------------------------------------------
1 | import __react__vue__Vue, {
2 | observer as __react__vue__observer
3 | } from 'react-vue'
4 | import __react__vue__ReactNative from 'react-native'
5 | import __react__vue__PropType from 'prop-types'
6 | import {
7 | buildNativeComponent as __react__vue__buildNativeComponent
8 | } from 'react-vue-helper'
9 | import {
10 | bindNativeClass as __react__vue__bindClass,
11 | bindNativeStyle as __react__vue__bindStyle,
12 | mergeProps as __react__vue__mergeProps
13 | } from 'react-vue-helper'
14 | import {
15 | createElement as __react__vue__createElement,
16 | Component as __react__vue__Component
17 | } from 'react'
18 |
19 | const __react__vue__options = {}
20 |
21 | const __react__vue__render = function render(vm) {
22 | return __react__vue__createElement(vm.$options.components['View'], __react__vue__mergeProps.call(this, this.props.__react__vue__nativeEvents, {
23 | ref: ref => {
24 | this.setRootRef(ref);
25 | this.props['__react__vue__setRef'] && this.props['__react__vue__setRef'](ref);
26 | },
27 | style: [__react__vue__bindClass.call(this, {
28 | staticClass: "footer",
29 | parentClass: this.props.style
30 | }), __react__vue__bindStyle(undefined, undefined, undefined)]
31 | }), __react__vue__createElement(vm.$options.components['Text'], {
32 | style: [__react__vue__bindClass.call(this, {
33 | staticClass: "text"
34 | })]
35 | }, "loading..."));
36 | };
37 |
38 | const __react__vue__css = {
39 | "footer": {
40 | "flex": 1,
41 | "paddingTop": 24,
42 | "paddingBottom": 44,
43 | "justifyContent": "center",
44 | "alignItems": "center"
45 | },
46 | "text": {
47 | "color": "#999"
48 | }
49 | }
50 |
51 | const __react__vue__ComponentBuilded = __react__vue__buildNativeComponent(__react__vue__render, __react__vue__options, {
52 | Component: __react__vue__Component,
53 | PropTypes: __react__vue__PropType,
54 | Vue: __react__vue__Vue,
55 | ReactNative: __react__vue__ReactNative,
56 | css: __react__vue__css
57 | })
58 |
59 | export default __react__vue__observer(__react__vue__ComponentBuilded)
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
14 |
15 |
16 |
17 |
81 |
82 |
87 |
88 |
--------------------------------------------------------------------------------
/src/components/TabView/Scroller.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
21 |
22 |
23 |
24 |
25 |
26 |
85 |
86 |
91 |
--------------------------------------------------------------------------------
/src/views/WebSite.js:
--------------------------------------------------------------------------------
1 | import __react__vue__Vue, {
2 | observer as __react__vue__observer
3 | } from 'react-vue'
4 | import __react__vue__ReactNative from 'react-native'
5 | import __react__vue__PropType from 'prop-types'
6 | import {
7 | buildNativeComponent as __react__vue__buildNativeComponent
8 | } from 'react-vue-helper'
9 | import {
10 | bindNativeClass as __react__vue__bindClass,
11 | bindNativeStyle as __react__vue__bindStyle,
12 | mergeProps as __react__vue__mergeProps
13 | } from 'react-vue-helper'
14 | import {
15 | createElement as __react__vue__createElement,
16 | Component as __react__vue__Component
17 | } from 'react'
18 |
19 |
20 | const __react__vue__options = {
21 | props: {
22 | navigation: {
23 | type: Object
24 | }
25 | },
26 | computed: {
27 | uri() {
28 | const {
29 | params
30 | } = this.navigation.state;
31 | return params.url;
32 | }
33 | },
34 | methods: {
35 | onLoadEnd() {
36 | this.navigation.setParams({
37 | title: ''
38 | });
39 | },
40 | onLoadStart() {
41 | this.navigation.setParams({
42 | title: 'loading...'
43 | });
44 | }
45 | }
46 | };
47 |
48 | const __react__vue__render = function render(vm) {
49 | return __react__vue__createElement(vm.$options.components['WebView'], __react__vue__mergeProps.call(this, this.props.__react__vue__nativeEvents, {
50 | ref: ref => {
51 | this.setRootRef(ref);
52 | this.props['__react__vue__setRef'] && this.props['__react__vue__setRef'](ref);
53 | },
54 | source: {
55 | uri: vm['uri']
56 | },
57 | onLoadEnd: vm['onLoadEnd'],
58 | onLoadStart: vm['onLoadStart'],
59 | style: [__react__vue__bindClass.call(this, {
60 | staticClass: "web",
61 | parentClass: this.props.style
62 | }), __react__vue__bindStyle(undefined, undefined, undefined)]
63 | }));
64 | };
65 |
66 | const __react__vue__css = {
67 | "web": {
68 | "flex": 1
69 | }
70 | }
71 |
72 | const __react__vue__ComponentBuilded = __react__vue__buildNativeComponent(__react__vue__render, __react__vue__options, {
73 | Component: __react__vue__Component,
74 | PropTypes: __react__vue__PropType,
75 | Vue: __react__vue__Vue,
76 | ReactNative: __react__vue__ReactNative,
77 | css: __react__vue__css
78 | })
79 |
80 | export default __react__vue__observer(__react__vue__ComponentBuilded)
--------------------------------------------------------------------------------
/src/components/Header/Left.js:
--------------------------------------------------------------------------------
1 | import __react__vue__Vue, {
2 | observer as __react__vue__observer
3 | } from 'react-vue'
4 | import __react__vue__ReactNative from 'react-native'
5 | import __react__vue__PropType from 'prop-types'
6 | import {
7 | buildNativeComponent as __react__vue__buildNativeComponent
8 | } from 'react-vue-helper'
9 | import {
10 | bindNativeClass as __react__vue__bindClass,
11 | bindNativeStyle as __react__vue__bindStyle,
12 | mergeProps as __react__vue__mergeProps
13 | } from 'react-vue-helper'
14 | import {
15 | createElement as __react__vue__createElement,
16 | Component as __react__vue__Component
17 | } from 'react'
18 |
19 |
20 | const __react__vue__options = {
21 | props: {
22 | navigation: {
23 | type: Object
24 | }
25 | },
26 | methods: {
27 | onPress() {
28 | this.navigation.goBack();
29 | }
30 | }
31 | };
32 |
33 | const __react__vue__render = function render(vm) {
34 | return __react__vue__createElement(vm.$options.components['TouchableOpacity'], __react__vue__mergeProps.call(this, this.props.__react__vue__nativeEvents, {
35 | ref: ref => {
36 | this.setRootRef(ref);
37 | this.props['__react__vue__setRef'] && this.props['__react__vue__setRef'](ref);
38 | },
39 | onPress: vm['onPress'],
40 | activeOpacity: 1,
41 | style: [__react__vue__bindClass.call(this, {
42 | staticClass: "container",
43 | parentClass: this.props.style
44 | }), __react__vue__bindStyle(undefined, undefined, undefined)]
45 | }), __react__vue__createElement(vm.$options.components['View'], {
46 | style: [__react__vue__bindClass.call(this, {
47 | staticClass: "back"
48 | })]
49 | }));
50 | };
51 |
52 | const __react__vue__css = {
53 | "container": {
54 | "flex": 1,
55 | "justifyContent": "center",
56 | "alignItems": "center"
57 | },
58 | "back": {
59 | "width": 30,
60 | "height": 30,
61 | "borderTopWidth": 4,
62 | "borderLeftWidth": 4,
63 | "borderTopColor": "#ff6600",
64 | "borderLeftColor": "#ff6600",
65 | "marginLeft": 8,
66 | "alignSelf": "center",
67 | "transform": [{
68 | "rotate": "-45deg"
69 | }, {
70 | "scale": 0.5
71 | }]
72 | }
73 | }
74 |
75 | const __react__vue__ComponentBuilded = __react__vue__buildNativeComponent(__react__vue__render, __react__vue__options, {
76 | Component: __react__vue__Component,
77 | PropTypes: __react__vue__PropType,
78 | Vue: __react__vue__Vue,
79 | ReactNative: __react__vue__ReactNative,
80 | css: __react__vue__css
81 | })
82 |
83 | export default __react__vue__observer(__react__vue__ComponentBuilded)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hacker News
2 |
3 | A mobile app for Hacker News, powered by Vue and React Native
4 |
5 |
6 |
7 | ## Preview
8 | Use [Expo app](https://expo.io) to scan the QR code below.
9 |
10 |
11 |
12 | QR Code content: [https://expo.io/@chuangchuang/hackernews](https://expo.io/@chuangchuang/hackernews)
13 |
14 | ## Available Scripts
15 | * [npm compiler](#npm-compiler)
16 | * [npm start](#npm-start)
17 | * [npm test](#npm-test)
18 | * [npm run ios](#npm-run-ios)
19 | * [npm run android](#npm-run-android)
20 | * [npm run eject](#npm-run-eject)
21 |
22 | If Yarn was installed when the project was initialized, then dependencies will have been installed via Yarn, and you should probably use it to run these commands as well. Unlike dependency installation, command running syntax is identical for Yarn and NPM at the time of this writing.
23 |
24 | ### `npm compiler`
25 |
26 | Start a server to compile vue components into react components
27 |
28 | ### `npm start`
29 |
30 | Runs your app in development mode.
31 |
32 | Open it in the [Expo app](https://expo.io) on your phone to view it. It will reload if you save edits to your files, and you will see build errors and logs in the terminal.
33 |
34 | Sometimes you may need to reset or clear the React Native packager's cache. To do so, you can pass the `--reset-cache` flag to the start script:
35 |
36 | ```
37 | npm start -- --reset-cache
38 | # or
39 | yarn start -- --reset-cache
40 | ```
41 |
42 | #### `npm test`
43 |
44 | Runs the [jest](https://github.com/facebook/jest) test runner on your tests.
45 |
46 | #### `npm run ios`
47 |
48 | Like `npm start`, but also attempts to open your app in the iOS Simulator if you're on a Mac and have it installed.
49 |
50 | #### `npm run android`
51 |
52 | Like `npm start`, but also attempts to open your app on a connected Android device or emulator. Requires an installation of Android build tools (see [React Native docs](https://facebook.github.io/react-native/docs/getting-started.html) for detailed setup). We also recommend installing Genymotion as your Android emulator. Once you've finished setting up the native build environment, there are two options for making the right copy of `adb` available to Create React Native App:
53 |
54 | ##### Using Android Studio's `adb`
55 |
56 | 1. Make sure that you can run adb from your terminal.
57 | 2. Open Genymotion and navigate to `Settings -> ADB`. Select “Use custom Android SDK tools” and update with your [Android SDK directory](https://stackoverflow.com/questions/25176594/android-sdk-location).
58 |
59 | ##### Using Genymotion's `adb`
60 |
61 | 1. Find Genymotion’s copy of adb. On macOS for example, this is normally `/Applications/Genymotion.app/Contents/MacOS/tools/`.
62 | 2. Add the Genymotion tools directory to your path (instructions for [Mac](http://osxdaily.com/2014/08/14/add-new-path-to-path-command-line/), [Linux](http://www.computerhope.com/issues/ch001647.htm), and [Windows](https://www.howtogeek.com/118594/how-to-edit-your-system-path-for-easy-command-line-access/)).
63 | 3. Make sure that you can run adb from your terminal.
64 |
65 | #### `npm run eject`
66 |
67 | This will start the process of "ejecting" from Create React Native App's build scripts. You'll be asked a couple of questions about how you'd like to build your project.
68 |
69 | **Warning:** Running eject is a permanent action (aside from whatever version control system you use). An ejected app will require you to have an [Xcode and/or Android Studio environment](https://facebook.github.io/react-native/docs/getting-started.html) set up.
70 |
--------------------------------------------------------------------------------
/src/components/TabView/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
18 | {{item.value || item}}
19 |
20 |
21 |
22 |
23 |
28 |
29 |
30 |
31 |
32 |
33 |
112 |
113 |
140 |
--------------------------------------------------------------------------------
/src/components/Stories/index.js:
--------------------------------------------------------------------------------
1 | import __react__vue__Vue, {
2 | observer as __react__vue__observer
3 | } from 'react-vue'
4 | import __react__vue__ReactNative from 'react-native'
5 | import __react__vue__PropType from 'prop-types'
6 | import {
7 | buildNativeComponent as __react__vue__buildNativeComponent
8 | } from 'react-vue-helper'
9 | import {
10 | bindNativeClass as __react__vue__bindClass,
11 | bindNativeStyle as __react__vue__bindStyle,
12 | mergeProps as __react__vue__mergeProps
13 | } from 'react-vue-helper'
14 | import {
15 | createElement as __react__vue__createElement,
16 | Component as __react__vue__Component
17 | } from 'react'
18 |
19 | import React from 'react';
20 | import {
21 | RefreshControl
22 | } from 'react-native';
23 | import {
24 | SCREEN_WIDTH,
25 | emptyFn
26 | } from '../../util';
27 | import Story from './Story';
28 | import Footer from './Footer'
29 | const __react__vue__options = {
30 | props: {
31 | stories: {
32 | type: Array,
33 | default: []
34 | },
35 | loading: {
36 | type: Boolean,
37 | default: true
38 | },
39 | onRefresh: {
40 | type: Function,
41 | default: function() {
42 | return emptyFn;
43 | }
44 | },
45 | onEndReached: {
46 | type: Function,
47 | default: function() {
48 | return emptyFn;
49 | }
50 | },
51 | navigation: {
52 | type: Object
53 | }
54 | },
55 | computed: {
56 | data() {
57 | return this.stories.map(story => {
58 | story.key = story.id;
59 | return story;
60 | });
61 | },
62 | refreshControl() {
63 | return ;
73 | },
74 | listFooterComponent() {
75 | return Footer;
76 | },
77 | flatListStyle() {
78 | return {
79 | width: SCREEN_WIDTH
80 | };
81 | }
82 | },
83 | methods: {
84 | renderItem(props) {
85 | return ;
91 | },
92 | onPress(item) {
93 | const {
94 | navigate
95 | } = this.navigation;
96 | navigate('WebSite', {
97 | url: item.url
98 | });
99 | }
100 | }
101 | };
102 |
103 | const __react__vue__render = function render(vm) {
104 | return __react__vue__createElement(vm.$options.components['FlatList'], __react__vue__mergeProps.call(this, this.props.__react__vue__nativeEvents, {
105 | ref: ref => {
106 | this.setRootRef(ref);
107 | this.props['__react__vue__setRef'] && this.props['__react__vue__setRef'](ref);
108 | },
109 | refreshControl: vm['refreshControl'],
110 | data: vm['data'],
111 | renderItem: vm['renderItem'],
112 | onEndReached: vm['onEndReached'],
113 | ListFooterComponent: vm['listFooterComponent'],
114 | style: [__react__vue__bindClass.call(this, {
115 | parentClass: this.props.style
116 | }), __react__vue__bindStyle(vm['flatListStyle'], undefined, undefined)]
117 | }));
118 | };
119 |
120 | const __react__vue__css = {
121 | "list": {
122 | "flex": 1
123 | }
124 | }
125 |
126 | const __react__vue__ComponentBuilded = __react__vue__buildNativeComponent(__react__vue__render, __react__vue__options, {
127 | Component: __react__vue__Component,
128 | PropTypes: __react__vue__PropType,
129 | Vue: __react__vue__Vue,
130 | ReactNative: __react__vue__ReactNative,
131 | css: __react__vue__css
132 | })
133 |
134 | export default __react__vue__observer(__react__vue__ComponentBuilded)
--------------------------------------------------------------------------------
/src/components/Stories/Story.js:
--------------------------------------------------------------------------------
1 | import __react__vue__Vue, {
2 | observer as __react__vue__observer
3 | } from 'react-vue'
4 | import __react__vue__ReactNative from 'react-native'
5 | import __react__vue__PropType from 'prop-types'
6 | import {
7 | buildNativeComponent as __react__vue__buildNativeComponent
8 | } from 'react-vue-helper'
9 | import {
10 | bindNativeClass as __react__vue__bindClass,
11 | bindNativeStyle as __react__vue__bindStyle,
12 | mergeProps as __react__vue__mergeProps,
13 | _toString as __react__vue__toString
14 | } from 'react-vue-helper'
15 | import {
16 | createElement as __react__vue__createElement,
17 | Component as __react__vue__Component
18 | } from 'react'
19 |
20 | import {
21 | emptyFn
22 | } from '../../util'
23 | const __react__vue__options = {
24 | props: {
25 | item: {
26 | type: Object
27 | },
28 | onPress: {
29 | type: Function,
30 | default () {
31 | return emptyFn;
32 | }
33 | }
34 | },
35 | methods: {
36 | _onPress() {
37 | this.onPress(this.item);
38 | }
39 | }
40 | };
41 |
42 | const __react__vue__render = function render(vm) {
43 | return __react__vue__createElement(vm.$options.components['TouchableOpacity'], __react__vue__mergeProps.call(this, this.props.__react__vue__nativeEvents, {
44 | ref: ref => {
45 | this.setRootRef(ref);
46 | this.props['__react__vue__setRef'] && this.props['__react__vue__setRef'](ref);
47 | },
48 | onPress: vm['_onPress'],
49 | activeOpacity: 0.5,
50 | style: [__react__vue__bindClass.call(this, {
51 | staticClass: "container",
52 | parentClass: this.props.style
53 | }), __react__vue__bindStyle(undefined, undefined, undefined)]
54 | }), __react__vue__createElement(vm.$options.components['View'], {
55 | style: [__react__vue__bindClass.call(this, {
56 | staticClass: "score"
57 | })]
58 | }, __react__vue__createElement(vm.$options.components['Text'], {
59 | style: [__react__vue__bindClass.call(this, {
60 | staticClass: "score-text"
61 | })]
62 | }, __react__vue__toString(vm['item'].score))), __react__vue__createElement(vm.$options.components['View'], {
63 | style: [__react__vue__bindClass.call(this, {
64 | staticClass: "detail"
65 | })]
66 | }, __react__vue__createElement(vm.$options.components['Text'], {
67 | style: [__react__vue__bindClass.call(this, {
68 | staticClass: "name"
69 | })]
70 | }, __react__vue__toString(vm['item'].by)), __react__vue__createElement(vm.$options.components['Text'], {
71 | style: [__react__vue__bindClass.call(this, {
72 | staticClass: "title"
73 | })]
74 | }, __react__vue__toString(vm['item'].title))));
75 | };
76 |
77 | const __react__vue__css = {
78 | "container": {
79 | "flex": 1,
80 | "flexDirection": "row",
81 | "padding": 16
82 | },
83 | "score": {
84 | "width": 40,
85 | "height": 40,
86 | "backgroundColor": "#fff",
87 | "borderRadius": 20,
88 | "justifyContent": "center",
89 | "alignItems": "center",
90 | "marginRight": 16
91 | },
92 | "score-text": {
93 | "color": "#ff6600",
94 | "fontWeight": "bold"
95 | },
96 | "detail": {
97 | "flex": 1
98 | },
99 | "name": {
100 | "color": "#666",
101 | "fontSize": 12,
102 | "marginBottom": 6
103 | },
104 | "title": {
105 | "color": "#333",
106 | "fontSize": 14
107 | }
108 | }
109 |
110 | const __react__vue__ComponentBuilded = __react__vue__buildNativeComponent(__react__vue__render, __react__vue__options, {
111 | Component: __react__vue__Component,
112 | PropTypes: __react__vue__PropType,
113 | Vue: __react__vue__Vue,
114 | ReactNative: __react__vue__ReactNative,
115 | css: __react__vue__css
116 | })
117 |
118 | export default __react__vue__observer(__react__vue__ComponentBuilded)
--------------------------------------------------------------------------------
/src/views/Home.js:
--------------------------------------------------------------------------------
1 | import __react__vue__Vue, {
2 | observer as __react__vue__observer
3 | } from 'react-vue'
4 | import __react__vue__ReactNative from 'react-native'
5 | import __react__vue__PropType from 'prop-types'
6 | import {
7 | buildNativeComponent as __react__vue__buildNativeComponent
8 | } from 'react-vue-helper'
9 | import {
10 | bindNativeClass as __react__vue__bindClass,
11 | bindNativeStyle as __react__vue__bindStyle,
12 | mergeProps as __react__vue__mergeProps,
13 | renderList as __react__vue__renderList
14 | } from 'react-vue-helper'
15 | import {
16 | createElement as __react__vue__createElement,
17 | Component as __react__vue__Component
18 | } from 'react'
19 |
20 | import TabView from '../components/TabView';
21 | import Stories from '../components/Stories';
22 | import store from '../store'
23 | const __react__vue__options = {
24 | components: {
25 | TabView,
26 | Stories
27 | },
28 | props: {
29 | navigation: {
30 | type: Object
31 | }
32 | },
33 | data() {
34 | return {
35 | loading: {}
36 | };
37 | },
38 | computed: {
39 | items() {
40 | return store.state.items;
41 | },
42 | titles() {
43 | return Object.keys(this.items);
44 | },
45 | renderHeader() {
46 | return this.titles.map(v => {
47 | return {
48 | value: v[0].toUpperCase() + v.slice(1),
49 | type: v
50 | };
51 | });
52 | }
53 | },
54 | methods: {
55 | select(i) {
56 | const type = this.renderHeader[i].type;
57 | this.fetchList(type);
58 | },
59 | onRefresh() {
60 | this.pullFetchList(store.state.activeType);
61 | },
62 | onEndReached() {
63 | const type = store.state.activeType;
64 | if (this.items[type].length) {
65 | store.dispatch('LOAD_MORE_ITEMS');
66 | }
67 | },
68 | pullFetchList(type) {
69 | this.$set(this.loading, type, true);
70 | this.fetchList(type).then(() => {
71 | this.$set(this.loading, type, false);
72 | });
73 | },
74 | fetchList(type) {
75 | return store.dispatch('FETCH_LIST_DATA', {
76 | type: type
77 | });
78 | }
79 | },
80 | created() {
81 | this.fetchList(store.state.activeType);
82 | }
83 | };
84 |
85 | const __react__vue__render = function render(vm) {
86 | return __react__vue__createElement(vm.$options.components['TabView'], __react__vue__mergeProps.call(this, this.props.__react__vue__nativeEvents, {
87 | ref: ref => {
88 | this.setRootRef(ref);
89 | this.props['__react__vue__setRef'] && this.props['__react__vue__setRef'](ref);
90 | },
91 | renderHeader: vm['renderHeader'],
92 | onPress: vm['select'],
93 | onPageSelected: vm['select'],
94 | style: [__react__vue__bindClass.call(this, {
95 | staticClass: "container",
96 | parentClass: this.props.style
97 | }), __react__vue__bindStyle(undefined, undefined, undefined)]
98 | }), __react__vue__renderList(vm['items'], function(item, type) {
99 | return __react__vue__createElement(vm.$options.components['Stories'], {
100 | stories: item,
101 | navigation: vm['navigation'],
102 | loading: !!vm['loading'][type],
103 | onRefresh: vm['onRefresh'],
104 | onEndReached: vm['onEndReached'],
105 | key: arguments[1],
106 | style: []
107 | });
108 | }.bind(this)));
109 | };
110 |
111 | const __react__vue__css = {
112 | "container": {
113 | "backgroundColor": "#f6f6ef"
114 | }
115 | }
116 |
117 | const __react__vue__ComponentBuilded = __react__vue__buildNativeComponent(__react__vue__render, __react__vue__options, {
118 | Component: __react__vue__Component,
119 | PropTypes: __react__vue__PropType,
120 | Vue: __react__vue__Vue,
121 | ReactNative: __react__vue__ReactNative,
122 | css: __react__vue__css
123 | })
124 |
125 | export default __react__vue__observer(__react__vue__ComponentBuilded)
--------------------------------------------------------------------------------
/src/components/TabView/Scroller.js:
--------------------------------------------------------------------------------
1 | import __react__vue__Vue, {
2 | observer as __react__vue__observer
3 | } from 'react-vue'
4 | import __react__vue__ReactNative from 'react-native'
5 | import __react__vue__PropType from 'prop-types'
6 | import {
7 | buildNativeComponent as __react__vue__buildNativeComponent
8 | } from 'react-vue-helper'
9 | import {
10 | bindNativeClass as __react__vue__bindClass,
11 | bindNativeStyle as __react__vue__bindStyle,
12 | mergeProps as __react__vue__mergeProps,
13 | renderSlot as __react__vue__renderSlot
14 | } from 'react-vue-helper'
15 | import {
16 | createElement as __react__vue__createElement,
17 | Component as __react__vue__Component
18 | } from 'react'
19 |
20 | import {
21 | Platform
22 | } from 'react-native';
23 | import {
24 | emptyFn,
25 | SCREEN_WIDTH
26 | } from '../../util'
27 | const __react__vue__options = {
28 | props: {
29 | defaultIndex: {
30 | type: Number,
31 | default: 0
32 | },
33 | onScroll: {
34 | type: Function,
35 | default () {
36 | return emptyFn;
37 | }
38 | },
39 | onPageSelected: {
40 | type: Function,
41 | default () {
42 | return emptyFn;
43 | }
44 | },
45 | setRef: {
46 | type: Function,
47 | default () {
48 | return emptyFn;
49 | }
50 | }
51 | },
52 | computed: {
53 | ios() {
54 | return Platform.OS === 'ios';
55 | },
56 | android() {
57 | return Platform.OS === 'android';
58 | },
59 | contentOffset() {
60 | return {
61 | x: this.defaultIndex * SCREEN_WIDTH,
62 | y: 0
63 | };
64 | },
65 | SCREEN_WIDTH() {
66 | return SCREEN_WIDTH;
67 | }
68 | },
69 | methods: {
70 | _onScroll(v) {
71 | this.onScroll(v);
72 | },
73 | _onPageSelected(i) {
74 | this.onPageSelected(i);
75 | }
76 | },
77 | mounted() {
78 | this.setRef(this.$refs.scroller);
79 | }
80 | };
81 |
82 | const __react__vue__render = function render(vm) {
83 | const __react__vue__slotSet = __react__vue__renderSlot.call(this, [], this.props.children);
84 | return __react__vue__createElement(vm.$options.components['View'], __react__vue__mergeProps.call(this, this.props.__react__vue__nativeEvents, {
85 | ref: ref => {
86 | this.setRootRef(ref);
87 | this.props['__react__vue__setRef'] && this.props['__react__vue__setRef'](ref);
88 | },
89 | style: [__react__vue__bindClass.call(this, {
90 | staticClass: "container",
91 | parentClass: this.props.style
92 | }), __react__vue__bindStyle(undefined, undefined, undefined)]
93 | }), vm['ios'] ? __react__vue__createElement(vm.$options.components['ScrollView'], {
94 | ref: ref => {
95 | this.setRef(ref, "scroller", false);
96 | },
97 | horizontal: true,
98 | pagingEnabled: true,
99 | scrollEventThrottle: 10,
100 | showsHorizontalScrollIndicator: false,
101 | onScroll: e => vm['_onScroll'](e.nativeEvent.contentOffset.x / vm['SCREEN_WIDTH']),
102 | onMomentumScrollEnd: e => vm['_onPageSelected'](e.nativeEvent.contentOffset.x / vm['SCREEN_WIDTH']),
103 | contentOffset: vm['contentOffset'],
104 | style: []
105 | }, __react__vue__slotSet(undefined, {})) : vm['android'] ? __react__vue__createElement(vm.$options.components['ViewPagerAndroid'], {
106 | ref: ref => {
107 | this.setRef(ref, "scroller", false);
108 | },
109 | initialPage: vm['defaultIndex'],
110 | keyBoardDismissMode: "on-drag",
111 | onPageScroll: e => vm['_onScroll'](e.nativeEvent.position + e.nativeEvent.offset),
112 | onPageSelected: e => vm['_onPageSelected'](e.nativeEvent.position),
113 | style: [__react__vue__bindClass.call(this, {
114 | staticClass: "container"
115 | })]
116 | }, __react__vue__slotSet(undefined, {})) : null);
117 | };
118 |
119 | const __react__vue__css = {
120 | "container": {
121 | "flex": 1
122 | }
123 | }
124 |
125 | const __react__vue__ComponentBuilded = __react__vue__buildNativeComponent(__react__vue__render, __react__vue__options, {
126 | Component: __react__vue__Component,
127 | PropTypes: __react__vue__PropType,
128 | Vue: __react__vue__Vue,
129 | ReactNative: __react__vue__ReactNative,
130 | css: __react__vue__css
131 | })
132 |
133 | export default __react__vue__observer(__react__vue__ComponentBuilded)
--------------------------------------------------------------------------------
/src/components/TabView/index.js:
--------------------------------------------------------------------------------
1 | import __react__vue__Vue, {
2 | observer as __react__vue__observer
3 | } from 'react-vue'
4 | import __react__vue__ReactNative from 'react-native'
5 | import __react__vue__PropType from 'prop-types'
6 | import {
7 | buildNativeComponent as __react__vue__buildNativeComponent
8 | } from 'react-vue-helper'
9 | import {
10 | bindNativeClass as __react__vue__bindClass,
11 | bindNativeStyle as __react__vue__bindStyle,
12 | mergeProps as __react__vue__mergeProps,
13 | renderList as __react__vue__renderList,
14 | _toString as __react__vue__toString,
15 | renderSlot as __react__vue__renderSlot
16 | } from 'react-vue-helper'
17 | import {
18 | createElement as __react__vue__createElement,
19 | Component as __react__vue__Component
20 | } from 'react'
21 |
22 | import {
23 | Animated,
24 | Platform
25 | } from 'react-native';
26 | import Scroller from './Scroller';
27 | import {
28 | emptyFn,
29 | SCREEN_WIDTH
30 | } from '../../util'
31 | const __react__vue__options = {
32 | components: {
33 | Scroller
34 | },
35 | props: {
36 | renderHeader: {
37 | type: Array
38 | },
39 | renderScene: {
40 | type: Array
41 | },
42 | defaultIndex: {
43 | type: Number,
44 | default: 0
45 | },
46 | onPress: {
47 | type: Function,
48 | default: function() {
49 | return emptyFn;
50 | }
51 | },
52 | onPageSelected: {
53 | type: Function,
54 | default: function() {
55 | return emptyFn;
56 | }
57 | }
58 | },
59 | computed: {
60 | scenes() {
61 | return this.renderScene || this.$slots.default.map(v => () => v);
62 | },
63 | underlineStyle() {
64 | const width = SCREEN_WIDTH / (this.renderHeader.length || 1);
65 | return {
66 | width: width,
67 | transform: [{
68 | translateX: this.animateValue.interpolate({
69 | inputRange: [0, 1],
70 | outputRange: [0, width]
71 | })
72 | }]
73 | };
74 | },
75 | scrollerWidth() {
76 | return SCREEN_WIDTH * this.renderHeader.length;
77 | }
78 | },
79 | methods: {
80 | _onPress(v, i) {
81 | if (Platform.OS === 'ios') {
82 | this.scrollerRef.scrollTo({
83 | x: i * SCREEN_WIDTH,
84 | y: 0,
85 | animated: true
86 | });
87 | } else {
88 | this.scrollerRef.setPage(i);
89 | }
90 | this.onPress(i, v);
91 | },
92 | _onScroll(v) {
93 | this.animateValue.setValue(v);
94 | },
95 | _onPageSelected(i) {
96 | this.onPageSelected(i);
97 | },
98 | setRef(ref) {
99 | this.scrollerRef = ref;
100 | }
101 | },
102 | created() {
103 | this.animateValue = new Animated.Value(this.defaultIndex);
104 | }
105 | };
106 |
107 | const __react__vue__render = function render(vm) {
108 | const __react__vue__slotSet = __react__vue__renderSlot.call(this, [], this.props.children);
109 | return __react__vue__createElement(vm.$options.components['View'], __react__vue__mergeProps.call(this, this.props.__react__vue__nativeEvents, {
110 | ref: ref => {
111 | this.setRootRef(ref);
112 | this.props['__react__vue__setRef'] && this.props['__react__vue__setRef'](ref);
113 | },
114 | style: [__react__vue__bindClass.call(this, {
115 | staticClass: "container",
116 | parentClass: this.props.style
117 | }), __react__vue__bindStyle(undefined, undefined, undefined)]
118 | }), __react__vue__createElement(vm.$options.components['View'], {
119 | style: [__react__vue__bindClass.call(this, {
120 | staticClass: "bar"
121 | })]
122 | }, __react__vue__renderList(vm['renderHeader'], function(item, index) {
123 | return __react__vue__createElement(vm.$options.components['TouchableOpacity'], {
124 | activeOpacity: 1,
125 | onPress: () => vm['_onPress'](item, index),
126 | key: arguments[1],
127 | style: [__react__vue__bindClass.call(this, {
128 | staticClass: "item"
129 | })]
130 | }, __react__vue__createElement(vm.$options.components['Animated']['Text'], {
131 | style: [__react__vue__bindClass.call(this, {
132 | staticClass: "item-text"
133 | }), __react__vue__bindStyle({
134 | color: vm['animateValue'].interpolate({
135 | inputRange: [index - 1, index, index + 1],
136 | outputRange: ['#000', '#ff6600', '#000'],
137 | extrapolate: 'clamp'
138 | })
139 | }, undefined, undefined)]
140 | }, "" + __react__vue__toString(item.value || item) + ""));
141 | }.bind(this)), __react__vue__createElement(vm.$options.components['Animated']['View'], {
142 | style: [__react__vue__bindClass.call(this, {
143 | staticClass: "underline"
144 | }), __react__vue__bindStyle(vm['underlineStyle'], undefined, undefined)]
145 | })), __react__vue__createElement(vm.$options.components['Scroller'], {
146 | defaultIndex: vm['defaultIndex'],
147 | setRef: vm['setRef'],
148 | onScroll: vm['_onScroll'],
149 | onPageSelected: vm['_onPageSelected'],
150 | style: []
151 | }, __react__vue__slotSet(undefined, {})));
152 | };
153 |
154 | const __react__vue__css = {
155 | "container": {
156 | "flex": 1
157 | },
158 | "bar": {
159 | "position": "relative",
160 | "flexDirection": "row",
161 | "backgroundColor": "#fff",
162 | "borderBottomColor": "#d9d9d9",
163 | "height": 44
164 | },
165 | "underline": {
166 | "position": "absolute",
167 | "left": 0,
168 | "bottom": 0,
169 | "height": 2,
170 | "backgroundColor": "#ff6600"
171 | },
172 | "item": {
173 | "flex": 1,
174 | "justifyContent": "center",
175 | "alignItems": "center"
176 | },
177 | "item-text": {
178 | "fontSize": 14
179 | }
180 | }
181 |
182 | const __react__vue__ComponentBuilded = __react__vue__buildNativeComponent(__react__vue__render, __react__vue__options, {
183 | Component: __react__vue__Component,
184 | PropTypes: __react__vue__PropType,
185 | Vue: __react__vue__Vue,
186 | ReactNative: __react__vue__ReactNative,
187 | css: __react__vue__css
188 | })
189 |
190 | export default __react__vue__observer(__react__vue__ComponentBuilded)
--------------------------------------------------------------------------------