前言
阅读建议:建议通过左侧导航栏进行阅读
案例介绍
功能介绍
RealWord
是一个开源学习项目,目的是帮助开发者快速学习新技能,开发者可以使用任何技术去实现它。RealWord
是一个类似一个小论坛的项目,业务流程很简单,包括的功能有用户登录/注册/退出/个人中心、文章信息发布/修改/详情查看/分页展示/作者信息查看/点赞/取消点赞/评论。
相关资源链接
- 在线示例:https://demo.realworld.io/#/
- GitHub仓库:https://github.com/gothinkster/realworld
- 接口文档:https://github.com/gothinkster/realworld/tree/master/api
- 页面模板:https://github.com/gothinkster/realworld-starter-kit/blob/master/FRONTEND_INSTRUCTIONS.md
学习收获
- 掌握使用
Nuxt.js
开发同构渲染应用 - 增强
Vue.js
实践能力 - 掌握同构渲染应用中常见的功能处理
- 用户登录态管理
- 页面访问权限处理
SEO
优化
准备工作
新建项目,进入项目目录
yarn init //生成 package.json 文件
yarn add nuxt //安装 nuxt 依赖
在package.json
中添加启动脚本:
"scripts": {
"dev": "nuxt"
},
新建pages
目录,创建子目录,并将提供的对应页面模板放入相应子目录下的index.vue
中,处理完所有页面组件后,pages
目录结构如下图:
在项目根目录下,新建一个app.html
文件,并使用Nuxt.js
默认的应用模板,导入项目中需要使用的CSS
样式及字体文件。
ionicons.min.css
文件中引用了其他字体文件,因此使用jsDelivr
进行地址转换;
index.css
是项目自身的样式文件,直接下载文件,放入static/index.css即可
<html {
{
HTML_ATTRS }}>
<head {
{
HEAD_ATTRS }}>
{
{ HEAD }}
<!-- 引入经过jsdelivr本地化后的字体文件 -->
<link href="https://cdn.jsdelivr.net/npm/ionicons@2.0.1/css/ionicons.min.css" rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=Titillium+Web:700|Source+Serif+Pro:400,700|Merriweather+Sans:400,700|Source+Sans+Pro:400,300,600,700,300italic,400italic,600italic,700italic" rel="stylesheet" type="text/css">
<!-- 引入本地化后(static/index.css)的css文件-->
<link rel="stylesheet" href="/index.css">
</head>
<body {
{
BODY_ATTRS }}>
{
{ APP }}
</body>
</html>
到此,正式开发的前期准备工作完成。
具体实现
自定义路由规则
在项目根目录下新建nuxt.config.js
,通过Nuxt.js
路由的extendRoutes
选项自定义路由规则。
/**
* 配置自定义路由表规则
*/
module.exports = {
router: {
extendRoutes(routes, resolve) {
routes.splice(0);//清除nuxtjs根据Pages目录生成的默认路由
routes.push(...[
{
path: '/',
component: resolve(__dirname, 'pages/layout/'), //父组件
children: [
{
path: '', //默认子路由
name: 'home',
component: resolve(__dirname, 'pages/home/')
},
{
path: '/login',
name: 'login',
component: resolve(__dirname, 'pages/login/')
},
{
path: '/register',
name: 'register',
component: resolve(__dirname, 'pages/login/')
},
{
path: '/profile/:username',
name: 'profile',
component: resolve(__dirname, 'pages/profile/')
},
{
path: '/settings',
name: 'settings',
component: resolve(__dirname, 'pages/settings/')
},
{
path: '/editor',
name: 'editor',
component: resolve(__dirname, 'pages/editor/')
},
{
path: '/article/:slug',
name: 'article',
component: resolve(__dirname, 'pages/article/')
}
]
}
]);
}
}
}
处理登录注册页面
pages/login/index.vue
登录/注册功能需要共用一个页面组件,使用计算属性判断当前页面是登录还是注册,根据该计算属性,进行登录注册页面差异性处理。
computed: {
isLogin() {
return this.$route.name === 'login';
}
},
处理顶部导航链接
pages/layout/index.vue
将页面模板顶部导航栏组件中所有的a
标签换成nuxt-link
标签,并为其to
属性添加正确的页面链接,达到点击以后跳转到正确页面的效果。
<!--顶部导航栏-->
<nav class="navbar navbar-light">
<div class="container">
<nuxt-link class="navbar-brand" to="/">conduit</nuxt-link>
<ul class="nav navbar-nav pull-xs-right">
<li class="nav-item">
<!--exact表示精确匹配,只有当路由是“/”时,才会高亮,而不是以“/”开头就高亮-->
<nuxt-link exact class="nav-link" to="/">Home</nuxt-link>
</li>
<template v-if=