资讯专栏INFORMATION COLUMN

项目经验总结

William_Sang / 3454人阅读

摘要:项目中前端开发问题经验总结下的安全限制问题问题描述数据看板中的数据大部分都是实时数据或前一天统计的历史数据,因此这边后端考虑采用来实时和定时推送数据来保证数据的实时性和有效性。

项目中前端开发问题经验总结 ie下websocket的安全限制问题

问题描述:
数据看板中的数据大部分都是实时数据或前一天统计的历史数据,因此这边后端考虑采用websocket来实时和定时推送数据来保证数据的实时性和有效性。而前端开发这边为了提高前端开发的复用性,采用了在各个组件中开发成一个个的小部件,然后在门户通过vue异步动态加载的方式来实现,小部件的组装拼接。 因此在组件中开发的小部件都是单vue页面。因此出现了有几个小部件就有几个websocket,目前我这边就出现了7个websocket。
问题现象:
在ie浏览器下,打开时就会发现报错。IE控制台会报SecurityError错误。
解决方法:
造成上述现象的原因是ie下websocket连接做了安全限制,如果websocket连接超过6个时,那么就会连接失败。默认最大连接数为6个。
那么如何避免报错呢?
当然ie下的限制我们是不好修改的,如果真的强制修改,那么可以通过修改注册表来修改最大连接数(当然这边是不建议的,不可能让客户区修改浏览器注册表的)。
那么我们需要的就是避免多个websocket的连接
2个思路:
使用websocket之前先思考,是否真的有必要使用wesocket??

如果是实时推送,定时推送这些场景,那么完全没有必要使用websocket,前端可通过定时器来实现相同的功能。因此能避免使用就避免使用。

如果是报警等未知的推送,那么我们就是必须要使用websocket的,而且如果正好应用在了看板小部件上。那么还是会出现7个websocket的情况。所以这种情况下就需要和后端沟通,一个项目采用一个websocket服务,通过type来区分。那么看板就只有一个websocket了。可是现在看板的小部件都是独立,如何去实现一个websocket?那么需要借助一下事件通信。如下:

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连接失败。

hui多语言使用问题

问题描述:在使用hui控件的时候,会出现某些bug,然后bug修改后,项目中应用的hui版本也对应的升级。但是这种情况下,可能会出现hui内置多语言增加了一些字段,导致项目中会出现有未翻译的字段。
解决方法:

在我们各个组件框架下的i18n下面有一个hui.js文件,这个文件内部就是hui的多语言,这个多语言版本是在脚手架完成的时候就已经创建了,它是不会随着hui的升级而变化,因此我们就需要从hui那边去拿到最新的包(node_modules/hui/lib/locale/lang/zh-CN.js),然后再替换更新。

当然我们除了手动这样替换之外,我们也可以直接引用这个文件,那么之后就不需要再替换了。(当然翻译的文件还是需要更具index.json来翻译最新的)

把hui.js替换成以下代码那么中文状态就可以随着hui的升级而变化了

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那样把语言放到项目工程中。

首先在工程中需要创建对应的语言js文件如zh_CN.js
然后在创建一个调用的方式:

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函数就是对外组件使用多语言的方法。
这边通过做一个mixins

import { t } from "hui-pro/src/locale";

export default {
  methods: {
    t(...args) {
      return t.apply(this, args);
    }
  }
};

然后直接在组件中使用该mixins即可


import Locale from "hui-pro/src/mixins/locale";
export default {
   mixins: [Locale]
}
require的使用问题

问题描述: 目前这边有那么一种场景,前端有一些列的城市的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 {}
}
门户看板小部件打包的一些问题

问题描述:之前讲述了一篇关于如何打包小部件的,但是那篇并没有使用复杂的页面,引用第三方插件等。就是单纯几个简单的页面的测试。这一次实际打包之后发现仍然有不少问题需要优化:

打包的文件会比较大。这是由于每个单vue文件打包,将所有依赖都打包进来了,那么就造成文件过于臃肿,相比于单vue实例的效果会差很多,会重复打包vue,hui,echarts等一些插件。

因此这边需要剔除依赖进行打包,方法如下:

// 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也都能正常翻译。

hui上传组件的问题

问题描述: 目前前端都使用了统一的前端请求封装,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 = ""
          })
        }
      }
    }

除了上面的方法还可以在上传组件前,先自己发送一个接口验证当前页面是否已经过期,如果已经过期,那么它就会自动跳转首页了(自己的接口都是经过处理的),而且这也不单单处理了单点登录,网络超时也做了相应了处理。(上传组件是没有做超时处理的,因为不知道文件上传需要多久,如果设置了,网络差的情况下可能上传文件或图片就失败了)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102570.html

相关文章

  • 帝都寒冬一年经验前端面试总结

    摘要:不过幸运的是所有面试的公司都给了,在这里总结下经验吧。这里推荐下我当时看的一篇的面经,木易杨老师写的大厂高级前端面试题汇总。 前言 本人毕业一年,最近陆续面试了头条、瓜子、360、猿辅导、中信银行、老虎等公司,由于最近比较寒冬而且招1-3年的并不多,再加上自己对公司规模和位置有一定要求,所以最后合适的也就这几家了。不过幸运的是所有面试的公司都给了offer,在这里总结下经验吧。掘金:h...

    Scott 评论0 收藏0
  • 经验分享】测试人员如何写总结

    摘要:参与者项目经理产品经理开发经理测试经理及其它相关人员。项目上线后问题反馈针对项目客户反馈问题进行分析总结,类似缺陷分析,重点总结遗漏的原因及后需的规避措施。六汇总整理各部门总结并发布基于测试总结过程中的数据分析,我们提出了对部门的建议。 最近参与了几次面试,面试者的简历中都会提及:需求或者...

    Vixb 评论0 收藏0
  • 项目经验总结

    摘要:每一个项目过后,我们总是有各种各样的体会,这些体会就是我们的收获,也是我们成长的源泉,也许过了一段时间我会忘记,但是,笔记能够让他们清晰的保留下来绿网项目宁肯走的慢一点,也要保证方向是正确的注意无论做什么项目,首先,我们需要清晰的明确大的环 每一个项目过后,我们总是有各种各样的体会,这些体会就是我们的收获,也是我们成长的源泉,也许过了一段时间我会忘记,但是,笔记能够让他们清晰的保留下来...

    lvzishen 评论0 收藏0
  • 程序员该如何有效的找工作?

    摘要:经验少的程序员小猿同学毕业工作一年了,在公司感觉自己的能力很好了,能力大于老板给的价值了,所以想要涨工资,但是老板给涨的不够理想,小猿听说跳槽可以让自己的工资翻倍,毅然决然的就辞职了,决定重新找工作。 又到了一周一次的周末心灵鸡汤的时间了,希望大家能够痛痛快快的喝了这碗鸡汤,让这酸爽的感觉使你永生难忘。哈哈……这周又有几个人,尤其是毕业生在「非著名程序员」微信公众号里私聊我关于找不到工...

    BLUE 评论0 收藏0

发表评论

0条评论

William_Sang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<