問題描述:
數據看板中的數據大部分都是實時數據或前一天統計的歷史數據,所以這邊後端考慮採用websocket來實時和定時推送數據來保證數據的實時性和有效性。而前端開發這邊爲了提升前端開發的複用性,採用了在各個組件中開發成一個個的小部件,而後在門戶經過vue異步動態加載的方式來實現,小部件的組裝拼接。 所以在組件中開發的小部件都是單vue頁面。所以出現了有幾個小部件就有幾個websocket,目前我這邊就出現了7個websocket。
問題現象:
在ie瀏覽器下,打開時就會發現報錯。IE控制檯會報SecurityError錯誤。
解決方法:
形成上述現象的緣由是ie下websocket鏈接作了安全限制,若是websocket鏈接超過6個時,那麼就會鏈接失敗。默認最大鏈接數爲6個。
那麼如何避免報錯呢?
固然ie下的限制咱們是很差修改的,若是真的強制修改,那麼能夠經過修改註冊表來修改最大鏈接數(固然這邊是不建議的,不可能讓客戶區修改瀏覽器註冊表的)。
那麼咱們須要的就是避免多個websocket的鏈接。
2個思路:
使用websocket以前先思考,是否真的有必要使用wesocket??html
a.vue created () { this.$root.eventBus = new Vue() this.init() }, methods: { init (i) { let ws = new WebSocket() ws.onmessage = (data) => { this.$root.eventBus.$emit('websocket', data) } } } b.vue created () { this.$root.eventBus.$on('websocket', () => { // 處理推送的數據 }) }
咱們知道咱們的小部件都是經過在門戶,經過vue動態加載組件的方式來造成看板的,那麼因此小部件就都會在門戶這個vue實例對象下。因此能夠採用this.$root下掛在一個vue實例來實現事件的傳遞前端
備註:
另外若是你一個頁面中只有4個websocket,而認爲ie下就不會報錯,請不要這要處理,也請使用type的形式來處理。由於ie下刷新頁面銷燬websocket是時間延遲的。第一次進入頁面websocket鏈接是正常的,而舒心頁面後,可能就會形成2個websocket鏈接失敗。vue
問題描述:在使用hui控件的時候,會出現某些bug,而後bug修改後,項目中應用的hui版本也對應的升級。可是這種狀況下,可能會出現hui內置多語言增長了一些字段,致使項目中會出現有未翻譯的字段。
解決方法:node
把hui.js替換成如下代碼那麼中文狀態就能夠隨着hui的升級而變化了webpack
hui.js 修改前: let hui = { colorpicker: { confirm: '肯定', clear: '清空' }, ....等因此hui的key值 } export default hui 修改後: import hui from 'hui/lib/locale/lang/zh-CN.js' export default hui.el // 這邊是由於hui內部包了一層el,因此直接拋出hui.el的對象
多語言問題的拓展:
在組件中開發中怎麼使用多語言呢?以前組件開發我都是把變量拋到外面,經過調用者傳遞參數進來,那麼外面確定都是已經轉過多語言的了,那麼這種確定是沒問題的,固然這不是特別好的。所以這邊把hui-pro如何使用多語言的方式來講明一下,之後開發組件中遇到多語言問題均可以這樣操做,向hui那樣把語言放到項目工程中。web
首先在工程中須要建立對應的語言js文件如zh_CN.js
而後在建立一個調用的方式:ajax
import defaultLang from 'hui-pro/src/locale/lang/zh-CN'; import Vue from 'vue'; import deepmerge from 'deepmerge'; import Format from './format'; const format = Format(Vue); let lang = defaultLang; let merged = false; let i18nHandler = function() { const vuei18n = Object.getPrototypeOf(this || Vue).$t; if (typeof vuei18n === 'function' && !!Vue.locale) { if (!merged) { merged = true; Vue.locale( Vue.config.lang, deepmerge(lang, Vue.locale(Vue.config.lang) || {}, { clone: true }) ); } return vuei18n.apply(this, arguments); } }; export const t = function(path, options) { let value = i18nHandler.apply(this, arguments); if (value !== null && value !== undefined) return value; const array = path.split('.'); let current = lang; for (let i = 0, j = array.length; i < j; i++) { const property = array[i]; value = current[property]; if (i === j - 1) return format(value, options); if (!value) return ''; current = value; } return ''; }; export const use = function(l) { lang = l || lang; }; export const i18n = function(fn) { i18nHandler = fn || i18nHandler; }; export default { use, t, i18n };
這個js文件是用於合併工程中的多語言或本身翻譯t函數就是對外組件使用多語言的方法。
這邊經過作一個mixinsjson
import { t } from 'hui-pro/src/locale'; export default { methods: { t(...args) { return t.apply(this, args); } } };
而後直接在組件中使用該mixins便可後端
<template> {{ t(`h.common.add`) }} </template> import Locale from 'hui-pro/src/mixins/locale'; export default { mixins: [Locale] }
問題描述: 目前這邊有那麼一種場景,前端有一些列的城市的json文件,而前端須要根據後端的返回值來調用相應的城市json文件。對於這種狀況下:我就使用了require加載動態文件的方式來加載,由於require是同步加載的,因此比較方便。使用方式以下瀏覽器
let city 從後端獲取 let cityMap = require(`static/city/${city}.json`); // 後續根據cityMap再處理
就以上那麼一段代碼在打包的時候會將city下的因此json文件都打包的js裏面。(require是提早把全部的文件都打包進來,才使得能夠動態的加載)。
形成了js比原來臃腫了不少。(臃腫程度是跟city下json文件大小有關)。而後進入對應的頁面也會相對要慢一些(js比原先大了一些),這樣用戶體驗很差。
由於對於動態加載的方式儘可能避免(若是文件小的話,那影響不大)
解決方法:
動態獲取的文件(這邊的city.js,多語言,皮膚包等等)儘可能都經過ajax來獲取,這樣打包的js文件會少不少。
爲了保證還是同步的,那麼就採用es7的async、await來操做吧
async get () { let city = xxx try { let cityMap = await xxx.get('xxxx') // 在根據cityMap出咯 } catch {} }
問題描述:以前講述了一篇關於如何打包小部件的,可是那篇並無使用複雜的頁面,引用第三方插件等。就是單純幾個簡單的頁面的測試。這一次實際打包以後發現仍然有很多問題須要優化:
所以這邊須要剔除依賴進行打包,方法以下:
// webpack配置中增長以下配置項,如還有其餘第三方插件均可以配置在以下 externals: { echarts: 'echarts', hui: 'hui', vue: 'vue' },
經過以上過濾,能夠講一個文件從幾M縮小到100KB之內。
a. 這個是因爲小部件內部是經過this.$t的形式去調用i18n來翻譯的。可小部件的環境發生了變化,經過門戶動態調用組件的方式加載,那麼小部件所在的環境就是門戶的vue實例對象,那麼i18n也就是門戶的,因此小部件就沒法獲得翻譯。
b. http的實例對象內部也不能夠經過i18n以及{message} from 'hui'這些。緣由是已經剔除了這些依賴,那麼打包後就會報錯,i18n和hui不存在。
解決方法: 經過一個配置文件裏面存放本身組件中的i18n的json文件路徑(/oams/static/i18n/zh-CN/index.json),以及一個keys字段。將看板的部件多語言文件給讓門戶下載,並跟門戶本身的多語言合併(所以多語言key必定要加上本身的上下文或其餘來和門戶區分,不要字段重疊)。這些組件內部經過this.$t也都能正常翻譯。
問題描述: 目前前端都使用了統一的前端請求封裝,http都作了一些處理如登陸過時跳登錄頁,可上傳組件是組件內部本身ajax請求,所以是不會作這些特殊處理。所以在組件內部須要本身作一下
解決方法:
若是當前已經登陸過時,那麼後端單點登陸針對Content-Type爲application/json都是後端作了一層處理,返回errorCode爲pleaseRefreshByHeader,那麼前端根據這個值來跳登陸頁。但是上傳組件的Content-Type:multipart/form-data,這種類型的單點登陸是直接進行攔截而不會通過後端,直接返回錯誤頁面。
那麼咱們就須要針對返回的頁面作特殊處理
uploadSuccess (res, file) { if (res.code === '0') { this.$message.success(this.$t(`oams_common.addSuccess`)) this.addMapDialog = false this.$emit('add-map-success') } else { // 頁面過時處理 if (res.includes && res.includes('html')) { let refreshUrl = '/isecure/cas/login?service=' + location.protocol + '//' + location.host + location.pathname location.href = refreshUrl } else { // 錯誤碼處理 this.$message.error(this.$t(`oams_errorcode.${res.code}`)) this.$refs.mapUpload.clearFiles() this.$nextTick(() => { this.mapForm.filename = '' }) } } }
除了上面的方法還能夠在上傳組件前,先本身發送一個接口驗證當前頁面是否已通過期,若是已通過期,那麼它就會自動跳轉首頁了(本身的接口都是通過處理的),並且這也不僅僅處理了單點登陸,網絡超時也作了相應了處理。(上傳組件是沒有作超時處理的,由於不知道文件上傳須要多久,若是設置了,網絡差的狀況下可能上傳文件或圖片就失敗了)