vue項目實戰經驗彙總

来源:https://www.cnblogs.com/mrwh/archive/2020/02/18/12327883.html
-Advertisement-
Play Games

[TOC] 1.vue框架使用註意事項和經驗 本文主要總結了在開發vue項目中的一些實踐經驗和踩過的一些坑,後續會接著更新,便於後期復盤,希望也對你有所幫助 1.1 解決Vue動態路由參數變化,頁面數據不更新 問題描述: 遇到動態路由如:/page/:id 從/page/1 切換到 /page/2 ...


目錄

1.vue框架使用註意事項和經驗

本文主要總結了在開發vue項目中的一些實踐經驗和踩過的一些坑,後續會接著更新,便於後期復盤,希望也對你有所幫助

1.1 解決Vue動態路由參數變化,頁面數據不更新

問題描述:

遇到動態路由如:/page/:id
從/page/1 切換到 /page/2 發現頁面組件沒有更新

解決方式:
給<router-view :key="key">增加一個不同:key值,這樣vue就會識別這是不同的了。

<router-view :key="key"></router-view>
  ...
  computed:{
        key(){
            return this.$route.path + Math.random();
        }
    }

1.2 vue組件里定時器銷毀問題

問題描述:
在a頁面寫一個定時器,每秒鐘列印一次,然後跳轉到b頁面,此時可以看到,定時器依然在執行。
推薦的解決方式:
通過$once這個事件偵聽器器在定義完定時器之後的位置來清除定時器。

const timer = setInterval(() => {
    // 定時器操作
}, 1000)

// 通過$once來監聽定時器,在beforeDestroy鉤子可以被清除。
this.$once('hook:beforeDestroy', () => {            
    clearInterval(timer);                                    
})

1.3 vue實現按需載入組件的兩種方式

1.使用resolve => require(['./ComponentA'], resolve),方法如下:

const ComponentA = resolve => require(['./ComponentA'], resolve)
  1. 使用 () => import(), 具體代碼如下:
const ComponentA = () => import('./ComponentA')

1.4 組件之間,父子組件之間的通信方案

組件之間的通信方案:

  • 通過事件匯流排(bus),即通過發佈訂閱的方式
  • vuex
  • 父子組件:
  • 父組件通過prop向自組件傳遞數據
  • 子組件綁定自定義事件,通過this.$emit(event,params) 來調用自定義事件
  • 使用vue提供的$parent/$children & $refs方法來通信
  • provide/inject
  • 深層次組件間的通信 $attrs, $listeners

實現細節可參考:https://m.jb51.net/article/167304.htm

1.5 vue中 $event 的用法--獲取當前父元素,子元素,兄弟元素

<button @click = “fun($event)”>點擊</button>
  ...
  
  methods: {
   fun(e) {
    // e.target 是你當前點擊的元素
    // e.currentTarget 是你綁定事件的元素
    #獲得點擊元素的前一個元素
    e.currentTarget.previousElementSibling.innerHTML
    #獲得點擊元素的第一個子元素
    e.currentTarget.firstElementChild
    # 獲得點擊元素的下一個元素
    e.currentTarget.nextElementSibling
    # 獲得點擊元素中id為string的元素
    e.currentTarget.getElementById("string")
    # 獲得點擊元素的string屬性
    e.currentTarget.getAttributeNode('string')
    # 獲得點擊元素的父級元素
    e.currentTarget.parentElement
    # 獲得點擊元素的前一個元素的第一個子元素的HTML值
    e.currentTarget.previousElementSibling.firstElementChild.innerHTML
  
    }
        },

1.6 vue常用工具函數總結

/*
 日期相關 dateFormater:格式化時間
 timestampToTime
 * */
function dateFormater(formater, t){
   let date = t ? new Date(t) : new Date(),
      Y = date.getFullYear() + '',
      M = date.getMonth() + 1,
      D = date.getDate(),
      H = date.getHours(),
      m = date.getMinutes(),
      s = date.getSeconds();
   return formater.replace(/YYYY|yyyy/g,Y)
      .replace(/YY|yy/g,Y.substr(2,2))
      .replace(/MM/g,(M<10?'0':'') + M)
      .replace(/DD/g,(D<10?'0':'') + D)
      .replace(/HH|hh/g,(H<10?'0':'') + H)
      .replace(/mm/g,(m<10?'0':'') + m)
      .replace(/ss/g,(s<10?'0':'') + s)
}
//  dateFormater('YYYY-MM-DD HH:mm', 1580787420000)//==> "2020-02-04 11:37"
// dateFormater('YYYYMMDDHHmm', new Date()) //==> 201906261830

