vue項目實踐@樹洞(二)

書接上文

上一篇粗略地搭建了項目,運行一下,編譯經過,可是控制檯上打出一個紅色錯誤警告!報錯了?!什麼狀況,還沒作事就錯了,來看看什麼錯!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項目實踐@樹洞(一)

vue項目實踐@樹洞(二)

vue項目實踐@樹洞(三)

相關文章
相關標籤/搜索