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)