移动端vue实现部门结构功能_基于vue-cli3.0构建功能完善的移动端架子,主要功能包括...

本文介绍了基于vue-cli3.0构建的移动端项目,涵盖webpack配置、vw/REM布局、跨域设置、eslint标准、CDN引入、路由设计与登录拦截、axios及API设计等多个方面,详细讲解了如何实现移动端的部门结构功能以及其他关键功能。
摘要由CSDN通过智能技术生成

webpack 打包扩展

css:sass支持、normalize.css、_mixin.scss、_variables.scss

vw、rem布局

跨域设置

eslint设置

cdn引入

路由设计、登录拦截

axios、api 设计

vuex状态管理

webpack 打包扩展

vue-cli3.*后目录结构大改,去除了以往的build,config文件夹,要实现配置的改动在根目录下增加vue.config.js进行配置

css:sass支持、normalize.css、_mixin.scss、_variables.scss

使用的css预处理器是sass,对于css mixin,变量这里做了全局引入,并且引入normalize.css 使HTML元素样式在跨浏览器上表现得的高度一致性 vue.config.js配置

css: {

// 是否使用css分离插件 ExtractTextPlugin

extract: true,

// 开启 CSS source maps?

sourceMap: false,

// css预设器配置项

// 启用 CSS modules for all css / pre-processor files.

modules: false,

sass: {

data: '@import "style/_mixin.scss";@import "style/_variables.scss";' // 全局引入

}

}

}

复制代码

vw、rem布局

对于移动端适配方案使用的是网易新闻的方法, 使用vw + rem布局

/**

750px设计稿

取1rem=100px为参照,那么html元素的宽度就可以设置为width: 7.5rem,于是html的font-size=deviceWidth / 7.5

**/

html {

font-size: 13.33333vw

}

