# realworld-nuxtjs
**Repository Path**: dadami/realworld-nuxtjs
## Basic Information
- **Project Name**: realworld-nuxtjs
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-08-12
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
### 一、创建项目
- mkdir realworld-nuxtjs
- npm init -y
- npm i nuxt
- 配置启动脚本
- 创建pages目录,配置初始化页面
### 二、导入页面模版
```html
{{ HEAD }}
{{ APP }}
```
### 三、项目初始化-导入样式资源
### 四、项目初始化-布局组件
- 导入样式资源
- 配置布局组件
- 配置页面组件
### 七、处理顶部导航链接
```html
// layout/index.vue
Home
// 替换
```
### 解析存储登录状态实现流程
```js
// https://www.nuxtjs.cn/examples/auth-external-jwt
// https://codesandbox.io/s/github/nuxt/nuxt.js/tree/dev/examples/auth-jwt?from-embed
// 为了防止数据冲突,需要把state 定义成一个函数,返回数据对象
export const state = () => {
return {
// 当前登录用户的登录状态
user: null
}
}
export const mutations = {
setUser (state, data) {
state.user = data
}
}
export const actions = {}
```
```js
// index.vue
async onSubmit () {
try {
const { data } = this.isLogin ? await login({
user: this.user
}) : await register({
user: this.user
})
// 保存用户的登录状态
this.$store.commit('setUser', data.user)
// 跳转到首页
this.$router.push('/')
} catch (err) {
this.errors = err.response.data.errors
}
}
```

### 17.登录状态持久化
```js
const cookieparser = process.server ? require('cookieparser') : undefined
// 为了防止数据冲突,需要把state 定义成一个函数,返回数据对象
export const state = () => {
return {
// 当前登录用户的登录状态
user: null
}
}
export const mutations = {
setUser (state, data) {
state.user = data
}
}
export const actions = {
// nuxtServerInit 是一个特殊的action方法
// 这个action 会在服务端渲染期间自动调用
// 作用: 初始化容器数据,传递数据给客户端使用
nuxtServerInit ({ commit }, { req }) {
let user = null
// 如果请求头有cookie
if (req.headers.cookie) {
// 使用cookieparser 把cookie 字符串转换为JS对象
const parsed = cookieparser.parse(req.headers.cookie)
try {
user = JSON.parse(parsed.user)
} catch (err) {
// No
}
}
// 提交mutation 修改state状态
commit('setUser', user)
}
}
// index.vue
async onSubmit () {
try {
const { data } = this.isLogin ? await login({
user: this.user
}) : await register({
user: this.user
})
// 保存用户的登录状态
this.$store.commit('setUser', data.user)
// 防止页面刷新,数据丢失,需要把数据持久化
Cookie.set('user', data.user)
// 跳转到首页
this.$router.push('/')
} catch (err) {
this.errors = err.response.data.errors
}
}
```
### 处理页面访问权限
[Nuxt中间件](https://www.nuxtjs.cn/examples/middleware)
我们只需在组件中配置一个参数就行, middelware 会自动去找到authenticated文件夹去匹配是否渲染
```js
// 创建 middleware/authenticated.js
export default function ({ store, redirect }) {
if (store.state.user) {
return redirect('/login')
}
}
// 组件配置
export default {
// 在路由匹配组件渲染之前先执行中间件处理
middleware: ['authenticated']
}
// 创建 middleware/notAuthenticated.js
export default function ({ store, redirect }) {
if (store.state.user) {
return redirect('/')
}
}
// 组件配置
export default {
// 在路由匹配组件渲染之前先执行中间件处理
middleware: ['notAuthenticated']
}
```
### 公共文章列表
https://github.com/gothinkster/realworld/tree/master/api
List Articles
```
```
### 优化并行任务
```js
async asyncData ({ query }) {
const page = Number.parseInt(query.page || 1)
const limit = 20
const [ articleRes, tagRes ] = await Promise.all([
getArticles({
limit,
offset: (page - 1) * limit
}),
getTags()
])
const { articles, articlesCount } = articleRes.data
const { tags } = tagRes.data
return {
articles,
articlesCount,
tags,
limit,
page
}
}
```
### 统一设置token
```js
// plugins/request.js
/**
* 基于 axios 封装的请求模块
*/
import axios from 'axios';
export const request = axios.create({
baseURL: 'https://conduit.productionready.io'
})
export default ({ store }) => {
// 请求拦截器
// 统一设置token
request.interceptors.request.use(function (config) {
// Do something before request is sent
const { user } = store.state
if (user && user.token) {
config.headers.Authorization = `Token ${user.token}`
}
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error)
});
}
// nuxt.config.js注册插件
plugins: [
'~/plugins/request.js'
]
```
### 时间格式化处理
- day.js 仅2kb
- 封装成全局过滤器
- plugins/day.js
```js
timer | date('MMM DD, YYYY')
```
### markdown 处理
```js
npm install markdown-it -save
// 使用
import { getArticle } from '@/api/article'
import MarkdownIt from 'markdown-it'
export default {
name: 'AritcelIndex',
async asyncData ({ params }) {
const { data } = await getArticle(params.slug)
const { alticle } = data
const md = new MarkdownIt()
data.body = md.render(article.body)
return {
article
}
}
};
```

### 文章详情优化
[nuxtjs视图 HTML 头部](https://www.nuxtjs.cn/guide/views)
Nuxt.js 使用了 vue-meta 更新应用的 头部标签(Head) and html 属性
```
{
keyName: 'head', // 设置 meta 信息的组件对象的字段,vue-meta 会根据这 key 值获取 meta 信息
attribute: 'n-head', // vue-meta 在监听标签时所添加的属性名
ssrAttribute: 'n-head-ssr', // 让 vue-meta 获知 meta 信息已完成服务端渲染的属性名
tagIDKeyName: 'hid' // 让 vue-meta 用来决定是否覆盖还是追加 tag 的属性名
}
```
个性化特定页面的 Meta 标签
关于个性化特定页面的 Meta 标签,请参考 [页面头部配置 API](https://www.nuxtjs.cn/api/pages-head)。
```js
{{ title }}
```
注意:为了避免子组件中的 meta 标签不能正确覆盖父组件中相同的标签而产生重复的现象,建议利用 hid 键为 meta 标签配一个唯一的标识编号。请阅读关于 vue-meta 的更多信息。