前沿:去年首次使用nuxt框架搭建项目,一个是对于新知识的学习,一个是公司项目需要使用到该框架,任务需求。前期看了下api后,开始着手开发,在使用过程中有疑问再去api文档查找。现在是项目上线后的某一天,作为当事人再次回顾一下事件的整个过程,整理下需要记录在案的一些点,便于有个系统性的了解。
一、根据官网api的安装步骤,根据自己个人的框架喜好初始化一个新项目。
二、大致回顾下项目中常用的几个目录结构:
(1)、assets:资源目录。这个不用说大家都知道的存放项目静态资源文件(如:图片、公共样式等)
(2)、components :组件目录。这个用vue的同僚们也都知道,用来存放项目公共组件的文件。
跟vue项目中一样,可以单独在某个文件中引入使用,也可以注册全局引入;
例如:下面这个组件:container.vue
单个页面引入就不用在这啰嗦了,只稍稍说明下全局使用的,一般是在plugins(下面会讲到这个目录的使用)建一个文件夹如component.js专门用来引入注册components下面的组件为全局组件。
component.js
// 引入组件
import FContainer from '~/components/Container'
// 注册为全局组件
Vue.component('f-container', FContainer)
使用:
(3)、layouts:布局目录。这个目录可就重要了,你可以在这里自定义一个项目的布局文件例如:default.vue来定义整个项目中页面的一个布局,做一些公共操作。
error.vue 还可以在此目录下定制错误页面,相当于一个显示错误的组件。
它用v-if进行判断错误类型,需要注意的是这个错误时你需要在props里进行声明。
页面不存在
应用发生错误异常
首 页
如果你需要自定义一个错误页面的话,可以使用layout重新指定页面,如果不需要的话,就请隐藏或删掉吧。
还可以设置个性布局,感兴趣的可以去api了解下。
(4)、middleware:中间件目录。这个也是skr重要的啦。
它的作用就是:使你自定义的函数在页面渲染之前进行。文件名就作为中间件的名称,收到上下文作为第一个参数:
device.js
// 在每进入一个页面前都会执行这个函数,接收上下文作为参数,这里是判断当前设备是PC还是移动端
export default function (context) {
context.userAgent = context.isServer ? context.req.headers['user-agent'] : navigator.userAgent
let userAgent = context.userAgent
let device = userAgent.match(/Android|webOS|iPhone|iPod|iPad|BlackBerry/i) ? 'phone' :'pc'
return device
}
它也可以是异步的,返回一个promise或者callback
import axios from 'axios'
// 在进入页面前进行ajax请求
export default function ({ route }) {
return axios.post('http://my-stats-api.com', {
url: route.fullPath
})
}
最重要的是要在vue.config.js里面进行配置,不然是不会执行的。
router: {
// 在每个页面渲染前运行device.js中间件逻辑
middleware: 'device'
}
(5)plugins:插件目录
该目录下主要是一些自己写的组件的声明注册、和一些需要使用到的插件框架等(例如elementUI)注入vue实例,然后再进行相关配置就可以在全局使用。
例如:我们上面说到的component.js,在上面我们已经成功引入并将我们自己写的组件注入Vue实例中,然后我们只需要在vue.config.js中配置就可以在页面中使用了。
plugins: [
{
src: '~plugins/components.js',
ssr: true
}
]
注:包括我们引用element还是其他什么框架插件等都可以在这个文件夹下面新建文件引入插件,这样一来项目分布就比较清晰,一目了然。
(6)nuxt.config.js文件:最重要的文件,上面所讲到的几个目录几乎都要在该文件进行配置,否则前面的努力都是白费。
const StyleLintPlugin = require('stylelint-webpack-plugin')
module.exports = {
mode: 'universal',
/*
** 主要用于配置页面的header信息,相当于我们项目开发中index.html页面中header标签内的内容
*/
head: {
title: 'vue组件页面',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1, user-scalable=0' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
],
script: [...]
},
/*
** 页面进度条颜色
*/
loading: { color: '#5cc72c' },
/*
** Build configuration
*/
env: {
_ENV: process.env.NODE_ENV
},
/*
** 全局css 配置
*/
css: [
'~/assets/styles/index.scss'
],
/**
* 路由信息
*/
router: {
// 在每个页面渲染前运行device.js中间件逻辑
middleware: 'device',
linkActiveClass: 'active-link',
// 页面滚动 是否滚到页面开始位置
scrollBehavior: function (to, from, savedPosition) {
return { x: 0, y: 0 }
},
// 扩展路由
extendRoutes (routes, resolve) {
// 为默认路由添加meta信息(根据需求而定)
let customRoute = [
{
name: "enterpriseInfo",
meta: {
logoColor: 'white',
crumbsColor: 'white',
bgColor: 'none'
}
}
]
routes.forEach(route => {
customRoute.forEach(item => {
if (route.name === item.name) {
route.meta = item.meta
}
})
})
}
},
/*
** 引入的插件
*/
plugins: [
{
src: '~plugins/components.js',
ssr: true
}
],
/*
** Nuxt.js modules
*/
modules: [
'@nuxtjs/axios'
],
/*
** Axios 请求配置
*/
axios: {
baseURL: `http://${process.env.HOST || 'localhost'}:${process.env.PORT || 3000}/api`,
browserBaseURL: '/api',
proxy: true,
https: true
},
// 代理配置
proxy: {
'/api': { target: `${process.env._API || 'http://xxxxx.com/Home/Index/'}`, pathRewrite: {'^/api': ''} }
},
/*
** 打包配置
*/
build: {
extend(config, ctx) {
// Run ESLint on save
if (ctx.isDev && ctx.isClient) {
config.module.rules.push({
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
},
plugins: [
new StyleLintPlugin({
// 正则匹配想要lint监测的文件
files: [
'layouts/*.vue',
'pages/**/*.vue',
'pages/**/*.l?(e|c)ss',
'components/**/*.vue',
'components/**/*.l?(e|c)ss',
'assets/styles/*.l?(e|c)ss'
]
})
]
}
}
三、项目过程遇到的问题
1、因为要兼容移动端和PC端所以自然就会有移动端横竖屏检测的问题:
当然方法有很多,但也都各自存在这一些兼容方面的问题,小编已为你整理了一套最佳方案,仅供参考:
// 判断横竖屏
var utils = {
debounce: function(func,delay){
var timer = null
return function(){
var context = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(function(){
func.apply(context,args);
},delay);
}
}
}
var detectRes = document.getElementById('J_detectRes')
var detectData = document.getElementById('J_detectData')
function detectOrient() {
var storage = localStorage // 用于存储我们拿到的值
var data = storage.getItem('J-recordOrientX')
var cw = document.documentElement.clientWidth
var _Width = 0,
_Height = 0
if(!data) {
sw = window.screen.width
sh = window.screen.height
// 2.在某些机型(如华为P9)下出现 srceen.width/height 值交换,所以进行大小值比较判断
_Width = sw < sh ? sw : sh
_Height = sw >= sh ? sw : sh
storage.setItem('J-recordOrientX',_Width + ',' + _Height)
}else {
var str = data.split(',')
_Width = str[0]
_Height = str[1]
}
if(cw === _Width) {
// 竖屏
return
}
if(cw === _Height){
// 横屏
return
}
}
// 3.通过绑定监听resize方法来执行判断事件,并进行函数去抖
window.onresize = utils.debounce(detectOrient,300)
detectOrient()
详细解释参考地址:凹凸实验室
四、打包文件
.nuxt
nuxt.config.js
package-lock.json
package.json
static