/*
獲取Url參數,返回一個對象
 * */
function GetUrlParam(){
   let url = document.location.toString();
   let arrObj = url.split("?");
   let params = Object.create(null)
   if (arrObj.length > 1){
      arrObj = arrObj[1].split("&");
      arrObj.forEach(item=>{
         item = item.split("=");
         params[item[0]] = item[1]
      })
   }
   return params;
}
// ?a=1&b=2&c=3 ==> {a: "1", b: "2", c: "3"}

//toFullScreen:全屏
function toFullScreen(){
   let elem = document.body;
   elem.webkitRequestFullScreen
   ? elem.webkitRequestFullScreen()
   : elem.mozRequestFullScreen
   ? elem.mozRequestFullScreen()
   : elem.msRequestFullscreen
   ? elem.msRequestFullscreen()
   : elem.requestFullScreen
   ? elem.requestFullScreen()
   : alert("瀏覽器不支持全屏");
}

//exitFullscreen:退出全屏
function exitFullscreen(){
   let elem = parent.document;
   elem.webkitCancelFullScreen
   ? elem.webkitCancelFullScreen()
   : elem.mozCancelFullScreen
   ? elem.mozCancelFullScreen()
   : elem.cancelFullScreen
   ? elem.cancelFullScreen()
   : elem.msExitFullscreen
   ? elem.msExitFullscreen()
   : elem.exitFullscreen
   ? elem.exitFullscreen()
   : alert("切換失敗,可嘗試Esc退出");
}

1.7 axios二次封裝http請求

import axios from 'axios'
import router from '@/router'
import {removeSessionStorage} from './storage';
import Vue from 'vue'
import { Message } from 'element-ui' // 引用element-ui的載入和消息提示組件
// 請求超時時間配置
axios.defaults.timeout = 30000;
// api地址配置
axios.defaults.baseURL = "";
// console.log(process.env.VUE_APP_BASE_API)
Vue.prototype.$http = axios
// 在全局請求和響應攔截器中添加請求狀態
let loading = null

// 請求攔截器
axios.interceptors.request.use(
    config => {
      config.headers = {
        'Content-Type': 'application/json'
      };
      // loading = Loading.service({ text: '拼命載入中' })
      let token = sessionStorage.getItem('-_token_-');
      if (token) {
        config.headers['token'] = token;
      }
      return config
    },
    error => {
      return Promise.reject(error)
    }
)

// 響應攔截器
axios.interceptors.response.use(
    response => {
      if (loading) {
        loading.close()
      }
      //console.log(response)
      const code = response.status
      if ((code >= 200 && code < 300) || code === 304) {
        let errorCode = response.data.errCode;
        if(errorCode==='000000'){
          return Promise.resolve(response.data)
        }else {
          if (errorCode === 'SYS0404') {
                router.push({
              name: 'error',
              params: {
                isTimeout: false,
                path: router.currentRoute.path,
                desc: '您請求的資源找不到(錯誤碼:404) ',
              },
            });
          } else if (errorCode === 'SYS0401') {
            removeSessionStorage('-_token_-');
            router.replace({
              path: '/login',
              query: {
                redirect: router.currentRoute.fullPath
              }
            });
          }
          // Message.error(response.data.message)
          return Promise.resolve(response.data)
        }
        // return Promise.resolve(response.data)
      } else {
        return Promise.reject(response)
      }
    },
    error => {
      if (loading) {
        loading.close();
      }
      console.log(error);
      if (error.response) {
        switch (error.response.status) {
          case 401:
          case 403:
            // 返回401 清除token信息並跳轉到登陸頁面
            removeSessionStorage('-_token_-');
            router.replace({
              path: '/login',
              query: {
                redirect: router.currentRoute.fullPath
              }
            });
            break;
          case 404:
            Message.error('網路請求不存在');
            console.log('錯誤碼:404 路由跳轉 currentRoute  %o ', router.currentRoute.path);
            router.push({
              name: 'error',
              params: {
                isTimeout: false,
                path: router.currentRoute.path,
                desc: '您請求的資源找不到(錯誤碼:404) ',
              },
            });
            break;
          case 502:
            router.push({
              name: 'error',
              params: {
                isTimeout: false,
                path: router.currentRoute.path,
                desc: '網關錯誤(錯誤碼:502),請聯繫系統管理員 ',
              },
            });
            break;
          default:
            Message.error(error.response.data.message ||'系統出錯,請聯繫系統管理員(錯誤碼:'+error.response.status+')!');
        }
      } else {
        let controlParam = {
          desc: '',
          path: router.currentRoute.path,
          isTimeout: false,
        };
        // 請求超時或者網路有問題
        if (error.message.includes('timeout')) {
          Message.error('請求超時!請檢查網路是否正常');
          controlParam.desc = '網路斷開,請檢查您的網路 ';
          controlParam.isTimeout = true;
        } else {
          Message.error('請求失敗,請檢查網路是否已連接');
          controlParam.desc = '頁面載入失敗 ';
        }
        router.push({
          name: 'error',
          params: controlParam,
        });
      }
      return Promise.reject(error);
    }
);

