This is the second post about React and Vue syntax comparison. In this article, we compare the syntax for the most famous routing library in both ecosystems.
oahehc / react-vue-comparison
Comparing the syntax of React.js/Next.js and Vue.js/Nuxt.js side by side
Agenda
- Basic-Routing
- Dynamic-Routing
- Nested-Routing
- Link
- NavLink
- Get-Location
- Push
- Replace
- Redirect
- Event
- Scroll
- Lazy-Loading-and-Code-Splitting
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 }], });
Top comments (0)