項目總結

 

項目總結

app

技術棧

vue+vuex+vue-cli@3.0+stylus+axios+vant-ui


 

一些基本的配置

  • vue-cli3.0中簡化了相應的配置文件,使得項目文件相對而言更加的清爽,配置也變得相對簡單。在項目的目錄文件下建立vue.config.js文件。常見配置以下:
  1. const path = require('path')
  2. module.exports = {
  3. // 基本路徑
  4. publicPath: process.env.NODE_ENV === 'production'
  5. ? '/production-sub-path/'
  6. : '/',
  7. // 輸出文件目錄
  8. outputDir: process.env.NODE_ENV === 'production' ? 'dist' : 'devdist',
  9. // eslint-loader 是否在保存的時候檢查
  10. lintOnSave: true,
  11. /**
  12. 1. webpack配置,see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
  13. **/
  14. chainWebpack: () => {
  15. },
  16. configureWebpack: config => {
  17. if (process.env.NODE_ENV === 'production') {
  18. // 爲生產環境修改配置...
  19. } else {
  20. // 爲開發環境修改配置...
  21. }
  22. config.resolve = { // 配置解析別名
  23. extensions: ['.js', '.vue'],
  24. alias: {
  25. '@': path.resolve(__dirname, './src'),
  26. 'public': path.resolve(__dirname, './public'),
  27. 'components': path.resolve(__dirname, './src/components'),
  28. 'common': path.resolve(__dirname, './src/common'),
  29. 'views': path.resolve(__dirname, './src/views'),
  30. 'store': path.resolve(__dirname, './src/store'),
  31. 'assets': path.resolve(__dirname, './src/assets'),
  32. 'api': path.resolve(__dirname, './src/api'),
  33. 'test': path.resolve(__dirname, './src/test')
  34. }
  35. }
  36. },
  37. // 生產環境是否生成 sourceMap 文件
  38. productionSourceMap: false,
  39. // css相關配置
  40. css: {
  41. // 是否使用css分離插件 ExtractTextPlugin
  42. extract: true,
  43. // 開啓 CSS source maps?
  44. sourceMap: false,
  45. // css預設器配置項
  46. loaderOptions: {
  47. stylus: {
  48. // 全局導入stylus樣式
  49. data: `@import "~@/common/stylus/index.styl";`
  50. }
  51. },
  52. // 啓用 CSS modules for all css / pre-processor files.
  53. modules: true
  54. },
  55. // use thread-loader for babel & TS in production build
  56. // enabled by default if the machine has more than 1 cores
  57. parallel: require('os').cpus().length > 1,
  58. /**
  59. 2. PWA 插件相關配置,see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
  60. */
  61. pwa: {},
  62. // webpack-dev-server 相關配置
  63. devServer: {
  64. open: false, // 編譯完成是否打開網頁
  65. host: '0.0.0.0', // 指定使用地址,默認localhost,0.0.0.0表明能夠被外界訪問
  66. port: 8080, // 訪問端口
  67. https: false, // 編譯失敗時刷新頁面
  68. hot: true, // 開啓熱加載
  69. hotOnly: false,
  70. proxy: null, // 設置代理
  71. overlay: { // 全屏模式下是否顯示腳本錯誤
  72. warnings: true,
  73. errors: true
  74. },
  75. before: app => {
  76. }
  77. },
  78. /**
  79. 3. 第三方插件配置
  80. */
  81. pluginOptions: {}
  82. }

上面一段配置只適用於本身。css


  • css在手機端的樣式 
    根據我的習慣設置項目目錄:我的會在項目的src下設置一個common目錄,而後把全部的css樣式都放到裏面。重置文件通常爲reset.less,全局樣式文件通常爲base.less,字體及顏色目錄文件通常爲variable.less,在項目中要使用到的一些特殊樣式爲mixin.styl,字體圖表樣式爲icon.less,出口問文件爲index.styl。具體參考內容以下:

index.styl文件html

 
  1. @import "./base"
  2. @import "./reset"
  3. @import "./icon"
  4. @import "variable"

