赞
踩
对于Vue所构建的单页面应用(SPA)虽然具有用户体验好,渲染性能好,可维护高等优点。但也有一些缺陷,其中只要涉及两点:
因此,就出现了现代化的服务端渲染,也叫同构渲染。就是指服务端构建渲染+客户端构建渲染。
Nuxt.js 是一个基于 Vue.js 生态开发的一个第三方服务端渲染框架,通过它我们可以轻松构建现代化的服务端渲染应用。
服务端渲染同样也存在问题:
Nuxt.js 是一个基于 Vue.js 的服务端渲染应用框架,它可以帮我们轻松的实现同构应用。
Nuxt 提供了两种方式用来创建项目:
mkdir nuxt-app-demo
cd nuxt-app-demo
npm init -y
npm innstall nuxt
"scripts": { "dev": "nuxt" },
Nuxt.js 依据 pages 目录结构自动生成 vue-router 模块的路由配置。
在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录。
你可以通过 vue-router 的子路由创建 Nuxt.js 应用的嵌套路由。
创建内嵌子路由,你需要添加一个 Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。
Warning: 别忘了在父组件( .vue 文件) 内增加 用于显示子视图内容。
可以通过配置文件配置自定义选项
默认布局
自定义布局
Nuxt.js 扩展了 Vue.js,增加了一个叫* asyncData *的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。
在项目开发的过程中,会涉及到一些登录状态的处理。既要客户端可以访问,也要服务端可以访问
login.js
// 仅在客户端加载 js-cookie 包 const Cookie = process.client ? require('js-cookie') : undefined export default { middleware: 'notAuthenticated', name: 'LoginIndex', computed: { isLogin () { return this.$route.name === 'login' } }, data () { return { user: { username: '', email: 'lpzmail@163.com', password: '12345678' }, errors: {} // 错误信息 } }, methods: { async onSubmit () { try { // 提交表单请求登录 const { data } = this.isLogin ? await login({ user: this.user }) : await register({ user: this.user }) // console.log(data) // TODO: 保存用户的登录状态 this.$store.commit('setUser', data.user) // 为了防止刷新页面数据丢失,我们需要把数据持久化 Cookie.set('user', data.user) // 跳转到首页 this.$router.push('/') } catch (err) { // console.log('请求失败', err) this.errors = err.response.data.errors } } } }
store/index.js
注:这里的store目录比较特殊,必须叫store,因为nuxt在发现这个store目录之后会自动加载里面的容器模块
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 字符串转为 JavaScript 对象 const parsed = cookieparser.parse(req.headers.cookie) try { user = JSON.parse(parsed.user) } catch (err) { // No valid cookie found } } // 提交 mutation 修改 state 状态 commit('setUser', user) } }
又称路由中间件,中间件允许定义一个自定义函数运行在一个页面或一组页面渲染之前。
每一个中间件应该放置在middleware/目录。文件名的名称将成为中间件名称,一个中间件接收context作为第一个参数
middleware/authenticated.js
/**
* 验证是否登录的中间件
*/
export default function ({ store, redirect }) {
// If the user is not authenticated
if (!store.state.user) {
return redirect('/login')
}
}
使用方法
export default {
// 在路由匹配组件渲染之前会先执行中间件处理
middleware: 'authenticated',
name: 'EditorIndex'
}
Nuxt中默认情况下query参数的变化不能引起asyncData代码的执行,所以我们可以通过使用watchQuery参数监听到路由的变化,触发asyncData的调用。
使用watchQuery属性可以监听参数字符串的更改。 如果定义的字符串发生变化,将调用所有组件方法(asyncData, fetch, validate, layout, …)。 为了提高性能,默认情况下禁用。
export default {
watchQuery: ['page']
}
如果要在请求的时候统一发送token,则需要添加请求拦截器,获取用户统一token需要拿到store中存储的内容,所以需要通过插件属性获取
在Nuxt配置文件中注册插件:
Nuxt.config.js
module.exports = {
// 注册插件
plugins: [
'~/plugins/request.js', // 波浪线开头表示从根路径触发
]
}
新建文件plugins/request.js
/** * 基于 axios 封装的请求模块 */ import axios from 'axios' // 创建请求对象 export const request = axios.create({ baseURL: 'http://realworld.api.fed.lagounews.com' }) // 通过插件机制获取到上下文对象(query、params、req、res、app、store...) // 插件导出函数必须作为 default 成员 export default ({ store }) => { // 请求拦截器 // Add a request interceptor // 任何请求都要经过请求拦截器 // 我们可以在请求拦截器中做一些公共的业务处理,例如统一设置 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}` } // 返回 config 请求配置对象 return config }, function (error) { // 如果请求失败(此时请求还没有发出去)就会进入这里 // Do something with request error return Promise.reject(error) }) }
markdown-it
Nuxt 在 head 方法里可通过 this 关键字来获取组件的数据,你可以利用页面组件的数据来设置个性化的 meta 标签。
注意:为了避免子组件中的 meta 标签不能正确覆盖父组件中相同的标签而产生重复的现象,建议利用 hid 键为 meta 标签配一个唯一的标识编号
head() {
return {
title: `${this.article.title} - RealWorld`,
meta: [
{
hid: 'description',
name: 'description',
content: this.article.description
}
]
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。