Skip to content

Add support for custom history implementations #2052

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ardoramor opened this issue Feb 8, 2018 · 7 comments
Open

Add support for custom history implementations #2052

ardoramor opened this issue Feb 8, 2018 · 7 comments
Labels
feature request fixed on 4.x This issue has been already fixed on the v4 but exists in v3 needs RFC This feature request needs to go through the RFC process to gather more information

Comments

@ardoramor
Copy link

What problem does this feature solve?

This feature would address many requests seen in relation to having greater control over applications history, stack management, initial route, and a few others.

There are several supported history modes. My proposal is to allow mode option accept an instance of a class that implements History API.

Instantiation would look like:

import { AbstractHistory } from 'vue-router'

class CustomHistory extends AbstractHistory {
   ...
}

const customHistory = new CustomHistory()

const router = new VueRouter({
  mode: customHistory,
  routes: [...]
})

This would give great flexibility to developers and would allow further integrations of cool features such as keeping reactive history with vuex.

What does the proposed API look like?

mode option would accept String or an instance of AbstractHistory. Internally, if an instance is detected, the history manipulation would happen through it.

@bundyo
Copy link

bundyo commented Sep 5, 2018

Disclaimer: I work for NativeScript Tooling

Using VueRouter in NativeScript-Vue

We want to use the default VueRouter in NativeScript-Vue since it is much more familiar to the casual web developer that comes to build native mobile apps than a custom solution of our own. However, currently the usage of VueRouter in NativeScript-Vue is hindered by the difference of how <router-view/> and {N} frame navigation works. <router-view/> essentially works, but directly replaces the content as it does in web, thus breaking frame animations and back button view caching. To work around this problem, we need to deeper changes to how the History is handled and the current VueRouter doesn't support custom History implementation.

However the above proposal while good is somewhat problematic. It is okay to be used directly in an app, but using this syntax to create an NPM package would include most of the VueRouter in the said package and the user should use the router from within that package, since importing it again would result in two routers, one of which without the said custom History in it.

Thus to work around this, our proposal is to use a factory to extend the VueRouter mode. Something in the lines of:

Init in VueRouter constructor

let CustomHistory
if (mode && mode.constructor === Object) {
  CustomHistory = mode.factory(AbstractHistory)

  mode = mode.name
}

if (!inBrowser && !CustomHistory) {
  mode = 'abstract'
}
this.mode = mode
  
switch (mode) {
  case 'history':
  ...
  default:
    if (CustomHistory) {
      this.history = new CustomHistory(this, options.base)
      break
    }
  ...
}

Factory module

export default (mode = {
  name: 'NativeScriptHistory',

  factory(baseClass) {
    return class NativeScriptHistory extends baseClass {
      constructor(router, base) {
        super(router, base)
        ...
      }

      ...
    }
  }
})

Usage

import { Vue, mode } from "nativescript-vue";  
import VueRouter from "vue-router";
  
Vue.use(VueRouter);  
  
const router = new VueRouter({
    mode,
    routes: [...],
});

With some modifications this can be reworked to inherit any of the existing histories.

What do you think?

I can make a pull request if needed.

@jlooper
Copy link

jlooper commented Sep 14, 2018

Kamen has made a fork of the Vue Router with changes we'd like to see implemented here nativescript-vue#1 - for now, we can use this fork but going forward, of course, for maintainability, we'd love to have them incorporated into the proper Vue Router

@jlooper
Copy link

jlooper commented Sep 14, 2018

cc @posva @yyx990803 @bundyo @rigor789

@yyx990803
Copy link
Member

yyx990803 commented Sep 16, 2018

Personally, I've always thought that vue-router's design isn't perfectly suited for mobile development as well. Most web apps perform full content replacement on navigation, while mobile apps often uses a stack-like structure where the previous screens are held in cache and can be navigated back to.

I've always wanted to revisit the problem and see if it's possible to provide one solution for both use cases, but deep down I feel that it may be best to have a dedicated solution for each due to the fundamental difference in how navigation is modeled on different platforms.

I'd be curious to hear more details on how a custom history implementation would help solve this, although personally, I don't think it's the best route forward trying to bend vue-router to fit mobile development.

@bundyo
Copy link

bundyo commented Sep 17, 2018

You are right - most mobile apps are working on a stack like cache history structure, while on the web direct replacement takes place. Additionally mobile apps not always depend on CSS for the view animations (the current versions of NativeScript don't yet support such animations, though this may change). However the rest of the functionality in the router is shared and we also wanted the user to experience something he is already used to when coming from the web - a router-view, history management and data propagation between the routes. This was the main reason we decided to use VueRouter instead of writing a new one.

I probably want too much, but I see a future VueRouter that is more modular - the core functionality and data handling to be baked in and the router-view/link implementations, history management and transition handling to be replaceable, depending on the occasion. This will also allow for better web/mobile code sharing - even though the views on desktop web and mobile apps differ greatly - the views in the mobile web and mobile apps do not.

Currently we use the VueRouter by passing our own history, based on the AbstractHistory, which is only doing some argument checks and passing all arguments to NativeScript-Vue's Frame implementation which takes care of doing the navigation through the NativeScript history stack.

@posva
Copy link
Member

posva commented Sep 17, 2018 via email

@bundyo
Copy link

bundyo commented Sep 17, 2018

I've tried to create a custom router-view, but since it is functional - I was unable to get to the Frame that houses it since I have to trigger the navigation there. We also thought about integrating the Frame inside the router-view - but this might be a point for confusion, since without the Router, one has to use it to do navigation.

But yes, if I can somehow can get to the Frame from inside a custom router-view and use custom history - that would be great and solve our issues.

@posva posva added the fixed on 4.x This issue has been already fixed on the v4 but exists in v3 label Mar 18, 2020
@posva posva added the needs RFC This feature request needs to go through the RFC process to gather more information label May 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request fixed on 4.x This issue has been already fixed on the v4 but exists in v3 needs RFC This feature request needs to go through the RFC process to gather more information
Projects
None yet
Development

No branches or pull requests

5 participants