nuxt 全局css_Nuxt开发经验分享,让你踩少点坑!

说明

本文章基于starter-template模板进行讲解,面向有vue-cli开发经验的宝宝

vue init nuxt-community/starter-template

Nuxt

简单来说,Nuxt就是基于Vue的一个应用框架,采用服务端渲染,让你的SPA应用(Vue)也可以拥有SEO

生命周期

众所周知,Vue的生命周期全都跑在客户端(浏览器),而Nuxt的生命周期有些在服务端(Node),客户端,甚至两边都在:

生命周期流程图,红框内的是Nuxt的生命周期(运行在服务端),黄框内同时运行在服务端&&客户端上,绿框内则运行在客户端

实战经验

1. 红框、黄框内的周期都不存在Window对象

export default {

asyncData() {

console.log(window) // 服务端报错

},

fetch() {

console.log(window) // 服务端报错

},

created () {

console.log(window) // undefined

},

mounted () {

console.log(window) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}

}

}

2. 配置错误页面

你可以通过编辑 layouts/error.vue 文件来定制化错误页面.

页面不存在

应用发生错误异常

首 页

export default {

props: ['error'],

layout: 'blog' // 你可以为错误页面指定自定义的布局

}

3. 自定义Loading页面

nuxt.config.js

module.exports = {

loading: '~components/loading.vue'

}

loading.vue

Loading...

export default {

data: () => ({

loading: false

}),

methods: {

start () {

this.loading = true

},

finish () {

this.loading = false

}

}

}

4. 校验参数

如果校验失败,则自动跳转到错误页面

export default {

validate({ params, query }) {

return /^d+$/.test(params.id) // must be number

}

}

5. Header、Footer等公共组件放哪?

大家都知道,vue-cli入口文件是app.vue,在nuxt开发当中则是**./layout/default.vue**

6. 没有keep-alive

由于是服务端渲染,所以不支持组件的keep-alive,那自然activated、deactivated这两个生命周期也没了

7. 配置插件

所有插件都写在**/plugins目录下,这里以vue-lazyload**为例

plugins/lazy-load.js

import Vue from 'vue'

import VueLazyLoad from 'vue-lazyload'

Vue.use(VueLazyLoad, {

loading: require('~/assets/images/loading.jpg'),

error: require('~/assets/images/error.jpg')

})

nuxt.config.js

module.expors = {

plugins = [

{

src: "~/plugins/lazy-load",

ssr: false

}

]

}

8. 使用Axios,并配置全局拦截器,处理跨域

starter-template模板,推荐使用**@nuxtjs/axios、@nuxtjs/proxy**,不需要在plugins配置

安装依赖

npm install @nuxtjs/axios @nuxtjs/proxy --save

使用、处理跨域

// nuxt.config.js

module.exports = {

modules: [ '@nuxtjs/axios' ], // 不需要加入@nuxtjs/proxy

axios: {

proxy: true,

prefix: '/api', // baseURL

credentials: true,

},

proxy: {

'/api/': {

target: 'http://127.0.0.1:2001', // 代理地址

changeOrigin: true,

pathRewrite: {

'^/api': ''

},

},

}

}

组件中使用

export default {

fetch ({ app }) {

console.log(app.$axios)

},

asyncData ({ app }) {

console.log(app.$axios)

},

created () {

console.log(this.$axios)

}

}

到此为止,我们并不需要在plugins配置axios,但是如果要设置全局拦截器,那么就要新建一个/plugins/axios.js

export default function (app) {

let axios = app.$axios;

// 基本配置

axios.defaults.timeout = 10000

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'

// 请求回调

axios.onRequest(config => {})

// 返回回调

axios.onResponse(res => {})

// 错误回调

axios.onError(error => {})

}

然后在plugins配置它

module.exports = {

plugins = [

{

src: "~/plugins/axios",

ssr: false

},

]

}

9. 默认Meta标签

nuxt.config.js

