快捷搜索:  汽车  科技

vue全家桶系列之基本知识点(开箱即用vue全家桶)

vue全家桶系列之基本知识点(开箱即用vue全家桶)"scripts":{ "serve":"vue-cli-serviceserve--open" "stage":"vue-cli-servicebuild--modestaging" "build":"vue-cli-servicebuild" }配置介绍  以 VUE_APP_ 开头的变量,在代码中可以通过 process.env.VUE_APP_ 访问。  比如 VUE_APP_ENV = 'development' 通过process.env.VUE_APP_ENV 访问。  除了 VUE_APP_* 变量之外,在你的应用代码中始终可用的还有两个特殊的变量NODE_ENV 和BASE_URLgitclonehttps://github.com/sun

vue全家桶系列之基本知识点(开箱即用vue全家桶)(1)

作者:花花小仙女

转发链接:https://mp.weixin.qq.com/s/c9uAYkWJu-zvKfELh_3V0A

前言

基于 vue-cli4.0 webpack 4 vant ui sass rem 适配方案 axios 封装,构建手机端模板脚手架,开箱即用,让开发变得更简单。

先夸一下自己,收到了很多人的好评。这次好好整理一文,你们的鼓励就是我前进的动力。

vue全家桶系列之基本知识点(开箱即用vue全家桶)(2)

github:https://github.com/sunniejs/vue-h5-template

Node 版本要求

Vue CLI它需要 Node.js 8.9 或更高版本 (推荐 8.11.0 )。你可以使用 nvm 或nvm-windows 在同一台电脑中管理多个 Node 版本。

本示例 Node.js 12.14.1

启动项目

gitclonehttps://github.com/sunniejs/vue-h5-template.git cdvue-h5-template npminstall npmrunserve目录

  • √ Vue-cli4
  • √ 配置多环境变量
  • √ rem 适配方案
  • √ VantUI 组件按需加载
  • √ Sass 全局样式
  • √ Vuex 状态管理
  • √ Axios 封装及接口管理
  • √ Vue-router
  • √ Webpack 4 vue.config.js 基础配置
  • √ 配置 proxy 跨域
  • √ 配置 alias 别名
  • √ 配置 打包分析
  • √ 配置 externals 引入 cdn 资源
  • √ 去掉 console.log
  • √ splitChunks 单独打包第三方模块
  • √ 添加 IE 兼容
  • √ Eslint Pettier 统一开发规范
✅ 配置多环境变量

package.json 里的 scripts 配置 serve stage build,通过 --mode xxx 来执行不同环境

  • 通过 npm run serve 启动本地 执行 development
  • 通过 npm run stage 打包测试 执行 staging
  • 通过 npm run build 打包正式 执行 production

"scripts":{ "serve":"vue-cli-serviceserve--open" "stage":"vue-cli-servicebuild--modestaging" "build":"vue-cli-servicebuild" }配置介绍

  以 VUE_APP_ 开头的变量,在代码中可以通过 process.env.VUE_APP_ 访问。  比如 VUE_APP_ENV = 'development' 通过process.env.VUE_APP_ENV 访问。  除了 VUE_APP_* 变量之外,在你的应用代码中始终可用的还有两个特殊的变量NODE_ENV 和BASE_URL

在项目根目录中新建.env.*

  • .env.development 本地开发环境配置

NODE_ENV='development' #muststartwithVUE_APP_ VUE_APP_ENV='development'

  • .env.staging 测试环境配置

NODE_ENV='production' #muststartwithVUE_APP_ VUE_APP_ENV='staging'

  • .env.production 正式环境配置

NODE_ENV='production' #muststartwithVUE_APP_ VUE_APP_ENV='production'

这里我们并没有定义很多变量,只定义了基础的 VUE_APP_ENV development staging production变量我们统一在 src/config/env.*.js 里进行管理。

这里有个问题,既然这里有了根据不同环境设置变量的文件,为什么还要去 config 下新建三个对应的文件呢?修改起来方便,不需 要重启项目,符合开发习惯。

config/index.js

//根据环境引入不同配置process.env.NODE_ENV constconfig=require('./env.' process.env.VUE_APP_ENV) module.exports=config

配置对应环境的变量,拿本地环境文件 env.development.js 举例,用户可以根据需求修改