reset.stylvue

 
  1. /*移動端css樣式重置,若是要修改全局樣式請在base.styl文件裏面修改*/
  2. html {
  3. font-family: "Helvetica Neue", Helvetica, STHeiTi, sans-serif;
  4. -ms-text-size-adjust: 100%;
  5. -webkit-text-size-adjust: 100%
  6. }
  7. html, body {
  8. -webkit-user-select: none;
  9. user-select: none;
  10. }
  11. html, body, div, object, iframe, applet,
  12. object, h1, h2, h3, h4, h5, h6, p, blockquote,
  13. pre, address, dl, dt, dd, ol, ul, li, table,
  14. caption, tbody, tfoot, thead, tr, th, td,
  15. article, aside, canvas, details, embed, figure,
  16. figcaption, footer, header, menu, nav, output, ruby,
  17. section, summary, time, mark, audio, video, progress {
  18. margin: 0;
  19. padding: 0;
  20. border: 0;
  21. vertical-align: baseline
  22. }
  23. a {
  24. text-decoration: none;
  25. -webkit-touch-callout: none;
  26. background-color: transparent
  27. }
  28. li {
  29. list-style: none
  30. }
  31. article, aside, details, figcaption, figure,
  32. footer, header, main, menu, nav,
  33. section, summary {
  34. display: block
  35. }
  36. audio, canvas, progress, video {
  37. display: inline-block
  38. }
  39. audio:not([controls]) {
  40. display: none;
  41. height: 0
  42. }
  43. [hidden], template {
  44. display: none
  45. }
  46. a:active, a:hover {
  47. outline: 0
  48. }
  49. abbr[title] {
  50. border-bottom: 1px dotted
  51. }
  52. b, strong {
  53. font-weight: bold
  54. }
  55. dfn {
  56. font-style: italic
  57. }
  58. h1 {
  59. font-size: 8.533vw;
  60. margin: 2.859vw 0
  61. }
  62. small {
  63. font-size: 80%
  64. }
  65. sub, sup {
  66. font-size: 75%;
  67. line-height: 0;
  68. position: relative;
  69. vertical-align: baseline
  70. }
  71. sup {
  72. top: -2.13vw;
  73. bottom: -2.13vw
  74. }
  75. sub {
  76. }
  77. img {
  78. border: 0;
  79. -webkit-touch-callout: none;
  80. }
  81. svg:not(:root) {
  82. overflow: hidden
  83. }
  84. figure {
  85. margin: 4.2667vw 10.667vw
  86. }
  87. hr {
  88. -moz-box-sizing: content-box;
  89. box-sizing: content-box;
  90. height: 0
  91. }
  92. pre {
  93. overflow: auto
  94. }
  95. code, kbd, pre, samp {
  96. font-family: monospace, monospace;
  97. font-size: 4.267vw
  98. }
  99. a, button, input, optgroup, select, textarea {
  100. -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  101. }
  102. button, input, optgroup, select, textarea {
  103. color: inherit;
  104. font: inherit;
  105. margin: 0;
  106. -webkit-appearance: none;
  107. outline: none;
  108. line-height: normal
  109. }
  110. button {
  111. overflow: visible
  112. }
  113. button, select {
  114. text-transform: none
  115. }
  116. button, html input[type="button"], input[type="reset"], input[type="submit"] {
  117. -webkit-appearance: button;
  118. cursor: pointer
  119. }
  120. button[disabled], html input[disabled] {
  121. cursor: default
  122. }
  123. button::-moz-focus-inner, input::-moz-focus-inner {
  124. border: 0;
  125. padding: 0
  126. }
  127. input {
  128. line-height: normal
  129. }
  130. input[type="checkbox"], input[type="radio"] {
  131. box-sizing: border-box;
  132. padding: 0
  133. }
  134. input[type="number"]::-webkit-inner-spin-button,
  135. input[type="number"]::-webkit-outer-spin-button {
  136. height: auto
  137. }
  138. input[type="search"] {
  139. -webkit-appearance: textfield;
  140. -moz-box-sizing: content-box;
  141. -webkit-box-sizing: content-box;
  142. box-sizing: content-box
  143. }
  144. input[type="search"]::-webkit-search-cancel-button,
  145. input[type="search"]::-webkit-search-decoration {
  146. -webkit-appearance: none
  147. }
  148. fieldset {
  149. border: 1px solid silver;
  150. margin: 0 2px;
  151. padding: 1.493vw 2.667vw 3.2vw
  152. }
  153. legend {
  154. border: 0;
  155. padding: 0
  156. }
  157. textarea {
  158. overflow: auto
  159. }
  160. optgroup {
  161. font-weight: bold
  162. }
  163. table {
  164. border-collapse: collapse;
  165. border-spacing: 0
  166. }
  167. td, th {
  168. padding: 0
  169. }

