上一篇粗略地搭建了项目,运行一下,编译经过,可是控制台上打出一个红色错误警告!报错了?!什么状况,还没作事就错了,来看看什么错!javascript
'Locale' is defined but never used,就是说Locale这个变量没有使用。在引入UI组件库的时候,个人编辑器已经错误提示了,莫名其妙嘛。并不是这个错抛得莫名其妙,而是这个错不是本身形成的。设想一下,在插件的基础上加了很复杂的逻辑,这时来一个这样莫名其妙的错,是否是很无语。这只是一个假想,绝大多数状况不会是插件带来的。不过,我仍是选择本身撸代码,不去使用所谓的插件,除非使用例如Babel之类的工具。css
除此以外,使用ESLint还会有更多的错误提示。好比,配置postcss.config.js的时候也会给出错误警告,我在上一篇文章给的配置文件的key使用的是双引号,它会提示使用单引号。再好比,ES推荐使用箭头函数,在某些时候没用使用箭头函数也会跑错,特别是使用插件。代码提示会抛出不少语法上的错误提示,若是开了ESLint,那就按着它的提示来培养代码编写习惯吧。html
// 从新给一下postcss.config.js module.exports = { plugins: { 'postcss-import': {}, 'postcss-url': {}, 'postcss-aspect-ratio-mini': {}, 'postcss-write-svg': { uft8: false }, 'postcss-cssnext': {}, 'postcss-px-to-viewport': { viewportWidth: 375, unitPrecision: 3, viewportUnit: 'vw', selectorBlackList: ['.ignore', '.hairlines'], minPixelValue: 1, mediaQuery: false }, 'postcss-viewport-units': { 'silence': true }, 'cssnano': { preset: 'advanced', autoprefixer: false, 'postcss-zindex': false } } }
我不喜欢ESLint之类的语法错误提示,我记得最搞笑的一次,个人编辑器设置的4个空格格式化代码。当时使用的webstorm编辑器,它能够给开发者提供了vue模版,而后生成的代码也是4个空格的规则。但是当我运行代码的时候就抛错了,它要求使用的2个空格,排查了好久才发现。我就在想,若是说相似变量声明没有使用之类的错误抛出是能够接受的,像这2个空格之类的抛错真的有必要吗?固然,这类工具能够本身配置,只是感受默认值很瓜。前端
看下页面,先看下PC下的显示,全部元素的间距大小都很大。切换到iphone 6的环境下,这时就是正常的间距。上面配置的375一倍像素,这时默认的设计。vw是根据浏览器视口宽度进行计算的单位,在pc环境下,浏览器视口变大全部元素也会随着发生变化。LOGO没有设置大小,因此一直保持这个尺寸。vue
试着改变浏览器大小,这时这些元素也会随之变化,这样就无需JS去监听resize事件。这时它的好处,也算得上是缺点:它是根据视窗发生变化的,因此移动端和PC端必须分开。使用rem能够设置一个峰值,当监听到视窗宽度达到峰值就按一倍像素展现再也不缩放,vw则不能。java
小到iPhone 5,大到iPad,效果都还不错,能够下一步了。node
## 拦截封装 ##ios
网络请求是一个必然,我准备使用axios,这个库使用的ES6语法,就很棒。git
# 安装axios npm i -D axios
在src下新建一个apis的目录,作一个简单的拦截封装。这个封装我在别的项目用过,数据请求都没问题,因为这个项目缺乏后端接口的环节,所以暂且只是一个普通的封装。web
// 封装拦截 http.js import axios from 'axios' // 默认参数根据状况配置 // 接口地址环境变量 process.env.VUE_APP_HOST axios.defaults.baseURL = process.env.VUE_APP_HOST axios.defaults.timeout = 10000 axios.defaults['Content-type'] = 'application/json;charset=UTF-8' axios.interceptors.request.use(config => { // 参数处理 return config }, error => { return Promise.reject(error) }) axios.interceptors.response.use(response => { // 响应处理 return response }, error => { // 错误处理 return Promise.reject(error) }) // 请求封装 export function request(url, method = 'get', params = {}) { params = /(get)|(delete)|(head)/ig.test(method) ? { params } : params return axios[method](url, params) } export default axios
// 具体接口文件 api.js // 能够根据业务需求分模块编写,按需引入 import { request } from './http' export const getImgCode = params => request('/utils/public/yzm/get', 'post', params)
按照个人作法,在http.js拦截的时候会统一进行错误处理。为了防止屡次点击按钮触发请求,会在请求开始使用模态loading防止屡次触发请求。我并无彻底拦截错误,封装保持错误的返回,由于有时须要在错误里作后续操做。Promise在catch以后再将同一个错误抛出,在最后还须要catch一次。
暂且作这样的封装,在开始作接口以后,这个封装会改成async/await语法来封装,整个封装结构再从新考虑,这是后话。
## 跨域请求 ##
接口开发和前端开发所在的网络必然会形成跨域问题,这个问题能够经过服务器容许跨域来处理。此外,还能够经过本地的代理来处理这个问题,配置一下vue.config.js。
devServer: { proxy: { "/api": { target: process.env.VUE_APP_PROXY, changeOrigin: true, ws: true, pathRewrite: { "^/api": '' } } } }
接口地址被代理,那么http.js中的baseURL对应的地址是/api。一般码好http.js、vue.config.js这类文件,在其余项目中几乎能够直接使用,因此,我将这两个文件对应的地址改成了环境变量process.env.VUE_APP_HOST、process.env.VUE_APP_PROXY,之后只需修改环境变量就能够了。
在项目根目录,新建三个文件,它们分别表明三个环境,development、production是vue默认的开发环境和生产环境。事实上,至少还须要一个环境,测试版的生产环境。总不可能在本地开发完了就直接打包进生产环境,因而须要先打包上测试服务器,测试完成再部署生产环境。这个环境我用的debug来标识,三个文件分别是:.env.development、.env.production和.env.debug。值得一提的是:这个文件是按文本读取,它的值是字符串类型。
NODE_ENV=development VUE_APP_HOST=/api
NODE_ENV=production VUE_APP_HOST=https://www.production.com
NODE_ENV=production VUE_APP_HOST=https://www.debug.com
关于环境变量官方文档说得很详细,我就不作赘述。环境变量配置好了,给测试服务器打包,还须要在package.json里面增长一个脚本。由于它和build执行的是同一编译环境,增长一个参数就行了:
"debug": "vue-cli-service build --mode debug"
这个debug环境能够增长一些其余处理,好比打包的时候分析包的占比,这在后面打包的时候会提到。
## 样式重置 ##
在开始页面编写以前咱们一般须要重置html元素的默认样式。为了统同样式,还须要申明一些变量来进行控制颜色、字体大小等等,这是全局的。更多的样式是精确到组件,可是主体的标准是来自全局,从而造成本身的UI库。除此以外还会有公共样式,好比1px边线的处理,文字溢出处理等等。
在技术选型的时候,我没有提到动态语言的选择,用哪一种语言并不影响最后的代码。这部分无需多言,根据本身的喜爱进行就行了。
## svg图标 ##
我不主张使用字体图标,这是一个庞大的资源。我在首页引入了vant的tabbar组件,5个图标,有时会出现方格状态(资源未加载完的状况)。字体图标最大的好处,我认为就是它能像字体同样进行大小控制,有得必有失嘛。为了图标在放大缩小的时候不失真,我选择使用字体图标。
做为图标必然会在不少地方使用,因此在components编写一个组件SvgIcon.vue。
<template> <svg :class="svgClass" aria-hidden="true"> <use :xlink:href="iconName"/> </svg> </template> <script> export default { name: 'SvgIcon', props: { iconClass: { type: String, required: true }, className: { type: String, default: '' } }, computed: { iconName() { return `#icon-${this.iconClass}` }, svgClass() { return `svg-icon ${this.className}` } } } </script> <style scoped lang="scss"> .svg-icon { display: block; min-width: 1em; fill: currentColor; overflow: hidden; } </style>
这个组件有两个属性:svg的名字及样式名。样式.svg-icon的fill目的是让svg图标颜色与字体颜色一致,属性里的样式名用于组件自定义样式。值得注意的是,svg文件源码写有fill属性且有颜色值没法修改图标颜色,须要去掉这个属性,或者修改fill=“currentColor” ,或者修改fill=""。
在src下新建一个目录icons,再在这个目录下新建一个目录svg和index.js文件。svg目录存放svg文件,index.js用于加载全部的svg。这不是必要的,能够按需引入SvgIcon组件便可。
import Vue from 'vue' import SvgIcon from '@/components/SvgIcon' Vue.component('svg-icon', SvgIcon) const create = ctx => ctx.keys().map(ctx) create(require.context('./svg', false, /\.svg$/))
在main.js中引入icons。若是package.js中没有配置入口文件,默认是index这个文件,所以直接引入目录icons便可;若是配置有入口文件,那么编译时会先去找这个文件。写全路径自己确定不会有问题。
import '@/icons'
vue内部本来是有svg这个规则,它不太能知足需求,改用svg-sprite-loader。
# 安装svg-sprite-loader npm i --save-dev svg-sprite-loader
在vue.config.js中进行相关配置:
// 引入path const path = require('path') // 修改chainWebpack chainWebpack: config => { // 清除默认svg规则改成svg-sprite-loader const svgRule = config.module.rule('svg') svgRule.uses.clear() svgRule.exclude.add(/node_modules/) svgRule.test(/\.svg$/).use('svg-sprite-loader').loader('svg-sprite-loader').options({ symbolId: 'icon-[name]' }).end() // 修改images规则 const imagesRule = config.module.rule('images') imagesRule.exclude.add(path.join(__dirname, 'src/icons')) config.module.rule('images').test(/\.(png|jpe?g|gif|svg)(\?.*)?$/).end() }
配置完成,在页面上引入:
<svg-icon iconClass="history" className="icon"></svg-icon>
截止到目前,准备工做算是完成,能够开始逻辑代码的编写啦。水平有限,能力通常,有什么不对的地方,欢迎你们不吝赐教。
## 代码仓库 ##
https://gitee.com/IanLew/tree-hole.git
## @树洞系列 ##
vue项目实践@树洞(二)