整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          你要的網頁視差效果設計

          • 者:oscicen
          • 使用技術:HTML / CSS / JavaScript
          • 依賴庫:-
          • 瀏覽器兼容:Chrome, Edge, Firefox, Opera, Safari
          • 響應式:否
          • 源碼鏈接:https://codepen.io/oscicen/pen/zyJeJw

          • 作者:Guilmain Dorian
          • 使用技術:HTML (Pug) / CSS (Less) / JavaScript
          • 依賴庫:-
          • 瀏覽器兼容:Chrome, Edge, Firefox (partial), Opera, Safari
          • 響應式:否
          • 源碼鏈接:https://codepen.io/Craaftx/pen/yQGpwa

          • 作者:Adrian Payne
          • 使用技術:HTML / CSS (SCSS) / JavaScript (Babel)
          • 依賴庫:-
          • 瀏覽器兼容:Chrome, Edge, Firefox, Opera, Safari
          • 響應式:是
          • 源碼鏈接:https://codepen.io/dazulu/pen/VVZrQv

          • 作者:Alex O’Neal
          • 使用技術:HTML / CSS
          • 依賴庫:-
          • 瀏覽器兼容:Chrome, Edge, Firefox, Opera, Safari
          • 響應式:是
          • 源碼鏈接:https://codepen.io/alexoneal/pen/OBqaoe

          • 作者:Sil van Diepen
          • 使用技術:HTML (Pug) / CSS (SCSS)
          • 依賴庫:-
          • 瀏覽器兼容:Chrome, Edge, Firefox, Opera, Safari
          • 響應式:是
          • 源碼鏈接:https://codepen.io/silvandiepen/full/NOboze

          • 作者:Yago Estévez
          • 使用技術:HTML (Pug) / CSS
          • 依賴庫:-
          • 瀏覽器兼容:Chrome, Edge, Firefox, Opera, Safari
          • 響應式:是
          • 源碼鏈接:https://codepen.io/yagoestevez/full/EdgRMX

          • 作者:jakob-e
          • 使用技術:HTML / CSS (SCSS) / JavaScript
          • 依賴庫:
          • 瀏覽器兼容:Chrome, Firefox, Opera, Safari
          • 響應式:是
          • 源碼鏈接:https://codepen.io/jakob-e/pen/ELqeRM

          • 作者:Casey Callis
          • 使用技術:HTML / CSS / JavaScript
          • 依賴庫:jquery.js, parallax.js
          • 瀏覽器兼容:Chrome, Edge, Firefox, Opera, Safari
          • 響應式:是
          • 源碼鏈接:https://codepen.io/caseycallis/full/pwEWxo

          嘍哈嘍 大家好,今天給大家分享一下 創建Vue 工程的小工具 vuecli

          Vue cli 就是 vue的 client,客戶端,是一個命令行工具,能幫我們快速構建一個 vue的標準工程。是官方cli,支持vue2和vue3不同版本。初始化一個vue工程,引入相關依賴。

          首先你本地需要有node環境,包括node和npm。請參考官方文檔安裝node環境。 https://nodejs.org/en/

          你可以在命令行狀態下敲入 如下命令檢查自己是否有node環境


          有了node環境,我們可以通過npm來安裝vuecli,當然,如果你習慣用yarn,請先使用 npm安裝yarn。


          檢查vuecli是否安裝成功


          cli安裝好后,我們可以創建標準的vue工程了。

          命令行敲入 vue create XXX

          其中XXX是你希望的工程名,會在當前目錄下生成同名文件夾的工程文件。


          提示要創建Vue的哪個版本,我們選擇第一項直接回車,就是創建Vue2的默認工程。


          經過一系列提示后,工程就創建好了,我的工程名是home,最后提示我進入home后,運行 yarn serve 或者 npm run serve ,來啟動默認的webpack dev server來運行服務。


          服務啟動完成, 提示我可以訪問 localhost:8080 來訪問我默認創建的這個vue 前端頁面

          我們打開瀏覽器,在地址欄鍵入 http://localhost:8080 后回車

          一切順利的話我們會看到如下頁面


          這個就是我們通過vuecli默認創建出來的一個vue工程了的默認頁面。

          工程目錄結構如下。


          node_modules: 前端工程的依賴庫,node-js的npm會通過package.json 管理 本地包,其中外部依賴庫,會在npm install時,安裝到node-modules下。

          public: 需要靜態發布的資源目錄,默認里面放了一個index.html,這個就是我們開發頁面的基礎html。之后vue創建的動態dom都是掛在到這個頁面上的,如果存在不在npm下管理的第三方插件,可以通過 public這個文件來發布,并在index.html中載入這些外部依賴。

          src:源代碼目錄,其中main.js 就是我們前端程序的主入口。根組件就是從這里最開始實例化的,這個根組件通常就是 App.vue。通常會在App.vue中搭建 站點的主結構,引入vue router,在App.vue下根據url映射決定顯示哪個視圖組件。

          .gitignore: git倉庫的忽略文件,當前目錄下哪些文件不需要git倉庫托管,可以在ignore文件中記下文件名,在git add時會忽略掉那些文件。

          babel.config.js: 因為我們的瀏覽器不一定會認識現在主流的es6語法,所以我們編寫的js代碼,是通過webpack編譯發布的,其中babel就是用來解析es6的,es6也存在不同的版本,可以通過這個文件,配置es6的特性。

          package.json : npm的包描述文件,當前工程的特性在這個文件中

          README.md:本身是個markdown格式的文件,markdown是類似html的格式化文檔,通過特殊字符表達特定格式,一般網站都會默認讀取README.md形成說明頁面。

          除了默認的依賴,我通常會在package.json中添加如下一下,以方便開發。


          其中pug可以以pug語言來書寫html模板,大大減少了不必要的字符,少敲了很多代碼。

          sass是在寫css時,語法和pug高度匹配,非常節省代碼

          這里需要注意的是,node-sass對node-js版本是有對應關系的,如果版本不匹配,工程會有編譯錯誤,請在node-sass的官方網站檢索對應的node-js的版本,下載對應的node-sass。

          相應的,sass-loader與node-sass也是有版本對應關系的,要注意



          之前使用過 Vue 開發后臺、中臺項目,也做過移動端 H5,弄過一點小的前端架構。每做一個項目都會收獲了不一樣的經驗和理解。下面我把這些點點滴滴的經驗總結下來,做一個系列的文章分享和階段性的總結。

          常規操作,先點贊后觀看哦!你的點贊是我創作的動力之一!

          概覽

          問題

          我將從 16 個方面來論述 vue 開發過程中的一些技巧和原理。當然由于篇幅有限,先論述前 8 個問題,下節將完成全系列內容。

          本篇文章將圍繞下列問題進行論述:

          • 如何規范你的 git 提交,并自動生成并提交日志?
          • 如何配置和使用 Sass 和 PUG 提升你的編碼效率?
          • 如何處理你的代碼風格問題,以及如何使用 perttier 與 eslint 解決效率風格兩難問題?
          • 如何管理頁面的路由,如何編寫異步路由?
          • 如何編寫組件,引入組件庫?
          • 如何管理你的資源,如何引入圖標,樣式?
          • 如何封裝你的 axios,管理你的api?
          • 如何使用 mock 模擬你的數據,實現真正意義的前后端分離?

          實踐

          實踐之前:我希望你有如下準備,或者知識儲備。

          了解 npm/yarn/git/sass/pug/vue/vuex/vue-router/axios/mock/ssr/jest 的使用和原理。

          當然上面知識不了解也沒關系哈哈哈,文章中會提到大致用法和作用。

          如何規范 git 提交

          代碼提交記錄是一個很好的代碼修改日志。規范的代碼提交記錄,不管在平時代碼開發維護過程中,還是在定位 bug 或者回退版本來說都是極為重要。

          原理

          兩種做法:

          • 自己手動規范 git 的提交原則或者團隊統一制定。這個靠自覺,好習慣養成之后就沒問題來
          • 使用插件規范,比如下面這種

          為了規范提交,我使用了如下插件:

          • commitizen
          • conventional-changelog
          • cz-conventional-changelog
          • conventional-changelog-cli

          解決方案

          安裝系列插件依賴

          yarn add -D commitizen conventional-changelog cz-conventional-changelog
          復制代碼

          安裝依賴時,要注意是否是生產環境需要的。顯然 commitizen 只在開發環境中使用。-D 只在 dev 環境使用

          配置依賴路徑

          在 package.json 中添加配置

          {
              //...
              "config": {
                  "commitizen": {
                    "path": "./node_modules/cz-conventional-changelog"
                  }
              }
          }
          復制代碼

          在命令行中輸入

          git add -A
          git-cz
          復制代碼

          出現了交互輸入方式,規范你的 commit 輸入格式

          生成 CHANGELOG

          npm i -g conventional-changelog-cli
          復制代碼

          增加一個npm 命令,快速生成日志

          "genlog": "conventional-changelog -p angular -i .github/CHANGELOG.md -s"
          復制代碼

          使用yarn命令生成日志

          yarn genlog
          復制代碼

          自動生成的log

          # 0.1.0 (2019-12-27)
          
          ### Features
          * **git:** 增加commitizen工具規范提交 ([58e3937](https://github.com/suoyuesmile/suo-design-pro/commit/58e39370aa838fd99312f73b37d092ffadc85990))
          復制代碼

          如何管理代碼風格

          較統一的代碼風格利于閱讀,也利于協作。

          原理與解決方案

          使用 eslint 約束基本風格和語法,使用 prettier 自動格式化你的代碼。

          實踐

          安裝 eslint 依賴

          {
              "eslint": "^5.16.0",
              "eslint-config-standard": "^6.2.1",
              "eslint-friendly-formatter": "^2.0.7",
              "eslint-loader": "^2.1.2",
              "eslint-plugin-html": "^2.0.1",
              "eslint-plugin-promise": "^3.5.0",
              "eslint-plugin-standard": "^2.3.1",
              "eslint-plugin-vue": "^5.0.0"
          }
          復制代碼

          使用兩個插件,一個 plugin:vue/essential,一個是 standard。 vue/essential 為了在 vue 里面也可以生效。另一個是 standard。 standard 標準文檔

          使用 recommend 也可以,采用推薦 lint,更加輕量化

          module.exports = {
            root: true,
            env: {
              node: true
            },
            extends: ['plugin:vue/essential', 'standard'],
            rules: {
              quotes: ['error', 'single'],
              indent: ['error', 2, { MemberExpression: 'off' }],
              'arrow-parens': 0,
              'no-loop-func': 2,
              'space-before-function-paren': ['error', 'never'],
              indent: ['error', 2, { SwitchCase: 1 }]
            },
            parserOptions: {
              parser: require.resolve('babel-eslint'),
              ecmaVersion: 2018,
              sourceType: 'module'
            }
          }
          復制代碼

          可以自定義 rules 的規則

          rules 的規則 { 規則名:[是否關閉/規則等級,配置的值,只對部分配置] } indent: ['error', 2, { SwitchCase: 1 }] 兼容 prettier,prettier 會將代碼格式化成 eslint 報錯的情況。 規則等級:0 關閉 1 警告 2 報錯

          使用 prettier

          配置 prettier 文件

          {
            "printWidth": 150,
            "singleQuote": true,
            "trailingComma": "none",
            "semi": false,
            "tabWidth": 2,
            "useTabs": false,
            "bracketSpacing": true,
            "jsxBracketSameLine": false,
            "arrowParens": "always",
            "proseWrap": "preserve",
            "overrides": [
              {
                  "files": ["*.json", ".eslintrc", ".tslintrc", ".prettierrc", ".tern-project"],
                  "options": {
                      "parser": "json",
                      "tabWidth": 2
                  }
              },
              {
                  "files": "*.{css,sass,scss,less}",
                  "options": {
                      "parser": "css",
                      "tabWidth": 2
                  }
              },
              {
                  "files": "*.ts",
                  "options": {
                      "parser": "typescript"
                  }
              },
              {
                  "files": "*.vue",
                  "options": {
                      "parser": "vue"
                  }
              },
              {
                  "files": "*.md",
                  "options": {
                      "parser": "markdown"
                  }
              }
            ]
          }
          復制代碼

          開啟 vscode 自動格式化

          {
            // prettier
            "prettier.singleQuote": true,
            "prettier.semi": false,
            "prettier.tabWidth": 2,
            "[javascript]": {
              "editor.formatOnSave": true,
              "editor.defaultFormatter": "esbenp.prettier-vscode"
            }
          }
          復制代碼

          如何提升編碼效率

          原理與解決方案

          我主要從 3 個方面來做一些編碼效率上的改進

          • 升級你的 vue-cli 減少 webpack 配置的成本
          • 使用 sass,利用里面函數、mixins、變量提升 css 文件的復用
          • 使用 pug,減少 html 的代碼編寫量

          實踐

          vue-cli3+、vue-cli4+ 相比于 vue-cli2+ 最大的改變就是將約定俗稱的配置,全部公共化了,也就是做了一次二次封裝。這樣的好處在于,我們不必要在繁多的配置代碼中尋找需要的配置。

          簡單新建一個配置入口就能操作我們大多數想要的功能。在 root 目錄下新建一個 vue.config.js 文件,作為我們 webpack 的配置文件。

          初始化 vue 配置

          const autoprefixer = require('autoprefixer')
          
          module.exports = {
            publicPath: process.env === 'production' ? '' : '/',
            outputDir: 'dist',
            assetsDir: 'static',
            filenameHashing: true,
            lintOnSave: true,
            runtimeCompiler: false,
            transpileDependencies: [/\/node_modules\/vue-echarts\//, /\/node_modules\/resize-detector\//],
            productionSourceMap: false
          }
          復制代碼

          簡單的配置完成后,我們引入一個 sass 工具用于編寫 sass文件

          用法見 sass 參考資料!

          使用 Sass

          安裝與使用

          yarn add -D sass sass-loader
          復制代碼

          如何處理樣式

          在 assets 目錄中建立一個 styles 文件專門來存放樣式文件,新增入口index.scss文件,便于 JavaScript 引入,增加 utils.scss、reset.scss、varibles 文件。

          這些樣式工具都是為了提升我們 scss 開發效率,具有暢快的開發體驗!

          使用 varibles 變量文件

          為了提升我們代碼的可讀性,復用性。使用 sass 變量必不可少。

          還有一點就是利于全局修改樣式,如果需要更換皮膚這個功能,我們只需要更改全局的主題色,即可更換主題,那樣更加方便。

          // 主題色
          $color-red: #ff3333;
          $color-purple: #ff33a9;
          $color-orange: #ff8833;
          $color-blue: #3377ff;
          
          // 文字色
          $color-black: #000;
          $color-dark: #333;
          $color-deep: #555;
          $color-pl: #999999;
          $color-weak: #B3B3B3;
          $color-white: #fff;
          
          // 背景色
          $bg-bar: #F9F9F9;
          $bg-page: #F3F3F3;
          $bg-page-light: #F9F9F9;
          復制代碼

          使用變量之后,sass 文件不會直接生效,至少在 vue 文件 里面是訪問不到的。 需要在 vue.config.js 里面增加如下配置。

          module.exports = {
              // ...
              css: {
                  sourceMap: true,
                  loaderOptions: {
                      sass: {
                          prependData: `
                  @import "@/assets/styles/variable.scss";
                  `
                      }
                  }
              }
          }
          復制代碼

          覆蓋默認樣式

          常規操作, 引入 reset.scss 將默認樣式覆蓋掉

          /* http://meyerweb.com/eric/tools/css/reset/
             v2.0 | 20110126
             License: none (public domain)
          */
          
          html, body, div, span, applet, object, iframe,
          h1, h2, h3, h4, h5, h6, p, blockquote, pre,
          a, abbr, acronym, address, big, cite, code,
          del, dfn, em, img, ins, kbd, q, s, samp,
          small, strike, strong, sub, sup, tt, var,
          b, u, i, center,
          dl, dt, dd, ol, ul, li,
          fieldset, form, label, legend,
          table, caption, tbody, tfoot, thead, tr, th, td,
          article, aside, canvas, details, embed,
          figure, figcaption, footer, header, hgroup,
          menu, nav, output, ruby, section, summary,
          time, mark, audio, video {
          	margin: 0;
          	padding: 0;
          	border: 0;
          	font-size: 100%;
          	font: inherit;
          	vertical-align: baseline;
          }
          /* HTML5 display-role reset for older browsers */
          article, aside, details, figcaption, figure,
          footer, header, hgroup, menu, nav, section {
          	display: block;
          }
          body {
          	line-height: 1;
          }
          ol, ul {
          	list-style: none;
          }
          blockquote, q {
          	quotes: none;
          }
          blockquote:before, blockquote:after,
          q:before, q:after {
          	content: '';
          	content: none;
          }
          table {
          	border-collapse: collapse;
          	border-spacing: 0;
          }
          
          html, body {
            width: 100%;
            height: 100%;
            overflow: auto;
            margin: 0;
            scroll-behavior: smooth;
            -webkit-overflow-scrolling: touch;
          }
          復制代碼

          使用樣式工具集

          有時候我們發現,光是引入變量還不夠,變量工具只能允許我們在 css 類文件中使用。假如我想著模版中直接使用樣式,有沒有更快的方案呢?

          當然有的,我們可以自定義一個常用的樣式工具集。設置一些背景顏色、字體顏色、盒子模型中的常規操作。

          要是有設計規范更好哦,我也是常常向設計師提出要求,一定要制定出一套產品的設計規范。

          // utils 工具
          // 顏色
          .bg-red {background-color: $color-red!important;}
          .bg-purple {background-color: $color-purple!important;}
          .bg-orange {background-color: $color-orange!important;}
          .bg-blue {background-color: $color-blue!important;}
          .color-red {color: $color-red!important;}
          .color-purple {color: $color-purple!important;}
          .color-orange {color: $color-orange!important;}
          .color-blue {color: $color-blue!important;}
          .text-black {color: #000;}
          .text-dark {color: #333;}
          .text-deep {color: #555;}
          .text-weak {color: #B3B3B3;}
          .text-white {color: #fff;}
          
          // 字體
          .f10 {font-size: 10px;}
          .f12 {font-size: 12px;}
          .f14 {font-size: 14px;}
          .f15 {font-size: 15px;}
          .f17 {font-size: 17px;}
          .f20 {font-size: 20px;}
          .f24 {font-size: 24px;}
          
          // 文字對齊
          .tl {text-align: left;}
          .tc {text-align: center;}
          .tr {text-align: right;}
          
          // 浮動與清除浮動
          .fl {float: left;}
          .fr {float: right;}
          .fix {*zoom: 1;}
          .fix:after{display:table; content:''; clear:both;}
          
          // 顯示
          .dn{display:none;}
          .di{display:inline;}
          .db{display:block;}
          .dib{display:inline-block;}
          .dt{display:table;}
          div.dib{*display:inline; *zoom:1;}
          .vm {vertical-align: middle;}
          .vib {display:inline-block; vertical-align: middle;}
          
          // 定位
          .pr {position: relative;}
          .pa {position: absolute;}
          .pf {position: fixed;}
          
          // 盒子模型
          .ml4 {margin-left: 4px;}
          .mr4 {margin-right: 4px;}
          .mt4 {margin-top: 4px;}
          .mb4 {margin-bottom: 4px;}
          .ml8 {margin-left: 8px;}
          .mr8 {margin-right: 8px;}
          .mt8 {margin-top: 8px;}
          .mb8 {margin-bottom: 8px;}
          .ml12 {margin-left: 12px;}
          .mr12 {margin-right: 12px;}
          .mt12 {margin-top: 12px;}
          .mb12 {margin-bottom: 12px;}
          .ml16 {margin-left: 16px;}
          .mr16 {margin-right: 16px;}
          .mt16 {margin-top: 16px;}
          .mb16 {margin-bottom: 16px;}
          .ml20 {margin-left: 20px;}
          .mr20 {margin-right: 20px;}
          .mt20 {margin-top: 20px;}
          .mb20 {margin-bottom: 20px;}
          .ml24 {margin-left: 24px;}
          .mr24 {margin-right: 24px;}
          .mt24 {margin-top: 24px;}
          .mb24 {margin-bottom: 24px;}
          
          .ml10 {margin-left: 10px;}
          .mr10 {margin-right: 10px;}
          .mt10 {margin-top: 10px;}
          .mb10 {margin-bottom: 10px;}
          .ml15 {margin-left: 15px;}
          .mr15 {margin-right: 15px;}
          .mt15 {margin-top: 15px;}
          .mb15 {margin-bottom: 15px;}
          
          // 按鈕禁用
          .disabled{outline:0 none; cursor:default!important; opacity:.4; filter:alpha(opacity=40); -ms-pointer-events:none; pointer-events:none;}
          復制代碼

          增加樣式入口文件

          最后一步,新建一個入口文件,將樣式工具類全部導入進來,供主程序引入。

          // index.scss 文件
          // @import './varibles.scss'
          @import './reset.scss';
          @import './utils.scss';
          復制代碼

          varibles.scss vue 配置中引入,這里無需引入

          在 main.js 中直接引入 index.scss

          import '@/assets/styles/index.scss'
          復制代碼

          vue 中寫樣式要注意哪些方面,有哪些技巧呢?

          避免全局污染

          在頁面中寫 css/scss 加上 scoped,scoped 的功能就是使頁面的樣式是局部的,不讓影響其他頁面的樣式。

          bem 規范

          我們大多數人時候會遇到問題,樣式嵌套太多了怎么命名

          BEM是塊(block)、元素(element)、修飾符(modifier)的簡寫,由 Yandex 團隊提出的一種前端 CSS 命名方法論。

          名字太長易讀性太差

          .cardbox {
              .cardbox-card {
                  .cardbox-card-wrapper
                      .cardbox-card-wrapper-header {
                          .cardbox-card-wrapper-header-title {
                              // ...
                          }
                      }
                      .cardbox-card-wrapper-body{
                          .cardbox-card-item {
                              .cardbox-card-item-title {
                                  // ...
                              }  
                        }
                    }
                  }
              }
          }
          復制代碼

          bem 使用方式

          block-name__element-name--color

          • 區分塊,子元素,修飾元素
          • 塊,頁面中獨立的單元
          • 子元素,塊里面的兒子 card__item 使用 __ 連接
          • 子元素長命名使用 - 連接
          • 修飾(易變的)card__item--warning 使用 --

          我們使用 bem 改造樣式

          .cardbox {
              &__header {
                  &__title {
                      //...
                  }
              }
              &__body {
                  &__item {
                      &__title {
                          //...
                      }
                  }
              }
          }
          復制代碼

          bem 一般推薦子元素嵌套盡量在2-3層以內

          但是我們發現樣式子元素嵌套有點多,使用了兩重子元素嵌套。

          大致原理是嘗試分離父子元素的關系,把卡片本身當作一個塊看待。

          下面來試著去減少嵌套:

          .cardbox {
              &__header {
                  &__title {
                      //...
                  }
              }
              &__body {
                  .card {
                      &__title {
                          //...
                      }
                  }
              }
          }
          復制代碼

          現在編寫樣式效率提高也更加規范了,那么編寫 HTML 也是有很多累贅的代碼。

          比如大多數標簽都是前開后閉的。通過 pug 我們可以省略很多字符的敲打,下面我們談談如何使用 pug 編寫模版。

          當然喜歡哪種 HTML 編寫風格見人見智啦,我自己更加傾向 pug,那種縮進和簡潔的表達,有種在寫 scss 的感覺。

          如何使用 pug

          類似 sass,首先安裝 pug 和 pug 的 loader

          yarn add -D pug pug-html-loader pug-plain-loader
          復制代碼

          完成配置

          module.exports = {
            // ...
            chainWebpack: (config) => {
              config.module
                .rule('pug')
                .test(/\.pug$/)
                .use('pug-html-loader')
                .loader('pug-html-loader')
                .end()
            }
          }
          復制代碼

          編寫 pug 代碼

          使用 scss 工具與 pug 完美搭配,少寫很多代碼

          // 登陸
          <template lang="pug">
            .login
              h1.login__title.ml15 注冊/登陸
              .login__form.mt15.ml15
                van-field.login__form__input(placeholder="輸入手機號" v-model="phone")
                .login__form__protocol.mt15
                  .login__form__protocol__tips.dib.text-weak 注冊或登錄即表示同意
                  .login__form__protocol__name.dib.color-orange 《用戶協議》
                app-button.mt15(size="large"
                  theme="orange"
                  :disabled="phone.length !== 11"
                  @click="handleSubmit"
                ) 下一步
          </template>
          復制代碼

          我們已經引入了樣式,接下來我將談談其他資源的引入

          如何管理你的資源

          原理與解決方案

          我暫時把資源分為下面幾種

          • 字體
          • ICON
          • 圖片
          • 樣式 把他們各自新建一個目錄,都放在 assets 目錄下面分門別類,供其他地方調用。 使用 alias 更好重命名,使之更便捷的訪問到。

          增加 vue.config.js 配置 ,設置assets別名

          const path = require('path')
          function resolve(dir) {
            return path.join(__dirname, dir)
          }
          module.exports = {
            //...
            chainWebpack: (config) => {
              config.resolve.alias.set('@', resolve('src')).set('@assets', resolve('src/assets'))
            }
          }
          復制代碼

          ICON

          引入 iconfont

          1. iconfont 阿里圖標項目中下載,將整個項目圖標包一起下載下來
          1. 引入 iconfont 樣式 需要下面四個文件
          • iconfont.eot
          • iconfont.ttf
          • iconfont.woff
          • iconfont.woff2
          1. 項目中引入 iconfont 讓 icon 組件化
          <template>
            <i class="iconfont" v-on="$listeners" :class="name"></i>
          </template>
          
          <script>export default {
            props: {
              name: String
            }
          }</script>
          
          <style lang="scss" scoped>.iconfont {
            font-size: 16px;
            color: $color-icon;
          }</style>
          復制代碼

          引入圖片作為 ICON

          讓圖片組件化,我們再來寫一個 img 組件

          <template lang="pug">
            img(
              :src="require(`@/assets/images/${name}.png`)"
              v-bind="$attrs"
              v-on="$listeners"
              :style="{'width': width ? width + 'px' : size + 'px', 'height': height ? height + 'px' : size + 'px' }")
          </template>
          <script>
          export default {
            name: 'app-img',
            props: {
              name: {
                type: String,
                default: ''
              },
              size: {
                type: Number,
                default: 16
              },
              width: {
                type: Number,
                default: 0
              },
              height: {
                type: Number,
                default: 0
              }
            }
          }
          </script>
          復制代碼

          如何管理你的路由

          原理與解決方案

          使用 vue-router,使用import() 生成異步路由,只有在訪問時候才會加載模塊。

          為什么使用 import() 會異步加載模塊?

          MDN:在您希望按照一定的條件或者按需加載模塊的時候,動態import() 是非常有用的。而靜態型的 import 是初始化加載依賴項的最優選擇,使用靜態 import 更容易從代碼靜態分析工具和 tree shaking 中受益。

          說白了就是起到一個按需加載的目的。現在大多數實現的按需加載,基本都是依賴 import() 這個方法。

          安裝 vue-router

          yarn add vue-router
          復制代碼

          安裝完 router,在編寫 router 先創建頁面

          新建一個空頁面

          src 目錄下新增 views 目錄存放頁面文件。創建 index 目錄和 home 頁面

          <template lang="pug">
            .home 首頁
          </template>
          
          <script>export default {
          
          }</script>
          <style lang="scss" scoped>
          </style>
          復制代碼

          編寫路由

          const routes = [
              {
                  // 首頁
                  path: '/',
                  name: 'index',
                  redirect: '/home',
                  component: App,
                  children: [
                      {
                          // 首頁
                          path: 'home',
                          name: 'home',
                          // 路由懶加載
                          component: () =>
                              import(
                                  /* webpackChunkName: "index" */ '../views/index/home.vue'
                              )
                      }
                  ]
              }
          ]
          Vue.use(VueRouter)
          
          const router = new VueRouter({
              mode: 'history',
              routes: routes,
              base: process.env.BASE_URL,
              props: true
          })
          
          export default router
          復制代碼

          為了消除 # 顯得路徑更加好看簡潔,我們采用 history 模式,但是 history 模式有個問題就是,異步路由沒有緩存在頁面中,第一次進入頁面會找不到

          在 vue.config.js 中增加配置,開發環境可以訪問到,恢復正常

          module.exports = {
            // ...
            devServer: {
              historyApiFallback: true
            }
          }
          復制代碼

          關于路由還有很多可以研究到地方,可以自行研究哦!

          組件化開發

          原理與解決方案

          一般來說,我們根據組件的復用度,分給基礎(公共)組件和業務組件。

          為了節省時間,快速開發,這里基礎組件大部分引用開源組件。當然不能直接就用哦。

          一般要進行二次封裝,也就是高階組件開發。

          1. 通過修改和覆蓋當前組件的樣式來達到修改樣式的作用。
          2. 通過攔截事件來更改js的邏輯。

          下面我們先引入 vant 組件

          實踐

          引入 vant

          yarn add vant
          復制代碼

          對基礎組件進行二次封裝和改造

          下面 7 步來寫好一個公共組件

          1. 新建一個 components 目錄來存放基礎組件
          2. 基礎組件命名為 app-xxx 或 appXxx,新建一個 app-button 目錄,新建 index.vue
          3. 根據設計稿設計和編寫組件

          編寫組件之前首先要設計組件,根據組件的不變性和可變性原則編寫。不變性是組件的核心,可變性根據參數對組件對相關部分進行調節,實現可選擇的功能。

          1. 實現組件
          <template lang="pug">
            div.dib
              van-button.btn(
                @click="$emit('click')"
                :class="getClass" v-bind="$attrs"
                :style="{'width': size === 'large' ? '345px': '', 'backgroundColor': getBgColor, borderColor: getBgColor, color: getBgColor}")
                slot
          </template>
          
          <script>import { Button } from 'vant'
          import Vue from 'vue'
          import { getColor } from '@/utils'
          Vue.use(Button)
          
          export default {
            name: 'app-button',
            props: {
              type: {
                type: String,
                default: 'primary'
              },
              theme: {
                type: String,
                default: 'blue'
              },
              size: {
                type: String,
                default: ''
              }
            },
            computed: {
              getClass() {
                if (!this.type) {
                  return ''
                }
                return `app-btn--${this.type}`
              },
              getBgColor() {
                if (!this.theme) {
                  return ''
                }
                return getColor(this.theme)
              }
            }
          }</script>
          
          <style lang="scss" scoped>
          .app-btn  {
            ::v-deep &--primary {
              padding: 8px 30px;
              height: 40px;
              border-radius: 4px;
              font-size: 15px;
              font-weight: 400;
              line-height: 19px;
              color: white!important;
            }
            ::v-deep &--minor {
              padding: 5px 10px;
              height: 26px;
              border-radius: 14px;
              font-size: 12px;
              font-weight: 400;
              line-height: 16px;
              background-color: #fff!important;
            }
            ::v-deep &--rect {
              padding: 5px px;
              height: 49px;
              font-size: 14px;
              color: white!important;
            }
          }
          </style>
          復制代碼

          ::v-deep 樣式深覆蓋,scoped 情況下覆蓋組件樣式,不改變其樣式

          1. 寫好基礎組件 README,為什么要寫文檔呢?如果多人開發同一個項目,基礎組件會被其他人引用。方便其他人使用,所以要寫文檔。

          一句話言:只要可能被其他人用的公共方法和組件,注釋或文檔是很重要的,對自己的代碼負責哈。

          其他用法參照 vant

          1. 全局引用,基礎組件許多頁面都會用到,將其設置成全局組件,其他地方就不必再引用了哦。

          新建一個文件 global 存放全局組件注冊,在 main.js 引入

          import Vue from 'vue'
          import appButton from '@/components/app-button'
          Vue.component('app-button', appButton)
          復制代碼
          1. 寫好 demo,即使暫時不寫單元測試,也要寫好一個 demo,使之能正常的運行

          添加 demo 頁面和路由

          <template lang="pug">
            div(class="base")
              // 按鈕組件
              app-button.mt4(theme="blue") 確認支付
              app-button(theme="orange") 確認支付
              app-button(theme="purple") 確認支付
              app-button.mt4(theme="red") 確認支付
              app-button(theme="grey") 確認支付
              app-button.mt4(theme="blue" size="large") 修改地址
              app-button.mt4(theme="orange" size="large") 修改地址
              app-button.mt4(theme="purple" size="large") 修改地址
              app-button.mt4(theme="red" size="large") 修改地址
              app-button.mt4(theme="grey" size="large") 修改地址
              app-button.mt4(theme="blue" type="minor") 確認收貨
              app-button(theme="orange" type="minor") 確認收貨
              app-button(theme="purple" type="minor") 確認收貨
              app-button(theme="red" type="minor") 修改地址
              app-button(theme="grey" type="minor") 修改地址
              app-button.mt4(theme="blue" type="rect") 確認收貨
              app-button(theme="orange" type="rect") 確認收貨
              app-button(theme="purple" type="rect") 確認收貨
              app-button(theme="red" type="rect") 修改地址
              app-button(theme="grey" type="rect") 修改地址
          </template>
          <script>export default {
          }</script>
          <style lang="scss">
          </style>
          復制代碼

          實現效果

          如何封裝請求

          原理與解決方案

          基本上就是對 axios 的封裝,封裝主要有兩個目的。

          • 修改一些基礎的配置:請求地址,超時,其他的雜七雜八的
          • 統一操作:統一處理錯誤,統一處理請求參數和格式,響應參數和格式。統一處理 message,統一攔截掛載等等。

          網上已經有很多類似的文章了, 我這里給出我常用的封裝方案。

          實踐

          根據不同環境設置請求地址

          // .env-default.js 文件
          // 不同環境訪問不同的路徑
          const api = {
            develop: 'http://xxxx:8080',
            mock: 'http://xxxx',
            feature: 'http://xxxx',
            test: 'http://xxxx',
            production: 'http://xxxx'
          }
          
          export const baseURL = api[process.env.NODE_ENV || 'dev']
          復制代碼

          因為每個人開發環境,mock環境不一定相同,這個文件建議 gitignore忽略掉。模版可以寫在 readme 文檔中,啟動項目時加入文件。

          新建一個 utils 工具

          我們現在將 axios 封裝成我們自己需要的配置,然后定義四個常用的請求方法供調用

          // utils/http.js 文件
          import axios from 'axios'
          import { baseURL } from '../../.env-defalut.js'
          
          // axios 配置
          const defaultBaseUrl = 'http://localhost:8080/'
          // 默認超時時間
          axios.defaults.timeout = 15000
          // 數據接口域名統一配置.env
          axios.defaults.baseURL = baseURL || defaultBaseUrl 
          
          // http request 攔截器
          axios.interceptors.request.use(
            (config) => {
              config.headers = {
              }
              return config
            },
            (err) => {
              return Promise.reject(err)
            }
          )
          
          // http response 攔截器
          axios.interceptors.response.use(
            (response) => {
              return response
            },
            (error) => {
              const data = error.response.data
              return Promise.reject(data || error)
            }
          )
          
          export default axios
          
          /**
           * fetch 請求方法
           * @param {*} url
           * @param {*} params
           */
          export function fetch(url, params = {}) {
            return new Promise((resolve, reject) => {
              axios
                .get(url, {
                  params: params
                })
                .then((response) => {
                  resolve(response.data)
                })
                .catch((err) => {
                  reject(err)
                })
            })
          }
          
          /**
           * post 請求方法,發送數據格式 json
           * @param {*} url
           * @param {*} data
           */
          export function post(  url,
            data = {},
            config = {
              transformRequest: [
                function(fData, headers) {
                  headers['Content-Type'] = 'application/json'
                  return JSON.stringify(fData)
                }
              ]
            }
          ) {
            return new Promise((resolve, reject) => {
              axios.post(url, data, config).then(
                (response) => {
                  resolve(response.data)
                },
                (err) => {
                  reject(err)
                }
              )
            })
          }
          
          /**
           * patch 請求方法,發送數據格式 json
           * @param {*} url
           * @param {*} data
           */
          export function patch(url, data = {}) {
            return new Promise((resolve, reject) => {
              axios
                .patch(url, data, {
                  transformRequest: [
                    function(fData, headers) {
                      headers['Content-Type'] = 'application/json'
                      return JSON.stringify(fData)
                    }
                  ]
                })
                .then(
                  (response) => {
                    resolve(response.data)
                  },
                  (err) => {
                    reject(err)
                  }
                )
            })
          }
          
          export function del(url, data) {
            return new Promise((resolve, reject) => {
              axios.delete(url, { data }).then(
                (response) => {
                  resolve(response.data)
                },
                (err) => {
                  reject(err)
                }
              )
            })
          }
          復制代碼

          如何管理 api

          原理

          首先要制定一個 api 的原則 我的原則一般是這些:

          • 干凈純粹
          • 盡量不要處理數據
          • 獨立單一不要互相依賴

          好處在于:不在 api 里面處理數據,api里面的接口和接口文檔上一樣。避免別人引用我的api,還要去看代碼,只需要看文檔就好了。

          例子:想象這樣一種情況,別人引用了我的 api,突然發現響應數據不對。首先它排查到頁面數據沒更改。看了api文檔,數據也沒問題,最后發現我在寫 api 的時候進行了處理,這個 api 呢又不能改動,改了影響我自己的模塊。只能它在重新寫一個api,這樣顯得很繁雜了,不夠干凈優雅。

          import { fetch, post } from '@/utils/http'
          
          // 用戶登陸
          export const login = data => post('/user/login', data)
          
          // 獲取用戶信息
          export const getUserInfo = (data) => fetch('/api/user/info', data)
          復制代碼

          如果需要處理數據,要么使用一個中間工具處理,要么在頁面里面處理。當然還是實際問題實際分析。

          如何使用mock模擬數據

          原理與解決方案

          一般就是兩種方案,一是模擬后端,使用遠程在線 JSON 服務器。另外一種搭建本地 JSON 或者 使用現成的 Node 服務器攔截請求。

          這兩種方式各有千秋,沒有優劣之分,適合就是最好的。

          遠程在線mock

          我用過的遠程在線mock

          • apizza:好用,功能齊全,喜歡他的文件展開目錄api,免費版只支持 2 個人共同編輯
          • swagger:開源免費,api管理太凌亂,
          • rap/rap2:開源免費,可以搭建本地api,需要自己搭建

          使用遠程mock的優點:

          • 不需要在項目內部增加mock
          • 功能更加全面完善
          • 可以在接口文檔基礎上mock,與接口文檔放在一起查看更加方便。

          缺點:需要自己另外搭建服務器,只支持靜態的mock,不能與單元測試結合使用

          本地JSON mock

          • 使用 webpack 內部 mock 配置
          devServer: {
              // 接口未實現情況下,使用mock
              before: require('./mock')
          }
          復制代碼

          基本原理:主要是使用 node 讀取文件,轉換成 JSON 格式,使用mock.js 模擬數據,最后 webpack 攔截請求生成json響應數據

          const Mock = require('mockjs')
          
          module.exports = (app) => {
              function getJsonFile (filePath) {
                  var json = fs.readFileSync(path.resolve(__dirname, filePath), 'utf-8')
                  return JSON.parse(json)
              },
              const returnMock = (datafile, res, req) => {
                  setTimeout(() => {
                      var json
                      if (/\.json$/.test(datafile)) {
                          // json文件暴露的是mock的模板
                          json = getJsonFile(datafile)
                      } else if (/\.js$/.test(datafile)) {
                          json = require(datafile)(req.query)
                      }
                      res.json(Mock.mock(json))
                  }, 500)
              }
          }
          復制代碼
          • 使用 json-server 搭建 主要分為下面幾步
          1. npm 安裝 json-server
          2. 編寫 npm 腳本命令,引入 mock 配置文件
          3. 編寫 mock 路由匹配規則

          比較簡單這里不詳細描述了!

          本地的缺點在于需要

          • 前端需要根據api文檔寫mock數據格式
          • 功能沒有遠程mock那么完善,支持restful需要去研究下
          • 也是需要配置相關mock工具

          優點在于

          • 不用查看編輯api文檔
          • 在代碼中就可以更改和查看mock數據
          • 支持使用JavaScipt動態處mock,可以與單元測試結合使用

          總結

          本篇文章耗費作者一個多星期的業余時間,存手工敲打 6000+字,同時收集,整理之前很多技巧和邊寫作邊思考總結。如果能對你有幫助,便是它最大的價值。都看到這里還不點贊,太過不去啦!

          由于技術水平有限,文章中如有錯誤地方,請在評論區指出,感謝!

          文中大多數代碼將在suo-design-pro 中更新

          項目有時間會盡量完善

          寫實踐總結性文章真的很耗費時間。如何文章中有幫到你的地方分享下唄,讓更多人看到!

          下節內容預告

          • 如何編寫原生組件,以及組件編寫的思考與原則?
          • 如何使用vuex 以及它的應用場景和原理
          • 如何使用過濾器,編寫自己的過濾器
          • 如何使用 Jest 測試你的代碼?TDD 與 BDD 的比較

          主站蜘蛛池模板: 日韩爆乳一区二区无码| 在线观看精品视频一区二区三区| 亚洲一区中文字幕久久| 日韩伦理一区二区| 亚洲熟女一区二区三区| 国产福利一区二区在线视频 | 久久免费区一区二区三波多野| 国产成人精品一区二区A片带套 | 亚洲国产精品一区二区三区久久 | 伊人久久精品一区二区三区| 国产另类TS人妖一区二区| 精品理论片一区二区三区| 亚洲字幕AV一区二区三区四区 | 精品国产亚洲第一区二区三区| 精品日韩亚洲AV无码一区二区三区| 成人免费一区二区三区| 亚洲人成网站18禁止一区| 相泽南亚洲一区二区在线播放 | jizz免费一区二区三区| 久久婷婷久久一区二区三区| 成人在线视频一区| 四虎精品亚洲一区二区三区| 精品一区二区三区免费毛片| 日韩在线观看一区二区三区| 日本香蕉一区二区三区| 国产一区二区影院| 一区二区三区91| 超清无码一区二区三区| 成人精品视频一区二区三区不卡 | 果冻传媒一区二区天美传媒| 中文国产成人精品久久一区| 精品人体无码一区二区三区| 亚洲毛片αv无线播放一区| 亚洲一区二区三区偷拍女厕| 色久综合网精品一区二区| 亚洲影视一区二区| 色国产在线视频一区| 国产成人片视频一区二区| 久草新视频一区二区三区| 97人妻无码一区二区精品免费 | 在线成人综合色一区|