React.js和Vue.js都是很好的框架。而且Next.js和Nuxt.js甚至将它们带入了一个新的高度,这有助于我们以更少的配置和更好的可维护性来创建应用程序。但是,如果你必须经常在框架之间切换,在深入探讨另一个框架之后,你可能会轻易忘记另一个框架中的语法。在本文中,我总结了这些框架的基本语法和方案,然后并排列出。我希望这可以帮助我们尽快掌握语法。
Assets
Next.js
/*
|- public/
|-- my-image.png
*/
function MyImage() {
return <img src="/my-image.png" alt="my image" />;
}
Nuxt.js
assets,默认情况下,Nuxt使用vue-loader、file-loader和url-loader来提供强大的assets服务。
<!--
|- assets/
|- image.png
-->
<img src="~/assets/image.png" alt="image" />
static,自动服务
<!--
|- static/
|- image.png
-->
<img src="/image.png" alt="image" />
基本路由
Next.js
|- pages/
|- index.js → href="/"
|- blog/index.js → href="/blog"
Nuxt.js
|- pages/
|- index.vue → href="/"
|- blog/index.vue → href="/blog"
动态路由
Next.js
|- pages/
|- blog/[slug].js → href="/blog/:slug" (eg. /blog/hello-world)
|- [username]/[option].js → href="/:username/:option" (eg. /foo/settings)
|- post/[...all].js → href="/post/*" (eg. /post/2020/id/title)
Nuxt.js
|- pages/
|- blog/[slug].vue → href="/blog/:slug" (eg. /blog/hello-world)
|- _username/_option.vue → href="/:username/:option" (eg. /foo/settings)
Link
Next.js
import Link from "next/link";
function Home() {
return (
<Link href="/">
<a>Home</a>
</Link>
);
}
Nuxt.js
<template>
<nuxt-link to="/">Home page</nuxt-link>
</template>
Fetch-On-Server
Next.js
getInitialProps只能在每个页面的默认导出中使用
< Next.js 9.3 (class component)
import fetch from "isomorphic-unfetch";
export default class Page extends React.Component {
static async getInitialProps(ctx) {
const res = await fetch(`https://.../data`);
const data = await res.json();
return { props: { data } };
}
render() {
// Render data...
}
}
< Next.js 9.3 (function component)
import fetch from "isomorphic-unfetch";
function Page({ data }) {
// Render data...
}
Page.getInitialProps = async (ctx) => {
const res = await fetch(`https://.../data`);
const data = await res.json();
return { props: { data } };
};
>= Next.js 9.3
import fetch from "isomorphic-unfetch";
function Page({ data }) {
// Render data...
}
export async function getServerSideProps() {
const res = await fetch(`https://.../data`);
const data = await res.json();
return { props: { data } };
}
export default Page;
Nuxt.js
<template>
<div v-if="$fetchState.error">发生了一些错误 </div>
<div v-if="$fetchState.pending">Loading...</div>
<div v-else>
<h1>{{ post.title }}</h1>
<pre>{{ post.body }}</pre>
<button @click="$fetch">刷新</button>
</div>
</template>
<script>
import fetch from "node-fetch";
export default {
data() {
return {
post: {},
};
},
async fetch() {
this.post = await this.$http.$get("xxx");
},
fetchOnServer: true,
};
</script>
Layout
Next.js
./pages/_app.js
:自动应用于所有页面
export default function MyApp({ Component, pageProps }) {
return (
<React.Fragment>
<MyHeader />
<Component {...pageProps} />
<MyFooter />
</React.Fragment>
);
}
Nuxt.js
layouts/with-header-footer.vue
:创建布局
<template>
<div>
<MyHeader />
<nuxt />
<MyFooter />
</div>
</template>
pages/index.vue
:应用布局
<template>
<!-- 你的模板 -->
</template>
<script>
export default {
layout: "with-header-footer",
};
</script>
错误页面
Next.js
pages/_error.js
function Error({ statusCode }) {
return (
<p>
{statusCode
? `An error ${statusCode} occurred on server`
: "An error occurred on client"}
</p>
);
}
Error.getInitialProps = ({ res, err }) => {
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
return { statusCode };
};
export default Error;
Nuxt.js
layouts/error.vue
<template>
<div class="container">
<h1 v-if="error.statusCode === 404">Page not found</h1>
<h1 v-else>一个错误发生</h1>
<nuxt-link to="/">Home page</nuxt-link>
</div>
</template>
<script>
export default {
props: ["error"],
layout: "blog", // 你可以为错误页面设置自定义布局
};
</script>
Meta-Tag
Next.js
import Head from "next/head";
function IndexPage() {
return (
<div>
<Head>
<title>My page title</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
</Head>
<p>Hello world!</p>
</div>
);
}
Nuxt.js
<template>
<h1>{{ title }}</h1>
</template>
<script>
export default {
data() {
return {
title: "Hello World!",
};
},
head() {
return {
title: this.title,
meta: [
// 为了避免在子组件中使用重复的元标记,可以使用hid键设置唯一的标识符
{
hid: "description",
name: "description",
content: "My custom description",
},
],
};
},
};
</script>
Context
Next.js
getInitialProps只能在每个页面的默认导出中使用
function Page({ data }) {
// 渲染数据...
}
Page.getInitialProps = async (context) => {
const { pathname, query, asPath, req, res, err } = context;
// pathname - 当前路径,这是/pages中的页面路径。
// query - 将URL的查询字符串部分作为对象进行解析
// asPath - 浏览器中显示的实际路径(包括查询)的字符串
// req - HTTP request object (server only)
// res - HTTP response object (server only)
// err - 如果在渲染过程中遇到任何错误,则为错误对象。
return { props: { project: "next" } };
};
Nuxt.js
export default {
asyncData(context) {
// 通用keys
const {
app,
store,
route,
params,
query,
env,
isDev,
isHMR,
redirect,
error,
} = context;
// 服务器端
if (process.server) {
const { req, res, beforeNuxtRender } = context;
}
// 客户端
if (process.client) {
const { from, nuxtState } = context;
}
return { project: "nuxt" };
},
};
CLI
React.js: create-react-app
npx create-react-app react-template
Next.js: create-next-app
npx create-next-app next-template
Vue.js: vue-cli
yarn global add @vue/cli
vue create vue-template
如果对你有所启发和帮助,可以点个关注、收藏、转发,也可以留言讨论,这是对作者的最大鼓励。
作者简介:Web前端工程师,全栈开发工程师、持续学习者。