//本地环境配置 module.exports={ title:'vue-h5-template' baseUrl:'http://localhost:9018' //项目地址 baseapi:'https://test.xxx.com/api' //本地api请求地址 APPID:'xxx' APPSECRET:'xxx' }

根据环境不同,变量就会不同了

//根据环境不同引入不同baseApi地址 import{baseApi}from'@/config' console.log(baseApi)✅ rem 适配方案

不用担心,项目已经配置好了 rem 适配 下免仅做介绍:

Vant 中的样式默认使用px作为单位,如果需要使用rem单位,推荐使用以下两个工具:

  • postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 rem
  • lib-flexible 用于设置 rem 基准值
PostCSS 配置

下面提供了一份基本的 postcss 配置,可以在此配置的基础上根据项目需求进行修改

//https://github.com/michael-ciniawsky/postcss-load-config module.exports={ plugins:{ autoprefixer:{ overrideBrowserslist:['Android4.1' 'iOS7.1' 'Chrome>31' 'ff>31' 'ie>=8'] } 'postcss-pxtorem':{ rootValue:37.5 propList:['*'] } } }

更多详细信息:vant

新手必看,老鸟跳过

很多小伙伴会问我,适配的问题。

我们知道 1rem 等于html 根元素设定的 font-size 的 px 值。Vant UI 设置 rootValue: 37.5 你可以看到在 iPhone 6 下 看到 (1rem 等于 37.5px):

<htmldata-dpr="1"style="font-size:37.5px;"></html>

切换不同的机型,根元素可能会有不同的font-size。当你写 css px 样式时,会被程序换算成 rem 达到适配。

因为我们用了 Vant 的组件,需要按照 rootValue: 37.5 来写样式。

举个例子:设计给了你一张 750px * 1334px 图片,在 iphone6 上铺满屏幕 其他机型适配。

  • 当rootValue: 70 样式 width: 750px;height: 1334px; 图片会撑满 iPhone6 屏幕,这个时候切换其他机型,图片也会跟着撑 满。
  • 当rootValue: 37.5 的时候,样式 width: 375px;height: 667px; 图片会撑满 iPhone6 屏幕。

也就是 iphone 6 下 375px 宽度写 CSS。其他的你就可以根据你设计图,去写对应的样式就可以了。

当然,想要撑满屏幕你可以使用 100%,这里只是举例说明。

<imgclass="image"src="https://imgs.solui.cn/weapp/logo.png"/> <style>/*rootValue:75*/ .image{ width:750px; height:1334px; } /*rootValue:37.5*/ .image{ width:375px; height:667px; }</style>✅ VantUI 组件按需加载

项目采 用 Vant 自动按需引入组件 (推荐) 下 面安装插件介绍:

babel-plugin-import 是一款 babel 插件,它会在编译过程中将import 的写法自动转换为按需引入的方式

安装插件

npmibabel-plugin-import-D

在babel.config.js 设置

//对于使用babel7的用户,可以在babel.config.js中配置 constplugins=[ [ 'import' { libraryName:'vant' libraryDirectory:'es' style:true } 'vant' ] ] module.exports={ presets:[['@vue/cli-plugin-babel/preset' {useBuiltIns:'usage' corejs:3}]] plugins } 使用组件

项目在 src/plugins/vant.js 下统一管理组件,用哪个引入哪个,无需在页面里重复引用

//按需全局引入vant组件 importVuefrom'vue' import{Button List Cell Tabbar TabbarItem}from'vant' Vue.use(Button) Vue.use(Cell) Vue.use(List) Vue.use(Tabbar).use(TabbarItem)✅ Sass 全局样式

首先 你可能会遇到 node-sass 安装不成功,别放弃多试几次!!!

目录结构,在 src/assets/css/文件夹下包含了三个文件

├──assets │├──css ││├──index.scss#全局通用样式 ││├──mixin.scss#全局mixin ││└──variables.scss#全局变量

每个页面自己对应的样式都写在自己的 .vue 文件之中

<stylelang="scss">/*globalstyles*/</style> <stylelang="scss"scoped>/*localstyles*/</style>

vue.config.js 配置注入 sass 的 mixin variables 到全局,不需要手动引入 配置$cdn通过变量形式引入 cdn 地址