@media screen and (max-width: 320px) {

html {

font-size: 42.667PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 321px) and (max-width:360px) {

html {

font-size: 48PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 361px) and (max-width:375px) {

html {

font-size: 50PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 376px) and (max-width:393px) {

html {

font-size: 52.4PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 394px) and (max-width:412px) {

html {

font-size: 54.93PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 413px) and (max-width:414px) {

html {

font-size: 55.2PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 415px) and (max-width:480px) {

html {

font-size: 64PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 481px) and (max-width:540px) {

html {

font-size: 72PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 541px) and (max-width:640px) {

html {

font-size: 85.33PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 641px) and (max-width:720px) {

html {

font-size: 96PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 721px) and (max-width:768px) {

html {

font-size: 102.4PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 769px) {

html {

font-size: 102.4PX;

font-size: 13.33333vw

}

}

@media screen and (min-width: 769px) {

html {

font-size: 102.4PX;

#app {

margin: 0 auto

}

}

}

复制代码

vue.config.js配置

loaderOptions: {

postcss: {

// 这是rem适配的配置

plugins: [

require('postcss-px2rem')({

remUnit: 100

})

]

}

}

复制代码

开发时跨域设置

devServer: {

open: true, // 启动服务后是否打开浏览器

host: '127.0.0.1',

port: 8088, // 服务端口

https: false,

hotOnly: false,

proxy: 'https://easy-mock.com/' // 设置代理

}

复制代码

配置完后,本地开发环境的axios的baseUrl要写为 '' ,即空字符串。 发布到线上时如果前端代码不是和后台api放在同源下的,后台还需做跨域处理,

eslint standard设置

使用的是JavaScript standard 代码规范,一个好的编码风格它可以帮助减少团队之间的摩擦,代码阅读起来也更加清爽,更加可读性,不要觉得烦,用了都说好。 这是 JavaScript standard 代码规范的全文

自定义配置,在.eslintrc.js里修改,这里是我给出的配置,4个空格缩进,不检查结尾分号,关闭单var 声明,可自行配置

rules: {

'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',

'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',

indent: [

'error',

4,

{

SwitchCase: 1

}

],

semi: 0, // 不检查结尾分号,

// 强制使用单引号

quotes: ['error', 'single'],

// 关闭函数名与后面括号间必须空格规则

'space-before-function-paren': 0,

// 关闭var 声明,每个声明占一行规则。

'one-var': 0

}

复制代码

cdn引入

对于 vue、vue-router、vuex、axios等等这些不经常改动的库、我们让webpack不对他们进行打包,通过cdn引入,可以减少代码的大小、也可以减少服务器的带宽 这里使用的是360的cdn,附上一份公共cdn评测文章 点我

vue.config.js配置

const externals = {

vue: 'Vue',

'vue-router': 'VueRouter',

vuex: 'Vuex',

'mint-ui': 'MINT',

axios: 'axios'

}

const cdn = {

// 开发环境

dev: {

css: [

'https://lib.baomitu.com/mint-ui/2.2.13/style.min.css'

],

js: []

},

// 生产环境

build: {

css: [

'https://lib.baomitu.com/mint-ui/2.2.13/style.min.css'

],

js: [

'https://lib.baomitu.com/vue/2.6.6/vue.min.js',

'https://lib.baomitu.com/vue-router/3.0.1/vue-router.min.js',

'https://lib.baomitu.com/vuex/3.0.1/vuex.min.js',

'https://lib.baomitu.com/axios/0.18.0/axios.min.js',

'https://lib.baomitu.com/mint-ui/2.2.13/index.js'

]

}

}

configureWebpack: config => {

if (isProduction) {

// externals里的模块不打包

Object.assign(config, {

externals: externals

})

} else {

// 为开发环境修改配置...

}

},

chainWebpack: config => {

// 对vue-cli内部的 webpack 配置进行更细粒度的修改。

// 添加CDN参数到htmlWebpackPlugin配置中, 详见public/index.html 修改

config.plugin('html').tap(args => {

if (process.env.NODE_ENV === 'production') {

args[0].cdn = cdn.build

}

if (process.env.NODE_ENV === 'development') {

args[0].cdn = cdn.dev

}

return args

})

}

复制代码

content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=0,minimal-ui,viewport-fit=cover" />

htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>

vuedemo

We're sorry but vuedemo doesn't work properly without JavaScript

enabled. Please enable it to continue.

htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>

复制代码

路由设计、登录拦截

const router = new Router({

routes: [

{

path: '/',

name: 'home',

component: Home,

meta: {

auth: false, // 是否需要登录

keepAlive: true // 是否缓存组件

}

},

{

path: '/about',

name: 'about',

component: () =>

import(/* webpackChunkName: "about" */ './views/About.vue'),

meta: {

auth: true,

keepAlive: true

}

},

{

path: '/login',

name: 'login',

component: () =>

import(/* webpackChunkName: "login" */ './views/login.vue'),

meta: {

auth: false,

keepAlive: true

}

},

{

path: '*', // 未匹配到路由时重定向

redirect: '/',

meta: {

// auth: true,

// keepAlive: true

}

}

]

})

// 全局路由钩子函数 对全局有效

router.beforeEach((to, from, next) => {

let auth = to.meta.auth

let token = store.getters['login/token'];

if (auth) { // 需要登录

if (token) {

next()

} else {

next({

name: 'login',

query: {

redirect: to.path

}

})

}

} else {

next()

}

})

复制代码

在meta中设置是否需要登录以及是否缓存当前组件, 在router.beforeEac路由钩子函数中对登录权限判断,没有登录的跳到登录页面,并且把当前页面传过去,登录后跳回这个页面。

对于页面缓存的在app.vue里进行处理

复制代码

axios、api 设计

对于axios的设计主要是请求拦截器, respone拦截器,以及get,post的二次封装

axios.defaults.timeout = 12000 // 请求超时时间

axios.defaults.baseURL = process.env.VUE_APP_BASE_API

axios.defaults.headers.post['Content-Type'] =

'application/x-www-form-urlencoded;charset=UTF-8' // post请求头的设置

// axios 请求拦截器

axios.interceptors.request.use(

config => {

// 可在此设置要发送的token

let token = store.getters['login/token'];

token && (config.headers.token = token)

Indicator.open('数据加载中')

return config

},

error => {

return Promise.error(error)

}

)

// axios respone拦截器

axios.interceptors.response.use(

response => {

// 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据

// 否则的话抛出错误 结合自身业务和后台返回的接口状态约定写respone拦截器

Indicator.close()

console.log('response', response);

if (response.status === 200 && response.data.code === 0) {

return Promise.resolve(response)

} else {

Toast({

message: response.data.msg,

position: 'middle',

duration: 2000

});

return Promise.reject(response)

}

},

error => {

Indicator.close()

const responseCode = error.response.status

switch (responseCode) {

// 401:未登录

case 401:

break

// 404请求不存在

case 404:

Toast({

message: '网络请求不存在',

position: 'middle',

duration: 2000

});

break

default:

Toast({

message: error.response.data.message,

position: 'middle',

duration: 2000

});

}

return Promise.reject(error)

}

)

/**

* 封装get方法,对应get请求

* @param {String} url [请求的url地址]

* @param {Object} params [请求时携带的参数]

*/

function get (url, params = {}) {

return new Promise((resolve, reject) => {

axios

.get(url, {

params: params

})

.then(res => {

resolve(res.data)

})

.catch(err => {

reject(err.data)

})

})

}

/**

* post方法,对应post请求

* @param {String} url [请求的url地址]

* @param {Object} params [请求时携带的参数]

*/

function post (url, params) {

return new Promise((resolve, reject) => {

axios

.post(url, qs.stringify(params))

.then(res => {

resolve(res.data)

})

.catch(err => {

reject(err.data)

})

})

}

复制代码

为了方便管理api路径,这里把所以请求都放在了api文件夹下,如

import { get, post } from '@/axios/http.js'

function getIndex (params) {

return get('/mock/5cb48c7ed491cd741c54456f/base/index', params)

}

function login(params) {

return post('/mock/5cb48c7ed491cd741c54456f/base/login', params)

}

export {

getIndex,

login

}

复制代码

其他

去除console.log

装uglifyjs-webpack-plugin插件

// 上线压缩去除console等信息

config.plugins.push(

new UglifyJsPlugin({

uglifyOptions: {

compress: {

warnings: false,

drop_console: true,

drop_debugger: false,

pure_funcs: ['console.log'] // 移除console

}

},

sourceMap: false,

parallel: true

})

)

复制代码

设置alias目录别名

在项目中经常会引用各个地方的文件,配置后可以更加方便的引入了

config.resolve.alias

.set('assets', '@/assets')

.set('components', '@/components')

.set('view', '@/view')

.set('style', '@/style')

.set('api', '@/api')

.set('store', '@/store')

复制代码

环境变量和模式

在一个产品的前端开发过程中,一般来说会经历本地开发、测试脚本、开发自测、测试环境、预上线环境,然后才能正式的发布。对应每一个环境可能都会有所差异,比如说服务器地址、接口地址、websorket地址…… 等等。在各个环境切换的时候,就需要不同的配置参数,所以就可以用环境变量和模式,来方便我们管理。

.env # 在所有的环境中被载入

.env.local # 在所有的环境中被载入,但会被 git 忽略

.env.[mode] # 只在指定的模式中被载入

.env.[mode].local # 只在指定的模式中被载入,但会被 git 忽略

复制代码

自定义的变量VUE_APP_开头,两个特殊的变量:

NODE_ENV - 会是 "development"、"production" 或 "test" 中的一个。具体的值取决于应用运行的模式。

BASE_URL - 会和 vue.config.js 中的 baseUrl 选项相符,即你的应用会部署到的基础路径。

如我们定义的.env

NODE_ENV = 'development'

BASE_URL = '/'

VUE_APP_BASE_API = ''

复制代码

.env.production

NODE_ENV = 'production'

BASE_URL = './'

VUE_APP_BASE_API = 'https://easy-mock.com/'

复制代码

在项目中可以用process.env.VUE_APP_*,如process.env.VUE_APP_BASE_API获取到定义的值

全局引入filter

把多个地方用到的过滤器写在一个js里面,复用代码。

// 过滤日期格式,传入时间戳,根据参数返回不同格式

const formatTimer = function(val, hours) {

if (val) {

var dateTimer = new Date(val * 1000)

var y = dateTimer.getFullYear()

var M = dateTimer.getMonth() + 1

var d = dateTimer.getDate()

var h = dateTimer.getHours()

var m = dateTimer.getMinutes()

M = M >= 10 ? M : '0' + M

d = d >= 10 ? d : '0' + d

h = h >= 10 ? h : '0' + h

m = m >= 10 ? m : '0' + m

if (hours) {

return y + '-' + M + '-' + d + ' ' + h + ':' + m

} else {

return y + '-' + M + '-' + d

}

}

}

export default {

formatTimer

}

复制代码

main.js引入

import filters from './filters/index'

// 注入全局过滤器

Object.keys(filters).forEach(item => {

Vue.filter(item, filters[item])

})

复制代码

使用

{{1555851774 | formatTimer()}}

复制代码

vue中使用mock.js

查看我以前写的文章点击我

wepback的可视化资源分析工具插件---webpack-bundle-analyzer

用来分析哪些模块引入了哪些代码,进行有目的性的优化代码

在打包环境中加,使用命令npm run build --report

if (process.env.npm_config_report) {

config.plugins.push(new BundleAnalyzerPlugin())

}

复制代码

代码地址

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值