Coder Social home page Coder Social logo

app's Introduction

Project App

  • outline

outline

core: 如何设计一个React Native路由

#0 what's your problem ?

厚葬友军

站在巨人的肩膀上

  • 小程序

    • Page
    • Component
  • vue-router

    • beforeHooks
  • 弹出层的一些想法

  • 预期能力

    • core
      • 生命周期
      • 钩子
      • 静态路由表与动态路由 <动态页面预警>
      • 页面传参
      • URLSchema 解析
    • feeling
      • 动画
      • 返回键/手势
    • devloper
      • redux free
      • event
      • debug
      • Exception

#1 生命周期与钩子

AOP yes!

  • onShow

    • history.push // 路由入栈新页面, 触发栈顶页面 onShow
    • onAppActive // App 返回前台, 触发栈顶页面 onShow
  • onHide

    • history.pop // 栈顶出栈, 触发栈顶 onHide
    • hisotry.push // 栈顶有新页面入栈, 触发原栈顶页面 onHide
    • onAppDeActive // App 进入后台, 触发栈顶页面 onHide
  • Thinking: 组件如何使用所在页面的钩子?

  • beforeEnter 入场钩子

  • beforeLeave 离场钩子

#2 数据结构与Api的初步设计

这个需求很简单, 怎么实现我不管

  • 数据结构

    • history: Route[]
    • route: Nav[]
    • nav: Page | Layer
  • hooks 全局钩子

    • onShow: (page: Page) => void
    • onHide: (page: Page) => void
    • beforeEnter: (page: Page) => Promise
    • beforeLeave: (page: Page) => Promise
  • actions

    • push: () => void
    • pop: () => void
    • replace: () => void
    • go: () => void
      • history.has ? pop until find : push
    • popup: () => void 弹窗
    • dismiss: () => boolean 取消弹窗
  • db 数据/页面传参

  • trace 痕迹

  • URLSchema

    • across()

#3 基本动作的实现

基本操作, 基本操作

  • push
    • hisotry.push([next])
  • pop
    • hisotry.pop()
  • replace
    • hisotry[hisotry.length - 1] = [next]
  • go
    • this.push
    • while (topNav[0] !== target) hisotry.pop();
  • popup
    • topNav.push(Layer)
  • dismiss
    • topNav.pop()

#4 核心组件与渲染

redux free!

  • Root
    • router.event
  • Page
    • position: absolute
    • @beforeEnter
    • @beforeLeave
    • @onShow
    • @onHide
    • @render
  • Layer
    • position: absolute

#5 页面传参与配置

power of immmer

  • when

    • push(page, data, config)
    • replace(page, data, config)
  • where

    • router.db [location.query,location.search]
      • 问题: 全局变量
      • 优势: 在组件中方便的使用
    • pageInstace.props.routeDB
      • 问题: 组件中如何使用
      • 优势: 伴随组件生命周期
    • keep? [Cookie]
  • clear?

    • immer.applyPatches

#6 生命周期的实现

@ref, @AppState

  • Page.onShow/Page.onHide

    • @componentDidMount onShow
    • @componentWillUnmount onHide
    • AppState.onChange
      • ref.onShow / ref.onHide
  • 组件内如何使用所在页面钩子?

    • const { Provider, Consumer } = createContext({});
    • .lifetimes = { onShow: [], onHide: [] }
    • .render
      • props: onShow
      • props: onHide
  • 主要问题

    • 进入动画未完成, 页面还未进入, 触发了 onShow
    • beforeEnter 权限校验未通过, 还是进入了页面触发了 onShow

#7 Promise, 钩子和动画

Promise yes!

  • All in Promise

    • push: () => Promise
    • pop: () => Promise
    • replace: () => Promise
    • go: () => Promise
  • push: Promise

    • 创建路由信息 next
      • id
      • name
      • element
      • ref
      • ...
    • 先假装push并渲染, history.push([next]);
    • db.push(data);
    • forceUpdate render // 通过 transform 来隐藏
    • [等待 ref 完成], 拿到实例, 主要是为了实例上的 beforeEnter 钩子
    • Promise.all beforeEnter 钩子
      • then
        • 触发入场动画
        • 触发 length - 2 页面的 onHide
        • 触发 next 的 onShow
        • resolve
      • catch
        • db.revert();
        • hisotry.pop();
        • reject
  • pop: Promise

    • 获取栈顶实例
    • Promise.all beforeLeave 离场钩子
      • then
        • 触发栈顶动画
        • [等待动画完成]
        • 触发当前 onHide
        • db.push(data)
        • hisotry.pop();
        • 触发下一个页面的 onShow
        • reoslve
      • catch reject
  • go: Promise

    • while (topNav[0] !== target) hisotry.pop();
    • 如果所有钩子都执行, 可能被中间页面中断, 另外批量触发pop动画也会卡顿, 所以只对栈顶页面进行 pop 判断和动画, 中间页面直接 splice 掉

#8 Backhandler与手势

Native

  • 触发 pop / dismiss
  • 手势是个大难题

#9 URLSchema

push 与 linking

  • parser 解析 URL 参数
  • polyfill pop
    • 如果栈底不是 /, 则替换为 /, 不用push是因为那样就成死循环了
  • across(paths) 追加穿透行为
    • 根据给定路由记录制造路由栈
    • 最后一个页面需要动画, 其余不需要, 跟 go 的一种情况是反向操作
  • 另一个难题across 中途被 Auth 之类的终端了, 再怎么续上
    • 保留 unacross, 然后 across 方法就递归

#10 原子操作页面的一个小礼物

atom

  • 原子操作页面

    • 选择联系人
    • 选择地址
    • 扫码
    • ...
  • wait

    • push 表现一样, 只是 resolve 会被存储, 等待回到栈顶接收参数
    • wait('/next').then(got => console.log('got it', got));

#11 debug 与 Exception

面向 console.log debug

  • trace page 需要追加的信息, 用于debug 和 log

    • lifetimes: []
    • name
    • path
  • enum Exception

    • AOP 尽量给出位置信息方便 debug

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.