constIS_PROD=['production' 'prod'].includes(process.env.NODE_ENV) constdefaultSettings=require('./src/config/index.js') module.exports={ css:{ extract:IS_PROD sourceMap:false loaderOptions:{ scss:{ //注入`sass`的`mixin``variables`到全局 $cdn可以配置图片cdn //详情:https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders prependData:` @import"assets/css/mixin.scss"; @import"assets/css/variables.scss"; $cdn:"${defaultSettings.$cdn}"; ` } } } }

在 main.js 中引用全局样式(发现在上面的,prependData 里设置@import "assets/css/index.scss";并没有应用全局样式这里在 main.js 引入)

设置 js 中可以访问 $cdn .vue 文件中使用this.$cdn访问

//引入全局样式 import'@/assets/css/index.scss' //设置js中可以访问$cdn //引入cdn import{$cdn}from'@/config' Vue.prototype.$cdn=$cdn

在 css 和 js 使用

<script>console.log(this.$cdn)</script> <stylelang="scss"scoped>.logo{ width:120px; height:120px; background:url($cdn '/weapp/logo.png')center/containno-repeat; }</style>✅ Vuex 状态管理

目录结构

├──store │├──modules ││└──app.js │├──index.js │├──getters.js

main.js 引入

importVuefrom'vue' importAppfrom'./App.vue' importstorefrom'./store' newVue({ el:'#app' router store render:h=>h(App) })

使用

<script>import{mapGetters}from'vuex' exportdefault{ computed:{ ...mapGetters(['userName']) } methods:{ //Action通过store.dispatch方法触发 doDispatch(){ this.$store.dispatch('setUserName' '真乖,赶紧关注公众号,组织都在等你~') } } }</script>✅ Vue-router

本案例采用 hash 模式,开发者根据需求修改 mode base

注意:如果你使用了 history 模式,vue.config.js 中的 publicPath 要做对应的修改

importVuefrom'vue' importRouterfrom'vue-router' Vue.use(Router) exportconstrouter=[ { path:'/' name:'index' component:()=>import('@/views/home/index') //路由懒加载 meta:{ title:'首页' //页面标题 keepAlive:false//keep-alive标识 } } ] constcreateRouter=()=> newRouter({ //mode:'history' //如果你是history模式需要配置vue.config.jspublicPath //base:'/app/' scrollBehavior:()=>({y:0}) routes:router }) exportdefaultcreateRouter()

更多:Vue Router

✅ Axios 封装及接口管理

utils/request.js 封装 axios 开发者需要根据后台接口做修改。

  • service.interceptors.request.use 里可以设置请求头,比如设置 token
  • config.hideloading 是在 api 文件夹下的接口参数里设置,下文会讲
  • service.interceptors.response.use 里可以对接口返回数据处理,比如 401 删除本地信息,重新登录

importaxiosfrom'axios' importstorefrom'@/store' import{Toast}from'vant' //根据环境不同引入不同api地址 import{baseApi}from'@/config' //createanaxiosinstance constservice=axios.create({ baseURL:baseApi //url=baseapiurl requesturl withCredentials:true //sendcookieswhencross-domainrequests timeout:5000//requesttimeout }) //request拦截器requestinterceptor service.interceptors.request.use( config=>{ //不传递默认开启loading if(!config.hideloading){ //loading Toast.loading({ forbidClick:true }) } if(store.getters.token){ config.headers['X-Token']='' } returnconfig } error=>{ //dosomethingwithrequesterror console.log(error)//fordebug returnPromise.reject(error) } ) //respone拦截器 service.interceptors.response.use( response=>{ Toast.clear() constres=response.data if(res.status&&res.status!==200){ //登录超时 重新登录 if(res.status===401){ store.dispatch('FedLogOut').then(()=>{ location.reload() }) } returnPromise.reject(res||'error') }else{ returnPromise.resolve(res) } } error=>{ Toast.clear() console.log('err' error)//fordebug returnPromise.reject(error) } ) exportdefaultservice接口管理

在src/api 文件夹下统一管理接口

  • 你可以建立多个模块对接接口 比如 home.js 里是首页的接口这里讲解user.js
  • url 接口地址,请求的时候会拼接上 config 下的 baseApi
  • method 请求方法
  • data 请求参数 qs.stringify(params) 是对数据系列化操作
  • hideloading 默认 false 设置为 true 后,不显示 loading ui 交互中有些接口不需要让用户感知

importqsfrom'qs' //axios importrequestfrom'@/utils/request' //userapi //用户信息 exportfunctiongetUserInfo(params){ returnrequest({ url:'/user/userinfo' method:'get' data:qs.stringify(params) hideloading:true//隐藏loading组件 }) }如何调用

//请求接口 import{getUserInfo}from'@/api/user.js' constparams={user:'sunnie'} getUserInfo(params) .then(()=>{}) .catch(()=>{})✅ Webpack 4 vue.config.js 基础配置

如果你的 Vue Router 模式是 hash

publicPath:'./'

如果你的 Vue Router 模式是 history 这里的 publicPath 和你的 Vue Routerbase 保持一直

publicPath:'/app/'

constIS_PROD=['production' 'prod'].includes(process.env.NODE_ENV) module.exports={ publicPath:'./' //署应用包时的基本 URL。vue-router hash 模式使用 // publicPath:'/app/' //署应用包时的基本 URL。 vue-router history模式使用 outputDir:'dist' //生产环境构建文件的目录 assetsDir:'static' //outputDir的静态资源(js、css、img、fonts)目录 lintOnSave:false productionSourceMap:false //如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。 devServer:{ port:9020 //端口号 open:false //启动后打开浏览器 overlay:{ //当出现编译器错误或警告时,在浏览器中显示全屏覆盖层 warnings:false errors:true } //... } }✅ 配置 proxy 跨域

如果你的项目需要跨域设置,你需要打开 vue.config.js proxy 注释 并且配置相应参数

注意:你还需要将 src/config/env.development.js 里的 baseApi 设置成 '/'

module.exports={ devServer:{ //.... proxy:{ //配置跨域 '/api':{ target:'https://test.xxx.com' //接口的域名 //ws:true //是否启用websockets changOrigin:true //开启代理,在本地创建一个虚拟服务端 pathRewrite:{ '^/api':'/' } } } } }

使用 例如: src/api/home.js

exportfunctiongetUserInfo(params){ returnrequest({ url:'/api/userinfo' method:'get' data:qs.stringify(params) }) }✅ 配置 alias 别名

constpath=require('path') constresolve=dir=>path.join(__dirname dir) constIS_PROD=['production' 'prod'].includes(process.env.NODE_ENV) module.exports={ chainWebpack:config=>{ //添加别名 config.resolve.alias .set('@' resolve('src')) .set('assets' resolve('src/assets')) .set('api' resolve('src/api')) .set('views' resolve('src/views')) .set('components' resolve('src/components')) } }✅ 配置 打包分析

constBundleAnalyzerPlugin=require('webpack-bundle-analyzer').BundleAnalyzerPlugin module.exports={ chainWebpack:config=>{ //打包分析 if(IS_PROD){ config.plugin('webpack-report').use(BundleAnalyzerPlugin [ { analyzerMode:'static' } ]) } } }

npmrunbuild✅ 配置 externals 引入 cdn 资源

这个版本 CDN 不再引入,我测试了一下使用引入 CDN 和不使用 不使用会比使用时间少。网上不少文章测试 CDN 速度快,这个开发者可 以实际测试一下。

另外项目中使用的是公共 CDN 不稳定,域名解析也是需要时间的(如果你要使用请尽量使用同一个域名)

因为页面每次遇到<script>标签都会停下来解析执行,所以应该尽可能减少<script>标签的数量 HTTP请求存在一定的开销,100K 的文件比 5 个 20K 的文件下载的更快,所以较少脚本数量也是很有必要的

暂时还没有研究放到自己的 cdn 服务器上。

constdefaultSettings=require('./src/config/index.js') constname=defaultSettings.title||'vuemobiletemplate' constIS_PROD=['production' 'prod'].includes(process.env.NODE_ENV) //externals constexternals={ vue:'Vue' 'vue-router':'VueRouter' vuex:'Vuex' vant:'vant' axios:'axios' } //CDN外链,会插入到index.html中 constcdn={ //开发环境 dev:{ css:[] js:[] } //生产环境 build:{ css:['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'] js:[ 'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js' 'https://cdn.jsdelivr.net/npm/vue-router@3.1.5/dist/vue-router.min.js' 'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js' 'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js' 'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js' ] } } module.exports={ configureWebpack:config=>{ config.name=name //为生产环境修改配置... if(IS_PROD){ //externals config.externals=externals } } chainWebpack:config=>{ /** *添加CDN参数到htmlWebpackPlugin配置中 */ config.plugin('html').tap(args=>{ if(IS_PROD){ args[0].cdn=cdn.build }else{ args[0].cdn=cdn.dev } returnargs }) } }

在 public/index.html 中添加

<!--使用CDN的CSS文件--> <%for(variin htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css){%> <linkhref="<%=htmlWebpackPlugin.options.cdn.css[i]%>"rel="preload"as="style"/> <linkhref="<%=htmlWebpackPlugin.options.cdn.css[i]%>"rel="stylesheet"/> <%}%> <!--使用CDN加速的JS文件,配置在vue.config.js下--> <%for(variin htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js){%> <scriptsrc="<%=htmlWebpackPlugin.options.cdn.js[i]%>"></script> <%}%>✅ 去掉 console.log

保留了测试环境和本地环境的 console.log

npmi-Dbabel-plugin-transform-remove-console

在 babel.config.js 中配置

//获取VUE_APP_ENV非NODE_ENV,测试环境依然console constIS_PROD=['production' 'prod'].includes(process.env.VUE_APP_ENV) constplugins=[ [ 'import' { libraryName:'vant' libraryDirectory:'es' style:true } 'vant' ] ] //去除console.log if(IS_PROD){ plugins.push('transform-remove-console') } module.exports={ presets:[['@vue/cli-plugin-babel/preset' {useBuiltIns:'entry'}]] plugins }✅ splitChunks 单独打包第三方模块

module.exports={ chainWebpack:config=>{ config.when(IS_PROD config=>{ config .plugin('ScriptExtHtmlWebpackPlugin') .after('html') .use('script-ext-html-webpack-plugin' [ { //将runtime作为内联引入不单独存在 inline:/runtime\..*\.js$/ } ]) .end() config.optimization.splitChunks({ chunks:'all' cacheGroups:{ //cacheGroups下可以可以配置多个组,每个组根据test设置条件,符合test条件的模块 commons:{ name:'chunk-commons' test:resolve('src/components') minChunks:3 //被至少用三次以上打包分离 priority:5 //优先级 reuseExistingChunk:true//表示是否使用已有的 chunk,如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了,那么将不会重新生成新的。 } node_vendors:{ name:'chunk-libs' chunks:'initial' //只打包初始时依赖的第三方 test:/[\\/]node_modules[\\/]/ priority:10 } vantUI:{ name:'chunk-vantUI' //单独将vantUI拆包 priority:20 //数字大权重到,满足多个cacheGroups的条件时候分到权重高的 test:/[\\/]node_modules[\\/]_?vant(.*)/ } } }) config.optimization.runtimeChunk('single') }) } }✅ 添加 IE 兼容

之前的方式 会报 @babel/polyfill is deprecated. Please use required parts of core-js andregenerator-runtime/runtime separately

@babel/polyfill 废弃,使用 core-js 和 regenerator-runtime

npmi--savecore-jsregenerator-runtime

在 main.js 中添加

//兼容IE //https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md#babelpolyfill import'core-js/stable' import'regenerator-runtime/runtime'

配置 babel.config.js

constplugins=[] module.exports={ presets:[['@vue/cli-plugin-babel/preset' {useBuiltIns:'usage' corejs:3}]] plugins }✅ Eslint Pettier 统一开发规范

该文件 .prettierrc 里写 属于你的 pettier 规则

{ "printWidth":120 "tabWidth":2 "singleQuote":true "trailingComma":"none" "semi":false "wrap_line_length":120 "wrap_attributes":"auto" "proseWrap":"always" "arrowParens":"avoid" "bracketSpacing":false "jsxBracketSameLine":true "useTabs":false "overrides":[{ "files":".prettierrc" "options":{ "parser":"json" } }] }鸣谢

vue-cli4-config: https://github.com/staven630/vue-cli4-config

vue-element-admin:https://github.com/PanJiaChen/vue-element-admin

mdnice:https://mdnice.com

作者:花花小仙女

转发链接:https://mp.weixin.qq.com/s/c9uAYkWJu-zvKfELh_3V0A

猜您喜欢: