因为项目需要,使用到nuxt,找了很多资料,然后抄袭 淮城一只猫这位大佬的笔记做的,重复的东西我就不写啦,只是把自己应用中遇到的问题,记录一下,还有一个小demo 放到码云上,感兴趣可以看一下。(里面的接口是真实,可以换成自己的。只是为了让大家用着方便,大佬们不要搞我,小服务经不起)
npx create-nuxt-app <项目名>
或者yarn create nuxt-app <项目名>
npm install -D sass-loader node-sass // 安装SASS预处理器
npm install -s @nuxtjs/style-resources // 安装nuxt.js 样式模块(需要在页面中注入一些变量和mixin而不必每次都导入它们时 )
在nuxt.config.js添加:
export default {
modules: [
'@nuxtjs/style-resources'
],
styleResources: {
scss: './assets/style/variables.scss'
}
}
然后就可以随处直接使用定义过的变量或函数
跟那位大佬有所不同 我这边操作token用的是cookie-universal-nuxt
export default function ({ $axios, redirect, route, app, $router }) {
$axios.onRequest((config) => { //可以在里面设置一下请求头,根据自己项目需要配置
//下面是我设置的token
const token = app.$cookies.get('token')//建议使用cookie-universal-nuxt一个获取cookie的插件 这个可以在服务端使用 ssr渲染有一个很大的问题,就是第一次请求服务端时获取token问题
// add token
if (token) { config.headers.Authorization = token } else {
//当没有token的时候做白名单判断,哪些是可以访问的
const WhiteList = ['/home', '/login', '/register']//白名单
const WhiteNum = WhiteList.filter((item) => {
return item === route.path
})
if (WhiteNum.length === 0) {
return redirect('/login')
}
}
// console.log('请求地址:' + config.url)
})
/**
* 响应
*/
$axios.onResponse((response) => {
// token无效,强制登出 根据后端返回自行更改
// if (response.data.code === 10001) {
// const self = this
// self.$router.push('/login')
// }
})
/**
* 错误
*/
$axios.onError((error) => { // 通过code状态码判断接口是否出错
console.log(error.response.status)
const code = parseInt(error.response && error.response.status)
if (code === 401) { // 需要登录
redirect('/login')
} else if (code === 403) { // 无权限访问
redirect('/home')
}
})
}
然后在nuxt.config.js里面导入。这里没有什么不同接口文件那边有些改变
export default {
plugins: [
'@/plugins/axios'
],
modules: [
// Doc: https://axios.nuxtjs.org/usage
'@nuxtjs/axios',
],
axios: {
proxy: true,
baseURL: 'http://localhost:5000'
},
proxy: {
'/api': {
target: 'http://localhost:5000',
pathRewrite: {
'^/api': '/api'
}
}
}
}
为了方便后期维护接口管理,可以在项目根目录新建/api文件夹,目录下面可以新建一些接口文件:
/api
- `index.js` # 首页接口管理
- `user.js` # 用户接口管理
- `cart.js` # 购物车接口管理
这接口文件做了些许改变
当时请求的数据会被data的对象包着
列如:data:{ id:1 }
但是我只是想传{ id : 1 }就做了一些改动 ,代码如下
user.js
const apiPrefix = process.env.NODE_ENV === 'development' ? '/api' : '/api'
//post请求
export const userLogin = ({ $axios }, data) => {
return new Promise((resolve, reject) => {
resolve($axios.$post(`${apiPrefix}/users/login`, data))
})
}
//get请求
export const userInfo = ({ $axios }) => {
return new Promise((resolve, reject) => {
resolve($axios.$get(`${apiPrefix}/users/current`))
})
}
项目调用
import { userLogin,userInfo } from '~/api/user'
export default {
data(){
return {
formDat:{
name:'',
pwd:''
}
}
}
mounted() {
this.userInfo()
},
methods: {
// 异步加载数据,页面挂载完成后执行
async userInfo() { //get
const self = this;
const data = await userInfo(self);
console.log(data); // 返回接口信息
},
async userLogin() { //post
const self = this;
const data = await userInfo(self,self.formDat);
console.log(data); // 返回接口信息
}
}
}
在/middleware文件夹新建auth.js文件:
export default function ({ app, route, req, store, redirect }) {
//const isClient = process.client Boolean类型 直接在浏览器地址栏上访问会触发(服务端渲染)
//const isServer = process.server Boolean类型 页面内路由跳转会触发(客户端)
//有特殊需求可以根据上面做改变
const WhiteList = ['/home', '/login', '/register'] //白名单
const token = app.$cookies.get('token')
if (token === undefined) { //未登录的时候
const WhiteNum = WhiteList.filter((item) => {
return item === route.path
})
// console.log(WhiteNum.length)
if (WhiteNum.length === 0) {
return redirect('/login')//未登录访问非白名单的时候
}
}
}
这里标注一下哈,有一个坑
nuxt如果不设置根路径显示哪一个页面,有时候会一直在这里刷新,成为死循环,整个浏览器都不好关闭,一直在那里转圈圈
我的解决方法:在pages目录下的index.vue添加默认页面
<template>
<Home />
</template>
<script>
import Home from '~/pages/home/index'
export default {
components: {
Home
}
}
</script>
Nuxt.js 内置引用了 vuex 模块,所以不需要额外安装。
Nuxt.js 支持两种使用 store 的方式,你可以选择使用:
普通方式: store/index.js 返回一个 Vuex.Store 实例
模块方式: store 目录下的每个 .js 文件会被转换成为状态树指定命名的子模块 (当然,index.js 是根模块)
我建了一个根模块和user模块
为了方便数据管理和好的渲染效果在vuex请求和存储全局数据方便各组件使用
在store目录下新建index.js和user.js:
index.js----主要是为了调用nuxtServerInit
user.js----为了方便管理,用户数据存储在这个模块,可以结合自己项目创建符合的模块文件
必须要注意!!!
nuxtServerInit方法必须在/store/index.js里面,放到其他文件不会触发 代码如下
//inde.js
const actions = {
async nuxtServerInit ({ commit }, { app, req }) { // 在地址栏输入地址访问或者刷新的时候触发
// 下面可以根据自己项目更改,这里只是做了一个demo
//原来我是使用jwt解析token 在更改VueX里的用户名,但每个人的token用的可能不一样。我就不再这里放了
const token = app.$cookies.get('token')
if (token) {
req.headers.Authorization = token // 在请求头添加token 我后端是koa2 jwt验证
await commit('user/SET_isLogin', true)
} else {
await commit('user/SET_isLogin', false)
}
}
}
export default {
actions
}
//user.js
export const state = () => ({ // state里面存放的是变量,如果你要注册全局变量,写这里
isLogin: false,
token: '',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', //用了网络上的图片,如有侵权,我麻溜就改
name: '',
roles: ['admin'] //根据需要是否要配置权限
})
const mutations = { // 修改store中的变量的方法,如果你要改变变量的值,就写这(vuex中state中的值不能直接修改)
SET_isLogin (state, value) {
state.isLogin = value
},
SET_token (state, value) {
state.token = value
},
Remove_token (state) {
state.token = ''
},
SET_name (state, value) {
state.name = value
}
}
export default {
namespaced: true, // 命名空间
state, // 这里你用到了哪几个属性就写哪几个,不需要的可以注释掉
// getters,
// actions,
mutations
}
复习一下,过两天就不一定记得这么清楚了。
//先安装svg-sprite-loader
npm i svg-sprite-loader --save-dev
1、在/assets目录下新建/icons/svg
在svg目录下放图标文件
2、在components目录下新建svg-icon.vue
代码如下
<template>
<svg aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
}
},
computed: {
iconName () {
return `#icon-${this.iconClass}`
}
}
}
</script>
3、在plugins/目录下新建文件svg-icon.js
代码如下
import Vue from 'vue'
import SvgIcon from '~/components/svg-icon.vue'
Vue.component('svg-icon', SvgIcon)
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('~/assets/icons/svg', false, /\.svg$/)
requireAll(req)
4、最后在nuxt.config.js文件配置一下
const { resolve } = require('path')//要加上这里要是么有配置会报错
router: {
// base: '/', //设置这里会让svg显示不出来
middleware: 'auth'
},
plugins: [
'@/plugins/element-ui',
'@/plugins/axios',
'~/plugins/svg-icon'
],
build: {
transpile: [/^element-ui/],
/*
** You can extend webpack config here
*/
extend (config, ctx) {
const svgRule = config.module.rules.find(rule => rule.test.test('.svg'))
svgRule.exclude = [resolve(__dirname, 'assets/icons/svg')]
// Includes /assets/svg for svg-sprite-loader
config.module.rules.push({
test: /\.svg$/,
include: [resolve(__dirname, 'assets/icons/svg')],
loader: 'svg-sprite-loader',
options: {
symbolId: 'icon-[name]'
}
})
}
}
一开始使用的时候svg在根路径下可以加载出来,不在根路径下,就加载不出来,检查一下发现路径多加了 “/”,把上面的 base: ‘/’ 注释掉就ok了。如果你的项目base:’/’,感觉可以配置一下webpack
5、在vue文件使用svg
<svg-icon icon-class="article" />
//article为图标文件的文件名
nuxt的params方法传值要新建_id.vue文件才能接受值,感觉挺麻烦的,还要新建页面 ,我这里用的query
//index.vue 传值
this.$router.push({ path: '/serverlist', query: { goods_type: `${goodsType}`,uuid:`${uuid}` } })
//serverlist.vue 接收值
this.$route.query.goods_type
this.$route.query.uuid
npm build //打包
npm start //测试
上传
.nuxt # 打包后的文件
/assets # 能被webpack处理的项目资源
/node_modules # 可以上传package.js文件,之后在npm安装
/plugins # 项目插件
/server # ssr模式的要上传这个文件
/static # 不被webpack处理的静态资源
nuxt.config.js # Nuxt.js配置文件
package.json # npm包管理器文件
部署的时候建议用pm2部署
pm2 start npm --name “project” – run start
名字使用package.json里面的name
服务跑起来之后,在用nginx配置一下就ok啦