2.elementui組件修改經驗總結

2.1 element-ui 中步驟條的深度使用

2.1.1element-UI的操作步驟steps每一項添加事件,比如click,hover

<el-steps :space="200" :active="1" finish-status="success">
  <el-step @click.native="on_click(1)" title="已完成"></el-step>
  <el-step @click.native="on_click(2)" title="進行中"></el-step>
  <el-step @click.native="on_click(3)" title="步驟 3"></el-step>
</el-steps>

2.1.2 具體業務交互
https://blog.csdn.net/weixin_40098371/article/details/88027949
2.1.3 改變文字方向
https://note.youdao.com/yws/public/resource/9c3b95f76c7c720da259832b7b0e087f/xmlnote/D19A72F2CA8F435C9285D24ADBAD4857/12997
變為
img2

調整css,設置magin和background

.el-step__main {
    white-space: normal;
    text-align: left;
    margin-top: -31px;
    margin-left: 25px;
}

}
i
.el-step__title {
    font-size: 16px;
    line-height: 38px;
    background: #FFF;
    width: 50px;
    position: relative;
    z-index: 1;
}

2.2 v-loading框中的提示文字換行

https://note.youdao.com/yws/public/resource/9c3b95f76c7c720da259832b7b0e087f/xmlnote/F78532DA69D64227BB91A5D7D1B74C8E/13062

2.3 路由菜單項雙擊控制台報錯

//解決菜單雙擊報錯
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}

3.Vue項目配置

3.1 Vue-cli3 配置開發、生產和測試環境

  • 創建開發環境變數 .env.development
  • 創建生產環境變數 .env.production
  • 創建測試環境變數 .env.test

image
註意環境變數的首碼必須是VUE_APP
image
在其他文件中通過process.env.VUE_APP_BASE_API來訪問,例如在介面文件代碼中

import axios from 'axios'
import router from '@/router'
// 請求超時時間配置
axios.defaults.timeout = 30000;
// api地址配置
axios.defaults.baseURL = "process.env.VUE_APP_BASE_API";

對應的package.json配置為

"scripts": {
  "serve": "vue-cli-service serve --mode development",
  "build": "vue-cli-service build --mode production",
  "test": "vue-cli-service build --mode test",
  },

3.2開發環境中代理的切換配置

為了應對這樣的跨域場景,在代碼開發時,devServer要代理到本地後端,測試時,又要去修改代理到測試環境,上線後,調試新問題有可能代理到線上環境

對vue.config.js的進行配置

