Swift Router 页面跳转路由,组件解耦


为什么要用到Router去做跳转:解耦、方便

像底下这种代码可能写了很多很多遍了,尤其是在项目中某个页面入口很多的情况下。

let xx = XX()

...

let vc = XXXViewController(xx:xxx)
self.navigationController?.pushViewController(vc, animated: true)

尤其是公司要开发多个项目,对模块进行了拆分,组件化的模式需要中间一个Router去决定跳转到那个模块的页面,而不是在每个页面都import XX 耦合非常严重。

浏览了下GitHub上的两个库,都不是很满意

  • Router 比较Swifty,但是耦合比较严重,实现了很多暂时不需要的功能,每个VC需要将自己当成字符串告诉Router , 还要告诉当前的navigation , 使用了NSClassFromString根据字符创建的 AnyClass 。比较繁琐-- 但是还有很好的思想可以借鉴的
  • FNUrlRoute 通过url形式跳转,看起来挺不错,仔细看下代码,首先AppDelegate要先用字符串和VC进行映射,每个VC要传入[String:AnyObject]? 进行初始化,这个把VC的创建都限制死了。绝对用不了呀,还有那么多人star ...

说完他们的不足,首先来看下我们这个Router设计要求

  • 解耦:调用者不知道VC的名字
  • 不要用字符串,字符串容易出错
  • 不能限制初始化方法
  • 调用者应该非常简洁

那么不使用字符串很容易想到就是用枚举来替代,枚举中也可能映射VC呀,而且不用在AppDelegate中注册,不能限制初始化方法我们就用params字典去映射 Router 里面的方式 感觉比较好 , 自己肯定是知道自己怎么初始化的, 用协议的方式比用强迫字典初始化好很多

public typealias  RouterParameter = [String: Any]
public protocol Routable {
  /**
   类的初始化方法
   - params 传参字典
   */
  static func initWithParams(params: RouterParameter?) -> UIViewController
}

我们跳转只需要知道哪个VC要传的参数,这个都交给枚举就可以了,为了项目路径映射和跳转解耦,用一个协议

public protocol RouterPathable {
  var any: AnyClass { get }
  var params: RouterParameter? { get }
}

其他就交给跳转了

open class func open(_ path:RouterPathable , present: Bool = false , animated: Bool = true , presentComplete: (()->Void)? = nil){
    if let cls = path.any as? Routable.Type {
      let vc = cls.initWithParams(params: path.params)
      vc.hidesBottomBarWhenPushed = true
      let topViewController = RouterUtils.currentTopViewController()
      if topViewController?.navigationController != nil && !present {
        topViewController?.navigationController?.pushViewController(vc, animated: animated)
      }else{
        topViewController?.present(vc, animated: animated , completion: presentComplete)
      }
    }
  }

其中有用到一个工具方法是获取最上层的vc好进行跳转,具体代码可以去GitHub下载

使用: 需要使用router进行跳转的都要事先Routable 接口,调用者不需要

无参数

class AVC: UIViewController, Routable{
  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = UIColor.red
  }

  static func initWithParams(params: RouterParameter?) -> UIViewController {
    return AVC()
  }
}

有参数


struct Demo {
  var name: String
  var id: Int
}

class RVC: UIViewController {
  let demo:Demo
  init(demo:Demo) {
    self.demo = demo
    super.init(nibName: nil, bundle: nil)
  }
  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  
  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = UIColor.white
    navigationItem.title = demo.name
  }
}

extension RVC: Routable {
  static func initWithParams(params: RouterParameter?) -> UIViewController {
    guard let demo = params?["demo"] as? Demo else {
      fatalError("params is wrong")
    }
    let rvc = RVC(demo: demo)
    return rvc
  }
}

路径映射:

比如上面的vc都是其他模块的,那么只有这个映射的枚举需要引入其他模块,调用者不需要 , 下面展示三个vc的路径映射

enum RouterPath: RouterPathable {
  case avc
  case bvc(String)
  case rvc(Demo)
  
  var any: AnyClass {
    switch self {
    case .avc:
      return AVC.self
    case .bvc:
      return BVC.self
    case .rvc:
      return RVC.self
    }
  }
  
  var params: RouterParameter? {
    switch self {
    case .bvc(let name):
      return ["name":name]
    case .rvc(let demo):
      return ["demo":demo]
    default:
      return nil
    }
  }
}

只要实现 RouterPathable 都可以 ,如果需要映射的vc特别多 , 也可以分组管理。

调用者就很方便了

Router.open(RouterPath.avc)
let demo = Demo(name: "RVC title", id: 1)
Router.open(RouterPath.rvc(demo))

或者present

Router.open(RouterPath.bvc("BVC title"), present: true)

项目地址: SwiftyRouter



作者:大石头布
链接:http://www.jianshu.com/p/4ba2db91030b
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,可以非常方便的实现单页面应用程序的路由功能。 Vue Router 提供了以下两种方式实现页面路由跳转: 1. 声明式导航:通过 `<router-link>` 组件实现页面跳转,该组件会被渲染成一个 `<a>` 标签,点击该标签后会触发路由跳转。 2. 编程式导航:通过 `$router` 对象提供的方法实现页面跳转,例如 `$router.push()`、`$router.replace()`、`$router.go()` 等方法。 下面我们来看一个简单的示例,在 Vue Router 中如何实现页面路由跳转: ```html <!-- 在模板中使用 router-link 组件 --> <router-link to="/home">Home</router-link> <!-- 在组件中使用 $router 对象实现编程式导航 --> <button @click="$router.push('/about')">About</button> ``` 在上面的示例中,我们分别演示了如何使用 `<router-link>` 组件和 `$router` 对象实现页面路由跳转,其中 `to` 属性表示跳转的目标路由地址。 此外,Vue Router 还支持路由嵌套的功能,可以通过嵌套路由的方式实现页面的嵌套展示。下面我们来看一个嵌套路由的示例: ```javascript const router = new VueRouter({ routes: [ { path: '/home', component: Home, children: [ { path: 'news', component: News }, { path: 'videos', component: Videos } ] } ] }) ``` 在上面的示例中,我们定义了一个名为 `Home` 的路由组件,并在该组件中嵌套了两个子路由 `News` 和 `Videos`,这样就可以实现在 `Home` 组件中展示新闻和视频内容的功能。在实际开发中,我们可以根据实际需求来定义不同的路由组件和子路由,实现灵活的页面嵌套效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值