module.exports = {

head: {

title: 'your project title',

meta: [

{ charset: 'utf-8' },

{ name: 'viewport', content: 'width=device-width, initial-scale=1' }

],

link: [

{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Roboto' }

]

}

}

10. 页面组件特有的Meta标签

export default {

head () {

return {

meta:

[

{

name: 'keywords',

content: '最强王者,今晚吃鸡'

},

]

}

}

}

11. 动态路由的Meta标签填充

游戏详情页面举例子,由于数据是异步获取的,我们需要把数据获取写在asyncData钩子,待数据获取成功才会渲染该页面组件

export default {

async asyncData ({ app, params }) {

let data = await app.$axios.get(`/appinfo/${params.id}`);

return {

appname: data.appinfo.appname

}

},

head () {

return {

meta:

[

{

name: 'keywords',

content: `${this.appname},无限宝石,无限元宝`

},

]

}

}

}

12. 使用Vuex

nuxt自己集成了vuex,所以不需要安装,在/store目录下新建index.js即可使用

import Vuex from 'vuex'

let store = () => new Vuex.Store({

state: {

token: ''

},

mutations: {

setToken (state, token) {

state.token = token

}

}

})

export default store

13. 登录状态?

vue-cli项目中,我们可以用vuex-persistedstate,它可以使vuex的状态持久化,页面刷新都不会丢失,原理当然是localStorage啦!当然我更喜欢用vue-cookies进行保存token,问题来了,nuxt项目怎么保存登录状态呢?当然上面这两种方法我们都可以使用,但是有个问题,由于在created钩子中不存在window对象(获取cookie、localStorage都需要window对象),当你需要判断是否存在token的时候,你必须要在mounted进行操作,这说明页面进来的一瞬间你无法得知是否已经登录了,这会导致显示用户名、组件显示于隐藏都慢半拍

nuxt非常友好,它提供了fetch钩子,还有nuxtServerInit,这两个钩子都运行在服务端并且我们能很快速地操作store

14. fetch的使用

如果页面组件设置了fetch方法,它会在组件每次加载前被调用(在服务端或切换至目标路由之前),此方法需要跟服务端的人员配合

export default {

async fetch ({ app, store, params }) {

let { data } = app.$axios.get('/token');

store.commit('setToken', data.token);

}

}

15. nuxtServerInit

终极无敌方法

import Vuex from 'vuex'

let store = () => new Vuex.Store({

state: {

token: ''

},

mutations: {

setToken (state, token) {

state.token = token

}

},

actions: {

nuxtServerInit({ commit }, { req }) {

let cookie = req.headers.cookie;

// 将cookie转成json对象(自己实现该方法)

let token = cookieparse(cookie).token;

commit('setToken', token);

},

}

})

export default store

16. 封装属于自己的全局方法

let xielikang = function () {

/**

* @method 打印信息方法

* @param {String} msg 信息

*/

let message = function (msg) {

msg && console.log(msg)

}

let otherfn = function (msg) {}

return {

message,

otherfn

}

}

Vue.prototype.$kang= xielikang

组件调用

export default {

created() {

this.$kang.message('小老弟,你怎么回事')

}

}

对了,别忘了在plugins中配置,可以回到第7小节查看配置

17. 全局样式

nuxt.config.js

module.exports = {

css: ['~/assets/stylesheets/main.min.css']

}

18. 使用Element-UI

还是plugins文件夹新建element-ui.js

// 全局引入

import Vue from 'vue'

import ElementUI from 'element-ui'

Vue.use(ElementUI)

// 按需引入

import { Button, Loading, MessageBox } from 'element-ui'

Vue.use(Button)

Vue.prototype.$loading = Loading.service

Vue.prototype.$msgbox = MessageBox

nuxt.config.js

module.exports = {

css: ['element-ui/lib/theme-chalk/index.css'],

plugins: [

{

src: "~/plugins/element",

ssr: true

}

]

}

18. 如何使用sass预处理器

安装依赖

npm install node-sass sass-loader --save

组件中使用(不需要其他的配置了)

19. fetch、asyncData、validate使用范围

只能在页面组件使用,也就是pages目录下的组件,而不是components目录下的组件,要有所区分

20. 传统部署

npm run build && npm run start

21. pm2部署

它允许您永久保持应用程序活跃,无需停机即可重新加载它们,并不需要传统部署的.nuxt文件夹,该部署方法也跟生产环境一样含热更新

npm install pm2 -g

npm run build

pm2 start ./node_modules/nuxt/bin/nuxt-start

22. cookieparse

/*

* @Author: likang xie

* @Date: 2018-09-14 15:56:14

* @Purpose: cookie格式化

*/

let cookieparse = function (cname, req) {

let name = cname + "="

let decodedCookie

if (typeof window === 'undefined') decodedCookie = decodeURIComponent(req.headers.cookie)

else decodedCookie = decodeURIComponent(document.cookie)

let ca = decodedCookie.split(';')

for (let i = 0; i < ca.length; i++) {

let c = ca[i]

while (c.charAt(0) == ' ') {

c = c.substring(1)

}

if (c.indexOf(name) == 0) {

return c.substring(name.length, c.length)

}

}

return ""

}

export default cookieparse

本文到此就结束啦,这是目前踩的坑,如果有错误的地方,请大家指出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值