const Timestamp = new Date().getTime();  //當前時間為了防止打包緩存不刷新,所以給每個js文件都加一個時間戳
const proxyTargetMap = {
    prod: 'https://xxx.xxx.com/',
    dev: 'http://192.168.200.230:6379',
    test: 'http://test.xxx.com',
    local: 'http://localhost:8080/'
}
let proxyTarget = proxyTargetMap[process.env.API_TYPE] || proxyTargetMap.local
module.exports = {
    publicPath: process.env.NODE_ENV === 'production' ? '/' : '/',
    outputDir: 'dist',
    assetsDir: 'static',
    lintOnSave: false, // 是否開啟eslint保存檢測
    productionSourceMap: false, // 是否在構建生產包時生成sourcdeMap
    // 調整內部的 webpack 配置。
    // 查閱 https://github.com/vuejs/vue-docs-zh-cn/blob/master/vue-cli/webpack.md
    chainWebpack: () => { },
    //configureWebpack 這部分打包文件添加時間戳,防止緩存不更新
    configureWebpack: {
        output: { // 輸出重構  打包編譯後的 文件名稱  【模塊名稱.版本號.時間戳】
            filename: `[name].${process.env.VUE_APP_Version}.${Timestamp}.js`,
            chunkFilename: `[name].${process.env.VUE_APP_Version}.${Timestamp}.js`
        },
    },

    devServer : {
        proxy: {
            '/api' : {
                target: proxyTarget,
                changeOrigin: true,
                pathRewrite: {
                    '^/api' : ''
                }
            }
        }
    }
};

對應的package.json配置為

"scripts": {
  "serve": "vue-cli-service serve --mode development",
+  "serve:dev": "cross-env API_TYPE=dev vue-cli-service serve --mode development",
+  "serve:test": "cross-env API_TYPE=test vue-cli-service serve --mode development",
  "build": "vue-cli-service build --mode production",
  "test": "vue-cli-service build --mode test",
  },

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、點擊上傳 2、填寫版本號、備註 3、https://mp.weixin.qq.com/回到微信公眾平臺,點擊版本管理就可以看到開發版本 4、點擊提交審核(提交之前填寫小程式基本資料,才可提交審核),接著配置功能頁面。 5、點擊提交審核之後在審核版本模塊中會出現項目信息(人工介入審核,審核成功之後 ...
  • 介紹馬蜂窩如何通過 App 地理相冊空間索引的應用,為用戶提供直觀、好用的圖片分享服務。 ...
  • 首先我們看ListView實現之後的的效果,如下圖所示: 現在我們來看看如何來實現這個可以進行上下活動的ListView: 首先是主界面Activity_Main.xml的代碼: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:a ...
  • css3和css有什麼區別?首先css33是css(層疊樣式表)技術的升級版本,而css是一種用來表現HTML(標準通用標記語言的一個應用)或XML(標準通用標記語言的一個子集)等文件樣式的電腦語言。然後是內容上css3主要包括盒子模型、列表模塊、超鏈接方式、語言模塊、背景和邊框、文字特效、多欄布... ...
  • ajax實例,檢測用戶與註冊 檢測用戶名是否被占用: 在用戶填寫完用戶名之後,ajax會非同步向伺服器發送請求,判斷用戶名是否存在 首先寫好靜態頁面: index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> < ...
  • 模板字元串:我理解為將字元串格式化、模板化,將字元串加強處理,此處的模板有動詞的意思。 字元串模板基本格式: `xxxxxx`(前後都用反引號【tab鍵上面按鍵】引起來)。除了作為普通字元串 外;還可以用來定義多行字元串;也可以在字元串中加入變數和表達式,進行字元串內容擴充和計算。 1、普通字元串: ...
  • 前言 一直身在武漢,基於眾所周知的疫情原因,這個春節只能宅著。 不過其實這個春節是這些年來過得最爽的一個了。 沒有鞭炮,不用四處跑,安安心心呆在家裡玩玩游戲看看書寫寫代碼,其實日子過得還是挺悠閑的。 廢話少說,這段時間買了《古劍奇譚3》,全成就拿齊了之後,就抽了點時間來分享在玩游戲的過程中自製的一個 ...
  • 解構賦值概述 1、解構賦值是對賦值運算符的擴展。 2、它是一種針對數組或者對象進行模式匹配,然後對其中的變數進行賦值。 3、代碼書寫上顯得簡潔且易讀,語義更加清晰明瞭;而且還方便獲取複雜對象中的數據欄位。 解構模型 在解構賦值操作過程中,有下麵兩部分參與: 1、解構的源:解構賦值表達式的右邊部分。如 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...