base.styl文件webpack

 
  1. // 總體樣式
  2. body, html
  3. line-height: 1
  4. font-weight: 200
  5. font-family: 'PingFang SC', 'STHeitiSC-Light', 'Helvetica-Light', arial, sans-serif
  6. // 清除浮動
  7. .clearfix
  8. display: inline-block
  9. &:after
  10. display: block
  11. content: "."
  12. height: 0
  13. line-height: 0
  14. clear: both
  15. visibility: hidden
  16. // 圖片處理1.5倍像素屏幕1px處理與2倍像素屏幕1px處理
  17. @media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)
  18. .border-1px
  19. &::after
  20. -webkit-transform: scaleY(0.7)
  21. transform: scaleY(0.7)
  22. @media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2)
  23. .border-1px
  24. &::after
  25. -webkit-transform: scaleY(0.5)
  26. transform: scaleY(0.5)

variable.styl文件ios

 
  1. // 顏色定義規範
  2. $color-background = #222
  3. $color-background-d = rgba(0, 0, 0, 0.3)
  4. $color-highlight-background = #333
  5. $color-dialog-background = #666
  6. $color-theme = #ffcd32
  7. $color-theme-d = rgba(255, 205, 49, 0.5)
  8. $color-sub-theme = #d93f30
  9. $color-text = #fff
  10. $color-text-d = rgba(255, 255, 255, 0.3)
  11. $color-text-l = rgba(255, 255, 255, 0.5)
  12. $color-text-ll = rgba(255, 255, 255, 0.8)
  13. //字體定義規範
  14. $font-size-10 = 2.667vw
  15. $font-size-12 = 3.2vw
  16. $font-size-14 = 3.733vw
  17. $font-size-16 = 4.267vw
  18. $font-size-18 = 4.8vw
  19. $font-size-20 = 5.33vw
  20. $font-size-22 = 5.867vw

mixin.styl文件git

 
  1. // 上邊框1px
  2. border-1px($color)
  3. position: relative
  4. &:after
  5. display: block
  6. position: absolute
  7. left: 0
  8. bottom: 0
  9. width: 100%
  10. border-top: 1px solid $color
  11. content: ' '
  12. // 沒有邊框
  13. border-none()
  14. &:after
  15. display: none
  16. // 圖片,3倍和2倍
  17. bg-image($url)
  18. background-image: url($url + "@2x.png")
  19. @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
  20. background-image: url($url + "@3x.png")

值得說明的是字體圖標,項目通常會使用iconfont字體圖標github


 

vuex的使用

  • 目錄結構 
    因爲不多使用到vuex模塊,爲了更加的熟悉vuex模塊,在此記錄:
    web

    1. index.js 
      1. import Vue from 'vue'
      2. import Vuex from 'vuex'
      3. import * as actions from './actions'
      4. import * as getters from './getters'
      5. import mutations from './mutations'
      6. import states from './states'
      7. Vue.use(Vuex)
      8. export default new Vue.Store({
      9. actions,
      10. getters,
      11. state,
      12. mutations
      13. })

    2.state.jsvuex

    1. const state = {
    2. name:''
    3. }
    4. export default states

    3.mutation-types.jsvue-cli

    1. export const SET_NAME = set_name // 修更名字信息(請加上註釋)

    4.mutations.js

    1. import * as type from './mutation-types'
    2. const mutations = {
    3. [type.SET_NAME](state,name){
    4. state.name = name
    5. }
    6. }
    7. export mutations

    5.getters.js

    1. export const name = state => state.name

    6.actions.js

    1. import * as type from './mutation-types'
    2. export const changeName = ({commit},{newName}){
    3. commit(types.SET_NAME, newName)
    4. }
 

 

