Skip to content

Latest commit

 

History

History
489 lines (374 loc) · 7.53 KB

ROUTER.md

File metadata and controls

489 lines (374 loc) · 7.53 KB

Router: React-Router & Vue-Router

Basic-Routing

React-Router

import { BrowserRouter, Switch, Route } from 'react-router-dom';

export default function App() {
  return (
    <BrowserRouter>
      <div>
        <Switch>
          <Route path="/about" component={About} />
          <Route path="/" component={Home} />
        </Switch>
      </div>
    </BrowserRouter>
  );
}

Vue-Router

const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar },
];
const router = new VueRouter({
  mode: 'history',
  routes,
});
const app = new Vue({ router }).$mount('#app');
<div id="app">
  <router-view></router-view>
</div>

Dynamic-Routing

React-Router

import { BrowserRouter, Route } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <div>
        <Route path="/contact/:id" component={Contact} />
      </div>
    </BrowserRouter>
  );
}

...

import { useParams } from 'react-router-dom';

function Contact() {
  let { id } = useParams();

  return ...;
}

Vue-Router

const router = new VueRouter({
  mode: 'history',
  routes: [{ path: '/contact/:id', component: Contact }],
});

export default {
  computed: {
    id() {
      return this.$route.params.id;
    },
  },
};

Nested-Routing

React-Router

import { BrowserRouter, Route } from 'react-router-dom';

const App = () => (
  <BrowserRouter>
    <div>
      <Route path="/tacos" component={Tacos} />
    </div>
  </BrowserRouter>
);

...

import { Route } from 'react-router-dom';

const Tacos = ({ match }) => (
  <div>
    {/* here's a nested Route, match.url helps us make a relative path */}
    <Route path={match.url + '/carnitas'} component={Carnitas} />
  </div>
);

Vue-Router

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      children: [
        {
          path: 'profile',
          component: UserProfile,
        },
        {
          path: 'posts',
          component: UserPosts,
        },
      ],
    },
  ],
});

const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `,
};

Link

React-Router

<Link
  to={{
    pathname: '/courses',
    search: '?sort=name',
    hash: '#the-hash',
    state: { fromDashboard: true },
  }}
>
  courses
</Link>

Vue-Router

<router-link to="/courses">courses</router-link>

NavLink

NavLink is used to display different style when current URL match to the link.

React-Router

<NavLink to="/react" activeClassName="react">
  React
</NavLink>

Vue-Router

router-link automatically gets the .router-link-active class when its target route is matched.

<router-link to="/vue">vue</router-link>

Get-Location

React-Router

Function component

import { useLocation } from "react-router-dom";

function App() {
  const location = useLocation();

  return ...;
}

Class component

import { withRouter } from "react-router";

class App extends React.Component {
  static propTypes = {
    location: PropTypes.object.isRequired
  };

  render() {
    const { location } = this.props;

    return ...;
  }
}
export default withRouter(App);

Vue-Router

export default {
  computed: {
    path() {
      return this.$route.path;
    },
    params() {
      return this.$route.params;
    },
    query() {
      return this.$route.query;
    },
    hash() {
      return this.$route.hash;
    },
    fullPath() {
      return this.$route.fullPath;
    },
  },
};

Push

React-Router

import { useHistory } from 'react-router-dom';

function HomeButton() {
  const history = useHistory();

  function handleClick() {
    history.push('/home');
  }

  return (
    <button type="button" onClick={handleClick}>
      Go home
    </button>
  );
}

Vue-Router

export default {
  methods: {
    toHome() {
      this.$router.push('/home');
    },
    toUser(id) {
      this.$router.push({ name: 'user', params: { userId: id } });
    },
    toRegister(id) {
      // /register?plan=private
      this.$router.push({ path: 'register', query: { plan: 'private' } });
    },
  },
};

Replace

replacing the current entry instead of push a new entry onto the history stack.

React-Router

<Link to="/courses" replace />;

// or

const history = useHistory();

function handleClick() {
  history.replace('/courses');
}

Vue-Router

<router-link :to="/courses" replace />

or

export default {
  methods: {
    toHome() {
      this.$router.replace('/home');
    },
  },
};

Redirect

React-Router

<Redirect to="/login" />
<Redirect from="/invoices" to="/invoices/dashboard" />
// push a new entry onto the history instead of replacing the current one.
<Redirect push to="/somewhere/else" />

Vue-Router

const router = new VueRouter({
  routes: [{ path: '/a', redirect: { name: 'foo' } }],
});

Event

React-Router

Function component

import { useHistory } from 'react-router-dom';

function App() {
  const history = useHistory();

  useEffect(() => {
    const unlisten = this.props.history.listen(...);
    return () => unlisten();
  }, [])

  return ...;
}

Class component

import { withRouter } from "react-router";

class App extends React.Component {
  static propTypes = {
    history: PropTypes.object.isRequired
  };

  componentDidMount() {
    this.unlisten = this.props.history.listen(...);
  }

  componentWillUnmount() {
    if (this.unlisten && typeof this.unlisten === 'function') {
      this.unlisten();
    }
  }

  render() {
    return ...;
  }
}
export default withRouter(App);

Vue-Router

global

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => { ... })
router.afterEach((to, from) => { ... })

by route

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => { ... }
    }
  ]
})

by component

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) { ... },
  beforeRouteUpdate (to, from, next) { ... },
  beforeRouteLeave (to, from, next) { ... },
}

Scroll

React-Router

Because browsers are starting to handle the default case and apps have varying scrolling needs, React-Router don’t ship with default scroll management.
https://reacttraining.com/react-router/web/guides/scroll-restoration

export default function ScrollToTop() {
  const { pathname } = useLocation();

  useEffect(() => {
    window.scrollTo(0, 0);
  }, [pathname]);

  return null;
}

Vue-Router

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return desired position
    if (savedPosition) {
      return savedPosition
    } else {
      return { x: 0, y: 0 }
    }
  }
})

Lazy-Loading-and-Code-Splitting

If you are using Babel, you will need to add the syntax-dynamic-import plugin so that Babel can properly parse the syntax.

React-Router

https://github.com/gregberge/loadable-components

import loadable from '@loadable/component';

const LoadableComponent = loadable(() => import('./Dashboard.js'), {
  fallback: <Loading />,
});

Vue-Router

const Foo = () => import('./Foo.vue');

const router = new VueRouter({
  routes: [{ path: '/foo', component: Foo }],
});