马鞍山培训机构Web前端培训机构哪家好

App Links 并不是用来取代 URL Scheme 的,所以也谈不上「有何本质不同」。它并不是某一种技术,而是一项协议(或者像他们说的,一种「解决方案」)。&br&&br&我们想像一下这样一个常见的场景:A 在大众点评上看到了一家餐厅并想通过微信把这家餐厅分享给 B——此时问题出现了——B 会如何处理这个链接是未知的。如果 A 和 B 都是同一平台的用户还好,当时直接传一个类似于 dianping://shop/12345 的 URL 对方在微信中点了就能在 app 里打开了(先不考虑微信是否接受这样的 URL)。可是如果大众点评某天升级了把 URL scheme 改成 dianping_v2://shop/12345 呢?如果 A 和 B 是两个不同平台的用户呢?如果 B 的手机上根本就没有装大众点评呢?&br&&br&这个事情,大众点评即使想做也是有心无力——链接一旦分享出去控制权就不在自己手里了。好吧,我们还是可以做一个网页版的嘛,弄一个 &a href=&///?target=http%3A///shop/4551072& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&/shop/455&/span&&span class=&invisible&&1072&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a& 这样的链接,不管对方是什么环境,至少可以在微信的 in-app 浏览器里打开嘛。牺牲部分体验来换取最大的可用性——而且还是有活路的,可以在网页加载好后用 JavaScript 做一点 window.location.href = 'dianping://shop/12345' 这样的小动作嘛——直到有一天微信关掉了 URL Scheme 跳转……&br&&br&于是这个事情就变得很荒唐。明明对方的手机里有装大众点评的 app,大众点评也支持 URL Scheme,可在微信上点开大众点评的链接就是只能看到 web 版。理论上来说作为平台的微信应该出来挑大梁,不过可能微信忙着征服全世界顾不上这点小事——于是另一个闲得没事干的平台 Facebook(好吧,准确地说是 Facebook 去年买进来的 Parse 团队)跳出来解决了问题。&br&&br&怎么解决?说难也不难,无外乎就是把自己在几个平台下的跳转规则一并告诉对方。对方是什么平台就按什么平台的规则去处理。如果对方没装我们的 app,那我就告诉他一个安装地址。如果他的平台确实没有我们的 app(并没有想黑 WP 的意思……),那么就给他看一个网页版好了。但是这些规则写在哪呢?用 &meta& 标签放在网页里就好了嘛!于是一个实现了 App Links 的网页大致长成这样:&br&&br&&div class=&highlight&&&pre&&code class=&language-html&&&span class=&nt&&&html&&/span&
&span class=&nt&&&head&&/span&
&span class=&nt&&&meta&/span& &span class=&na&&property=&/span&&span class=&s&&&al:ios:url&&/span& &span class=&na&&content=&/span&&span class=&s&&&applinks://docs&&/span& &span class=&nt&&/&&/span&
&span class=&nt&&&meta&/span& &span class=&na&&property=&/span&&span class=&s&&&al:ios:app_store_id&&/span& &span class=&na&&content=&/span&&span class=&s&&&12345&&/span& &span class=&nt&&/&&/span&
&span class=&nt&&&meta&/span& &span class=&na&&property=&/span&&span class=&s&&&al:ios:app_name&&/span& &span class=&na&&content=&/span&&span class=&s&&&App Links&&/span& &span class=&nt&&/&&/span&
&span class=&nt&&&meta&/span& &span class=&na&&property=&/span&&span class=&s&&&al:android:url&&/span& &span class=&na&&content=&/span&&span class=&s&&&applinks://docs&&/span& &span class=&nt&&/&&/span&
&span class=&nt&&&meta&/span& &span class=&na&&property=&/span&&span class=&s&&&al:android:app_name&&/span& &span class=&na&&content=&/span&&span class=&s&&&App Links&&/span& &span class=&nt&&/&&/span&
&span class=&nt&&&meta&/span& &span class=&na&&property=&/span&&span class=&s&&&al:android:package&&/span& &span class=&na&&content=&/span&&span class=&s&&&org.applinks&&/span& &span class=&nt&&/&&/span&
&span class=&nt&&&meta&/span& &span class=&na&&property=&/span&&span class=&s&&&al:web:url&&/span&
&span class=&na&&content=&/span&&span class=&s&&&http://applinks.org/documentation&&/span& &span class=&nt&&/&&/span&
&span class=&nt&&&/head&&/span&
&span class=&nt&&&body&&/span&
Hello, world!
&span class=&nt&&&/body&&/span&
&span class=&nt&&&/html&&/span&
&/code&&/pre&&/div&&br&大众点评网的程序员们看到之后如获至宝,嗨嗨皮皮(不要质疑我的成语能力!)地把这些 meta tags 都塞进了 &a href=&///?target=http%3A///shop/4551072& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&/shop/455&/span&&span class=&invisible&&1072&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&。Parse 说我都给你们写好各个平台下的 SDK 了,解析跳转一条龙哦你们赶紧用。腾讯(过了一年后)说,App Links 是什么?&br&&br&App Links 还制定了一些别的标准,比如可以多次指定同一项值来完成 fallback(用于新老版本 URL Scheme 不兼容的情况),比如实现了跳转时的数据传输标准(用 JSON 描述,放在 al_applink_data 参数中),比如提供了跳转后 app 的 UX 建议(导航栏用一层蓝色的可点按区域覆盖,点按后返回原 app)。App Links 不是唯一解,也不一定是最优解,但它确实是解决当下 app 间跳转混乱局面的一个可行解(而且标准本身具有可扩展性,即使 iOS 8 里加入类似 Android 中的 Intent,App Links 也可以通过增加几个 meta tags 来支持)。回到最初的问题上,它解决的问题,其实就是 Ilya Sukhar (Parse CEO) 在 F8 上说的这句话:「There is no unified way to navigate to links across all the platforms.」在技术层面上,App Links 统一了流程、跨了平台,这就很好了。&br&&br&而剩下的问题其实才是最大的问题——有人用的标准才是好标准。这个用也分两种角色:类似大众点评这样的第三方开发者,他们只需要发布自己的 App Links 就可以了,这个事情很简单,如上面所说无非就是在现成的网页里加几个 meta tags 的事情。而类似微信这样的平台则需要实现这样的协议,理论上也不难,但也许除了优化用户体验之外好处有限,可能还会面临到如何去兼容老版本啦、跳转出去会不会降低用户黏性啦、怎么满足平台的统计需求啦之类的问题(随口一说,也许没那么多问题。)老外比较单纯,想想这对用户来说是件好事我们就做吧,于是至少 Parse 有他的亲爹 Facebook 给他撑腰。至于国内,需要有第一个吃螃蟹的人。
App Links 并不是用来取代 URL Scheme 的,所以也谈不上「有何本质不同」。它并不是某一种技术,而是一项协议(或者像他们说的,一种「解决方案」)。 我们想像一下这样一个常见的场景:A 在大众点评上看到了一家餐厅并想通过微信把这家餐厅分享给 B——此…
已有帐号?
无法登录?
社交帐号登录
117 条内容
162 人关注
1512 条内容
1425 人关注
107 条内容
1265 人关注
701 人关注
610 条内容你正在使用的浏览器版本过低,将不能正常浏览和使用知乎。Facebook推App Link:解决应用内容互通问题
招聘信息:
今天,在F8开发者大会上,发布了一款全新开发者产品。借助该产品,应用开发者便可以轻松将应用程序之间的内容连接在一起。
换句话来说,在大部分情况下,即便应用程序体验非常出色,但应用内链接却总是将用户引领至一个移动版缩小网页。也就是说,如果有人向你发送了一个Spotify播放列表的链接,相较于网页版,直接通过链接打开Spotify应用程序播放,岂不是更好?
Facebook的App Link就能够让开发人员在自己的应用中实现这样的操作。简单讲,开发者将能够轻易地让应用程序之间彼此对话,如此一来,用户就不必再为了打开应用中的另一个程序的相关内容,而在应用程序之间来回的进行切换。
Facebook该产品的推出可谓是一个重大举措,修复了许多移动设备所存在的问题,对iPhone和iPad产品更是如此。不允许用户选择地图和网页浏览等默认应用,用户必须使用苹果的默认应用。而Facebook的App Link产品让应用开发人员(和用户)能够在自己想使用的应用之间快速跳转。
不仅如此,App Link还兼容iOS、Android和WP等所有主流移动平台。所以,无论用户使用何种设备,都不会遇到问题。在某种程度上来看,Facebook是在利用App Links,来制霸智能手机和平板电脑平台中应用的互相通信模式。苹果、()和都没有为开发人员提供简化方法,所以,Facebook出手了。
其实,该产品最终还是更有益于用户。目前,在应用和应用内容的彼此互通模式方面,Facebook拥有主权,而用户则将获得一个更加丰富和流畅的手机体验。
App Link的推出,奏响了最近不少移动业界领军人物一直在谈论的一个主题,即,人们使用应用程序的频率要高于移动页面,但到目前为止,还没有人找到法子成为&移动应用领域的谷歌&。
没错,还没有人找到一个不错的办法,让手机应用能够彼此互通,并帮助用户管理应用之间的内容。但Facebook似乎已经通过App Link找到了解决方法,而这或将对未来产生重大影响。
移动应用是计算机的未来,而App Link将赋予Facebook控制权,即便用户没有直接绑定Facebook,其也能够轻易掌握用户的智能手机使用方式。说白了就是,Facebook找到了控制用户手机的方法。
Facebook在F8大会上表示,App Link已有不少合作伙伴,其中包括社交博客平台Tumblr、社交图片分享应用Pinterest以及热门邮件应用Mailbox等。另外,App Link向所有应用开发人员开放,估计未来将会有很多兼容应用和网页出现。
CocoaChina是全球最大的苹果开发中文社区,官方微信每日定时推送各种精彩的研发教程资源和工具,介绍app推广营销经验,最新企业招聘和外包信息,以及Cocos2d引擎、Cocostudio开发工具包的最新动态及培训信息。关注微信可以第一时间了解最新产品和服务动态,微信在手,天下我有!
请搜索微信号&CocoaChina&关注我们!
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
您还没有登录!请或
点击量11866点击量6088点击量4532点击量3786点击量3184点击量2971点击量2930点击量2769点击量2364
&2016 Chukong Technologies,Inc.
京公网安备89Facebook F8App-ReactNative项目源码分析4-js篇 - 简书
Facebook F8App-ReactNative项目源码分析4-js篇
本文开始分析f8app核心js部分的源码,这篇文章将非常难理解,原因了Redux框架引入了很多新概念,使用了大量函数式编程思想,建议先把后面的参考文章仔细过一遍,确保理解后再看本文。React Native的理念是Learn once,write anywhere, Android和iOS App端的js代码是放在一起的,以便最大限度的复用业务逻辑,UI部分的可以根据平台特性各自实现,React native分别渲染成安卓和iOS的原生UI界面,对于两个平台UI组件的细微差异和完全不同的UI组件2种情况,react native提供了不同的处理方式。&!-- more --&
js入口分析
React Native Android App和iOS App的入口jsbundle对应的默认js源文件分别是index.android.js和index.ios.js,在f8app中这2个文件内容一致。代码如下:
'use strict';
const {AppRegistry} = require('react-native');
const setup = require('./js/setup');
AppRegistry.registerComponent('F8v2', setup);
React Native采用了组件化编程的思想,在React Native项目中,所有展示的界面,都可以看做是一个组件(Component)。index.android.js利用Node.js的require机制引入setup包,然后注册到AppRegistry.
js目录结构分析
首先还是先看下js目录的结构:
├── F8App.js
├── F8Navigator.js
├── FacebookSDK.js
├── Playground.js
├── PushNotificationsController.js
├── actions
├── config.js
├── filter.js
├── index.js
├── installation.js
├── login.js
├── navigation.js
├── notifications.js
├── parse.js
├── schedule.js
├── surveys.js
├── test.js
└── types.js
├── common
├── BackButtonIcon.js
├── Carousel.js
├── F8Button.js
├── F8Colors.js
├── F8DrawerLayout.js
├── F8Header.js
├── F8PageControl.js
├── F8SegmentedControl.js
├── F8StyleSheet.js
├── F8Text.js
├── F8Touchable.js
├── ItemsWithSeparator.js
├── ListContainer.js
├── LoginButton.js
├── MapView.js
├── ParallaxBackground.js
├── ProfilePicture.js
├── PureListView.js
├── ViewPager.js
└── img
├── env.js
├── filter
├── FilterScreen.js
├── FriendsList.js
├── Header.js
├── Section.js
└── TopicItem.js
├── flow-lib.js
├── login
├── LoginModal.js
├── LoginScreen.js
└── img
├── rating
├── Header.js
├── RatingCard.js
├── RatingQuestion.js
├── RatingScreen.js
└── img
├── reducers
├── __mocks__
└── parse.js
├── __tests__
├── maps-test.js
├── notifications-test.js
└── schedule-test.js
├── config.js
├── createParseReducer.js
├── filter.js
├── friendsSchedules.js
├── index.js
├── maps.js
├── navigation.js
├── notifications.js
├── schedule.js
├── sessions.js
├── surveys.js
├── topics.js
└── user.js
├── setup.js
├── store
├── analytics.js
├── array.js
├── configureStore.js
├── promise.js
└── track.js
└── tabs
├── F8TabsView.android.js
├── F8TabsView.ios.js
├── MenuItem.js
├── img
├── info
├── CommonQuestions.js
├── F8InfoView.js
├── LinksList.js
├── Section.js
├── ThirdPartyNotices.js
├── WiFiDetails.js
└── img
├── maps
├── F8MapView.js
├── ZoomableImage.js
└── img
├── notifications
├── F8NotificationsView.js
├── NotificationCell.js
├── PushNUXModal.js
├── RateSessionsCell.js
├── allNotifications.js
├── findSessionByURI.js
├── img
└── unseenNotificationsCount.js
└── schedule
├── AddToScheduleButton.js
├── EmptySchedule.js
├── F8FriendGoing.js
├── F8SessionCell.js
├── F8SessionDetails.js
├── F8SpeakerProfile.js
├── FilterHeader.js
├── FriendCell.js
├── FriendsListView.js
├── FriendsScheduleView.js
├── FriendsUsingApp.js
├── GeneralScheduleView.js
├── InviteFriendsButton.js
├── MyScheduleView.js
├── ProfileButton.js
├── ScheduleListView.js
├── SessionsCarousel.js
├── SessionsSectionHeader.js
├── SharingSettingsCommon.js
├── SharingSettingsModal.js
├── SharingSettingsScreen.js
├── __tests__
├── formatDuration-test.js
└── formatTime-test.js
├── filterSessions.js
├── formatDuration.js
├── formatTime.js
├── groupSessions.js
└── img
js部分的代码理解起来还是比较困难的,首先要熟悉javascript ES6,React Native和Redux的常见语法,还需要弄明白redux-react,redux-promise,redux-thunk等插件的作用和原理,否则直接看代码会很困难,主要涉及的新概念比较多,语法比较奇怪。
Redux - 架构上深受 flux 启发,实现上却更接近于 elm,或者说更倾向于函数式编程的一个数据层实现。和 flux 架构对数据层的描述最大的区别就在于 Redux 是采用不可变单一状态树来管理应用程序数据的。用 redux 充当数据层也可以完全兼容 flux 架构(但没好处)并且 redux 对视图层也没有倾向性,只是目前用的比较多的还是 react。redux使用了很多函数式编程的概念,例如柯里化等的。
actions目录下的js实现了业务层的逻辑。
common目录下是抽取的一些UI组件,react是基于组件化编程的。
filter目录下是一些UI组件页面,暂时没有想明白为什么叫filter
login目录下是登录页面,提供了通过Facebook帐号登录F8app的功能
rating目录下是投票和问卷相关的页面
reduces目录是redux Reducer相关的文件。Redux有且只有一个State状态树,为了避免这个状态树变得越来越复杂,Redux通过 Reducers来负责管理整个应用的State树,而Reducers可以被分成一个个Reducer。
store目录下是redux store相关的文件
tabs目录下是App 4个tab页面的源文件整个目录结构划分还是比较合理的。
下面是知乎上对Redux的一个比较好的解释,弄明白了Redux我们才有能力分析f8app js的代码。
理解 React,但不理解 Redux,该如何通俗易懂的理解 Redux?解答这个问题并不困难:唯一的要求是你熟悉React。不要光听别人描述名词,理解起来是很困难的。从需求出发,看看使用React需要什么:
React有props和state: props意味着父级分发下来的属性,state意味着组件内部可以自行管理的状态,并且整个React没有数据向上回溯的能力,也就是说数据只能单向向下分发,或者自行内部消化。理解这个是理解React和Redux的前提。
一般构建的React组件内部可能是一个完整的应用,它自己工作良好,你可以通过属性作为API控制它。但是更多的时候发现React根本无法让两个组件互相交流,使用对方的数据。然后这时候不通过DOM沟通(也就是React体制内)解决的唯一办法就是提升state,将state放到共有的父组件中来管理,再作为props分发回子组件。
子组件改变父组件state的办法只能是通过onClick触发父组件声明好的回调,也就是父组件提前声明好函数或方法作为契约描述自己的state将如何变化,再将它同样作为属性交给子组件使用。这样就出现了一个模式:数据总是单向从顶层向下分发的,但是只有子组件回调在概念上可以回到state顶层影响数据。这样state一定程度上是响应式的。
为了面临所有可能的扩展问题,最容易想到的办法就是把所有state集中放到所有组件顶层,然后分发给所有组件。
为了有更好的state管理,就需要一个库来作为更专业的顶层state分发给所有React应用,这就是Redux。让我们回来看看重现上面结构的需求:a. 需要回调通知state (等同于回调参数) -& actionb. 需要根据回调处理 (等同于父级方法) -& reducerc. 需要state (等同于总状态) -& store对Redux来说只有这三个要素:a. action是纯声明式的数据结构,只提供事件的所有要素,不提供逻辑。b. reducer是一个匹配函数,action的发送是全局的:所有的reducer都可以捕捉到并匹配与自己相关与否,相关就拿走action中的要素进行逻辑处理,修改store中的状态,不相关就不对state做处理原样返回。c. store负责存储状态并可以被react api回调,发布action.当然一般不会直接把两个库拿来用,还有一个binding叫react-redux, 提供一个Provider和connect。很多人其实看懂了redux卡在这里。a. Provider是一个普通组件,可以作为顶层app的分发点,它只需要store属性就可以了。它会将state分发给所有被connect的组件,不管它在哪里,被嵌套多少层。b. connect是真正的重点,它是一个科里化函数,意思是先接受两个参数(数据绑定mapStateToProps和事件绑定mapDispatchToProps),再接受一个参数(将要绑定的组件本身):mapStateToProps:构建好Redux系统的时候,它会被自动初始化,但是你的React组件并不知道它的存在,因此你需要分拣出你需要的Redux状态,所以你需要绑定一个函数,它的参数是state,简单返回你关心的几个值。mapDispatchToProps:声明好的action作为回调,也可以被注入到组件里,就是通过这个函数,它的参数是dispatch,通过redux的辅助方法bindActionCreator绑定所有action以及参数的dispatch,就可以作为属性在组件里面作为函数简单使用了,不需要手动dispatch。这个mapDispatchToProps是可选的,如果不传这个参数redux会简单把dispatch作为属性注入给组件,可以手动当做store.dispatch使用。这也是为什么要科里化的原因。做好以上流程Redux和React就可以工作了。简单地说就是:1.顶层分发状态,让React组件被动地渲染。2.监听事件,事件有权利回到所有状态顶层影响状态。
和 Flux 一样,Redux 让应用的状态变化变得更加可预测。如果你想改变应用的状态,就必须 dispatch 一个 action。你没有办法直接改变应用的状态,因为保存这些状态的东西(称为 store)只有 getter 而没有 setter。对于 Flux 和 Redux 来说,这些概念都是相似的。
那么为什么要新设计一种架构呢?Redux 的创造者 Dan Abramov 发现了改进 Flux 架构的可能。他想要一个更好的开发者工具来调试 Flux 应用。他发现如果稍微对 Flux 架构进行一些调整,就可以开发出一款更好用的开发者工具,同时依然能享受 Flux 架构带给你的可预测性。
Redux包含了代码热替换(hot reload)和时间旅行(time travel)功能。
智能组件(smart components)和木偶组件(dumb components)
Flux 拥有控制型视图(controller views) 和常规型视图(regular views)。控制型视图就像是一个经理一样,管理着 store 和子视图(child views)之间的通信。
在 Redux 中,也有一个类似的概念:智能组件和木偶组件。(注:在最新的 Redux 文档中,它们分别叫做容器型组件 Container component 和展示型组件 Presentational component)智能组件的职责就像经理一样,但是比起 Flux 中的角色,Redux 对经理的职责有了更多的定义:
智能组件负责所有的 action 相关的工作。如果智能组件里包含的一个木偶组件需要触发一个 action,智能组件会通过 props 传一个 function 给木偶组件,而木偶组件可以在需要触发 action 时调用这个 function。
智能组件不定义 CSS 样式。
智能组件几乎不会产生自己的 DOM 节点,他的工作是组织若干的木偶组件,由木偶组件来生成最终的 DOM 节点。
redux-thunk 介绍
先贴官网链接:Thunk的做法就是扩展了这个action creator。Redux官网说,action就是Plain JavaScript Object。Thunk允许action creator返回一个函数,而且这个函数第一个参数是dispatch。A
is a function that wraps an expression to delay its evaluation.
// calculation of 1 + 2 is immediate
// x === 3
let x = 1 + 2;
// calculation of 1 + 2 is delayed
// foo can be called later to perform the calculation
// foo is a thunk!
let foo = () =& 1 + 2;
setup.js代码分析
熟悉React Native都知道,index.android.js和index.ios.js分别是Android和iOS App的js程序入口,当然实际运行是压缩处理后的jsbundle。这个2个文件都是注册了setup组件,AppRegistry.registerComponent('F8v2', setup);。setup.js负责配置其它的组件,具体代码如下:
//js/setup.js
var F8App = require('F8App');
var FacebookSDK = require('FacebookSDK');
var Parse = require('parse/react-native');
var React = require('React');
var Relay = require('react-relay');
var { Provider } = require('react-redux');
var configureStore = require('./store/configureStore');
var {serverURL} = require('./env');
function setup(): ponent {
console.disableYellowBox =
Parse.initialize('oss-f8-app-2016');
Parse.serverURL = `${serverURL}/parse`;
FacebookSDK.init();
Parse.FacebookUtils.init();
Relay.injectNetworkLayer(
new Relay.DefaultNetworkLayer(`${serverURL}/graphql`, {
fetchTimeout: 30000,
retryDelays: [],
class Root ponent {
constructor() {
this.state = {
isLoading: true,
store: configureStore(() =& this.setState({isLoading: false})),
render() {
if (this.state.isLoading) {
&Provider store={this.state.store}&
&/Provider&
global.LOG = (...args) =& {
console.log('/------------------------------\\');
console.log(...args);
console.log('\\------------------------------/');
return args[args.length - 1];
module.exports =
setup.js负责对整个app进行配置,首先配置了Parse,FacebookSDK和Relay,这3个组件是服务器端相关的。然后通过react-redux配置了Provider组件,这个组件包裹在整个组件树的最外层。这个组件让根组件的所有子孙组件能够轻松的使用 connect() 方法绑定 store。Provider 本质上创建了一个用于更新视图组件的网络。那些智能组件通过 connect() 方法连入这个网络,以此确保他们能够获取到状态的更新。configureStore提供了对Store的创建和配置,由于Redux只有一个store,如果让store 完全独立处理自己的事,store会变的很复杂。因此,Redux 中的 store 首先会保存整个应用的所有状态,然后将「判断哪一部分状态需要改变」的任务分配下去。而以根 reducer(root reducer)为首的 reducer 们将会承担这个任务。
// ./js/store/configureStore.js
'use strict';
var {applyMiddleware, createStore} = require('redux');
var thunk = require('redux-thunk');
var promise = require('./promise');
var array = require('./array');
var analytics = require('./analytics');
var reducers = require('../reducers');
var createLogger = require('redux-logger');
var {persistStore, autoRehydrate} = require('redux-persist');
var {AsyncStorage} = require('react-native');
var isDebuggingInChrome = __DEV__ && !!window.navigator.userA
var logger = createLogger({
predicate: (getState, action) =& isDebuggingInChrome,
collapsed: true,
duration: true,
var createF8Store = applyMiddleware(thunk, promise, array, analytics, logger)(createStore);
function configureStore(onComplete: ?() =& void) {
// TODO(frantic): reconsider usage of redux-persist, maybe add cache breaker
const store = autoRehydrate()(createF8Store)(reducers);
persistStore(store, {storage: AsyncStorage}, onComplete);
if (isDebuggingInChrome) {
window.store =
module.exports = configureS
createF8Store使用了柯里化方法调用了applyMiddleware,我们可以简单的理解成过滤器,作用就是加入一些中间处理过程。最后返回store对象。
用户登录流程代码分析
下面分析登录页面的代码,代码在login目录下,包括LoginModal.js和LoginScreen.js,实现了通过Oauth登录Facebook帐号的功能。登录涉及的代码有actions/types.js(定义了所有的Action事件), actions/login.js(实现登录业务逻辑,与服务器交互),js/reducers/user.js(实现对用户相关状态的计算)。登录的入口是js/tabs/schedule/logIn.js,142行定义了&LoginButton source="My F8" /& ,LoginButton组件封装了登录UI相关的逻辑。点击LoginButton后会调用logIn函数,logIn函数会调用logInWithFacebook进行OAuth登录或在等待15s后超时返回,下面是logIn的代码:
async logIn() {
const {dispatch, onLoggedIn} = this.
this.setState({isLoading: true});
await Promise.race([
dispatch(logInWithFacebook(this.props.source)),
timeout(15000),
} catch (e) {
const message = e.message ||
if (message !== 'Timed out' && message !== 'Canceled by user') {
alert(message);
console.warn(e);
} finally {
this._isMounted && this.setState({isLoading: false});
onLoggedIn && onLoggedIn();
用到了async,Promise.race等ES6的语法。logInWithFacebook的实现在js/actions/login.js中,如果登录成功会通过Promise异步获取好友的日程和调查问卷。
function logInWithFacebook(source: ?string): ThunkAction {
return (dispatch) =& {
const login = _logInWithFacebook(source);
// Loading friends schedules shouldn't block the login process
login.then(
(result) =& {
dispatch(result);
dispatch(loadFriendsSchedules());
dispatch(loadSurveys());
登录是调用Facebook SDK进行登录,logInWithFacebook是个异步方法,用到了ES6的async,async function _logInWithFacebook(source: ?string): Promise&Array&Action&& {...},返回值是个Promise,在then方面里面异步调用loadFriendsSchedules,loadSurveys。这些方法会继续请求数据,并更新store,从而让页面更新。
js部分的代码用了很多ES6的新语法和函数式编程思想,特别是使用了Redux框架,代码量也比较大,分析和理解起来比较困难,本文只分析了部分典型模块的代码。特别是在相关的技术和框架了解程度不够深入,缺少实际开发经验的情况下(这说的就是我自己啊)。建议看代码之前先把JavaScript ES6和Redux框架好好学习一下。虽然代码看上去很难,但整个处理流程和模块划分还是很清晰的。
全栈工程师,移动端架构师,极客
CSDN认证专家,做过多次技术演讲
专注新技术 不写鸡汤文 不做标题党

我要回帖

更多关于 马鞍山培训机构 的文章

 

随机推荐