问题描述:
数据看板中的数据大部分都是实时数据或前一天统计的历史数据,所以这边后端考虑采用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 = '' }) } } }
除了上面的方法还能够在上传组件前,先本身发送一个接口验证当前页面是否已通过期,若是已通过期,那么它就会自动跳转首页了(本身的接口都是通过处理的),并且这也不仅仅处理了单点登陆,网络超时也作了相应了处理。(上传组件是没有作超时处理的,由于不知道文件上传须要多久,若是设置了,网络差的状况下可能上传文件或图片就失败了)