axiox封裝

 
axiox 的封裝能夠分爲三步,我的喜歡在項目目錄文件夾下創建一個api 文件來專門存放關於api 接口的一些東西
  • http.js 用來專門封裝 axios 的接口設置,通常會和vue-axios使用

    http.js文件

 
  1. import axios from 'axios'
  2. import vueAxios from 'vue-axios'
  3. import Vue from 'vue'
  4. import QS from 'qs'
  5. Vue.use(vueAxios,axios)
  6. // axios 環境設置
  7. if(process.env.NODE_ENV === 'production'){
  8. axios.defaults.baseURL= 'http://prouction.com'
  9. }else if(process.env.NODE_ENV === 'development'){
  10. axios.defaults.baseURL = 'http://development.com'
  11. }else if(process.env.NODE_ENV === 'debug'){
  12. axios.defaults.baseURL = 'http://debug.com'
  13. }
  14. // axios請求超時
  15. axios.defaults.timeout = 10000
  16. // post請求頭
  17. axios.defaults.headers = {
  18. 'X-Requested-With': 'XMLHttpRequest',
  19. 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  20. }
  21. // 請求攔截器
  22. axios.interceptors.request.use(
  23. config=>{
  24. // 每次發送請求以前判斷是否存在token,若是存在,則統一在http請求的header都加上token,不用每次請求都手動添加了
  25. // 即便本地存在token,也有可能token是過時的,因此在響應攔截器中要對返回狀態進行判斷
  26. // const token = store.state.user.token
  27. // token && (config.headers.Authorization = `Bearer ${token}`)
  28. config.data = QS.stringify(config.data)
  29. return config
  30. },
  31. error => {
  32. return Promise.error(error)
  33. })
  34. // 相應攔截器
  35. let errorHandle = (status, other) => {
  36. if (status) {
  37. switch (status) {
  38. /**
  39. * 401: 未登陸
  40. * 未登陸則跳轉登陸頁面,並攜帶當前頁面的路徑
  41. *在登陸成功後返回當前頁面,這一步須要在登陸頁操做。
  42. */
  43. case 401:
  44. // tip('未登陸,請先登陸')
  45. break
  46. /**
  47. * 403 token過時,登陸過時對用戶進行提示,清除本地token和清空vuex中token對象,跳轉登陸頁面
  48. */
  49. case 403:
  50. // tip('登陸過時,請從新登陸')
  51. // setTimeout(() => {
  52. // logout()
  53. // }, 1000)
  54. break
  55. // 404請求不存在
  56. case 404:
  57. // tip('請求的資源不存在')
  58. break
  59. // 其餘錯誤,直接拋出錯誤提示
  60. default:
  61. // tip({
  62. // message: error.response.data.message,
  63. // duration: 1500, // 持續時間
  64. // forbidClick: true
  65. // })
  66. console.log(other)
  67. break
  68. }
  69. }
  70. }
  71. axios.interceptors.response.use(
  72. // 拿到數據200
  73. res => res.status === 200 ? Promise.resolve(res) : Promise.reject(res),
  74. // 未拿到,非200
  75. error => {
  76. if (error.response === undefined) {
  77. console.log('response:' + error.message)
  78. return Promise.reject(error)
  79. // tip('後臺錯誤,請求undfined')
  80. }
  81. errorHandle(error.response.status, error.response.data.message)
  82. return Promise.reject(error.response)
  83. }
  84. )
  85. /**
  86. * 封裝接口調用方法
  87. * @param url:地址
  88. * @param data:傳入參數
  89. * @param type:類型(僅限於get/post)
  90. * @returns {Promise<any>}
  91. * @constructor
  92. */
  93. export function Axios (url, data = {}, type = 'GET') {
  94. return new Promise((resolve, reject) => {
  95. // 執行異步請求
  96. let promise
  97. if (type === 'GET') {
  98. // 準備url的query參數數據
  99. let dataStr = '' // 數據拼接字符串
  100. Object.keys(data).forEach(key => {
  101. dataStr += key + '=' + data[key] + '&'
  102. })
  103. if (dataStr !== '') {
  104. dataStr = dataStr.substring(0, dataStr.lastIndexOf('&'))
  105. url = url + '?' + dataStr
  106. }
  107. // get請求
  108. promise = axios.get(url)
  109. } else {
  110. // 發送post請求
  111. promise = axios.post(url, data)
  112. }
  113. promise.then(response => {
  114. // 成功拿到response的data
  115. resolve(response.data)
  116. }).catch(error => {
  117. reject(console.log(error))
  118. })
  119. })
  120. }
  • base.js 裏面存放的是api接口模塊,全部的接口都存放在裏面:

base.js文件

 
  1. let baseURL = '10.10.21.86'
  2. export nameURL = baseURL + '/name'
  3. export let loginURL = baseURL + '/account/login'
  4. export let guestURL = baseURL + '/account/guest'
  5. export let regURL = baseURL + '/account/reg'
  6. export let accountURL = baseURL + '/home/account'
  7. export let kefuURL = baseURL + '/home/getkefu'

api.js 文件是獲取數據的接口方法模塊:

api.js文件

 
  1. import {Axios} from './http'
  2. import * as url from './base'
  3. esport const getName = ({data})=>Axios(url.nameURL,{data},'POST')

 vuex 的 actions.js 文件裏面能夠直接調用方法從而異步獲取數據的

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息