记录帖子-开发过程中遇到的问题和感悟记录

前端规范和小技巧

1.关于计算属性

计算属性关联的变量不可以过多,同时要保证关联的变量在代码中的变换次数不可过多

例如这段代码的this.options内部数据变化过多,计算属性调用次数过多导致页面卡顿。

3.关于更新数据问题

有这样的一个页面,

产品信息数据是从tab获取的,此时点击保存的时候,需要跟新左侧tab数据,才能够保证切换tab选项再切换回来的时候,显示的是修改之后的数据,我的做法是直接拉数据。但是会有个问题,就是下面的ppt展示的数据依赖的tab产品的数据,而我是通过监听整个对象,这时候就会有个问题,重新拉数据,就是导致ppt展示接口也会拉数据,导致ppt展示组件闪一下。但是如果点击保存不重新拉数据,而是直接修改数据,需要把保存的数据向上抛三层,而且数据字段过多,类型还不一致。

解决方案:为了保证即能拉到数据,又让ppt组件接口不调用,需要在ppt展示组件换成监听组件必须的字段,即监听一个基本数据类型,通过props的形式传入,在监听改字段,此时由于是基本数据类型,只看内容,就不会触发监听

要求:赋值的时候,fileId要在productDetails之后赋值,要不然慧法师监听到fileId但是productDetails没变的情况

2.关于自定义v-model

使用自定义v-model保证双向绑定的数据类型是一个基本数据类型,不使用v-model实现绑定一个对象类型的数据,对于对象类型应该使用的是props+emit的方式实现数据的双向流动。原因:业务迭代的时候,不好对数据进行拦截做其他操作。

3.组件数据通传,后代组件接收

vue3的props子组件未接收都放到$attrs,$attrs包括$attrs和$listeners两个部分,

v-bind="$attrs"

v-bind="[...cardConfig]"

v-bind="{...$attrs, ...minInputProps}"

问题记录

1.关于腾讯无界微前端的问题

a.关于tab切换渲染同一个页面,同时这个页面中含有无界子应用的的问题

问题描述:来回切换tab的时候,第二次切入原先打开的无界子页面空白。(此时的无界的name绑定为tab的id加一个常量字符串)

原因:切换页面时无界未被销毁,切回的时候方式冲突,

解决方案:生成随机无界name,只是一个临时方案,用于将vue2升级成vue3过渡使用。

2.关于页面开发布局和数据流动问题

页面做成流式布局,尽量不用使用嵌套布局,以便迭代的时候,数据好流动到各个组件。

拆掉一层布局,这样如果在这个页面上再加层 布局或者是在之中加一层布局就会很方便,代码举例

改方法内部有很多的组件,实际上可以提出来放到div中。

3.关于框架的使用问题

再使用框架的时候,尽量不要使用这个框架提供的api而是使用原生api实现。

原因:可能在那个版本使用的是最好的,但是对于迭代来说,可能会造成累赘。

问题描述:使用nuxt提供的asyncData,通过请求接口获取到数据在注入到vue的data里面。迭代需求,再原来的页面上增加侧栏nav,每次切换的时候,数据带入到原来的页面,差不多类似下图

这时候就会有个问题,侧栏通过请求接口获取到数据,会有一定的延时,同时如果获取到数据后再通过v-if渲染组件,由于原来的是通过asyncData来获取到数据,数据会在create的时候就初始化,即vue的data渲染的时候赋值。这会导致传入的props无法在data之前获取,同时使用了大量的计算属性和vuex,导致数据没传入就执行了计算属性和vuex的内容,导致报错。

此处临时解决方案:使用无界嵌入原页面作为子组件(过渡方案)

4.关于导航守卫无法拦截问题

nuxt项目,使用的是window.open打开的新页面,导致无法拦截,无法解决,最后使用浏览器原生api--beforeunload 实现跳转拦截提示。

5.关于阻止冒泡的技巧

(2023-12-06更新)

有种情况,就是使用了组件,但是改组件内部的click方法内有阻止冒泡,但是改组件外层也有个click方法,解决问题的方法是直接改掉该组件,但是过程会比较麻烦,还需要发布组件库,此时我们可以在改组件的父元素(如果改组件的父元素刚好绑定click,此时需要在该组件套一层div)绑定一个方法,再这个方法实现阻止冒泡即可

6.关于iframe嵌入跨域问题

有个项目嵌入了iframe,iframe子页面和本项目完全跨域,通过查找网上的一些部分之后,低版本谷歌和火狐可以,但是高版本谷歌不行,后端没法将cookie写入。

功能描述:一个弹框,弹框内嵌入另一个页面,逻辑为我需要先请求一个接口,通过接口获取到uuid,然后通过拼接到嵌入页面的地址,这个地址为一个转发地址,改转发地址会将token写道用户信息,此时嵌入的页面可以显示,但是出现问题,token无法写入cookie中,转发接口报跨域错误。

问题原因: 高版本谷歌使用iframe不允许转发写入cookie。

解决方案: 再部署一份项目,访问地址为父引用的地址,实现同源访问。例如我们的访问地址为fom.1234sig.com,则新部署的地址为mp.1234sig.com。即可实现同源访问。

7.关于按钮点击获取焦点后按enter键一直触发事件问题

问题描述:公司封装的按钮和confirm一起配合使用的时候会触发这个问题

第一次触发

鼠标不点击页面上任何位置,按键盘enter键

查看调用栈

已知原因,由于第一次点击弹出弹框之后,未能使元素失去获焦,导致按住enter键之后会一直触发按钮的enter事件

解决方案:点击时让其失去焦点

在方法触发时添加

document.activeElement.blur()

8.关于使用provide/inject先后代传值的问题描述

描述

父组件通过provide向个个后代组件注入同一个对象,后代组件分别使用inject获取到该数据,但是会导致一个问题,如果多次刷新页面,此时页面展示会有问题,如下图所示:

用过vuetools查看input组件,v-model是已经绑定了,但是数据未能显示,后面换成原生input,还是会出现这个问题,而且这个问题本地特别难复现,发布到沙盒之后偶显。

使用很多方式解决过,但是不行,所以怀疑是nuxt版本的问题,所以升级了nuxt版本,由于升级nuxt版本升级得有问题,就不用过升级nuxt解决了。

最终解决方案:不使用provide依赖注入,而是使用props的方式逐层传入。

9.关于v-model实现双向绑定的注意事项

这个问题是在将vue2页面升级成vue3页面时发现的一个问题,原先组件是通过emit触发的,但是由于已经迭代了,这个方式不满足要求了,所以使用了v-model实现了

主要是值变化触发了两次,看代码发现属性赋值了两次,就会触发两次,如下图

10.关于flex-grow:1的问题

一个父元素有三个子元素,其中一个子元素宽度固定,另外两个子元素使用flex-grow:1平分剩余空间的,如果值设置flex-grow:1,不会平分剩余空间而是需要再设置width才能平分剩余空间

例如:{flex: 1; width: 0;}

11,关于tab自适应问题,tab会跟着屏幕的收缩而进行隐藏

父元素固定高度,使用flex布局,使用溢出隐藏,

获取到offsetLeft而且index不为0的元素index,即是被隐藏的第一个元素,从这里切开数组。

父元素开启相对定位,省略元素开启绝对定位,

获取显示最后的元素即index-1的元素,计算出元素右侧距离到元素左边的距离

算出距离之后,将距离作为省略元素定位的left值即可

部分代碼

    resizeLabel() {
      let labelDom = document.querySelector(".g-tag-group_overflow");
      let labelDomChildren = labelDom.children;
      let childrenArrayKList = Array.from(labelDomChildren);
      let computedParam = this.getDomIndexItem(childrenArrayKList);
      if (computedParam.index != 0) {
        this.overLabelList = this.zyLabel.slice(
          computedParam.index,
          this.zyLabel.length + 1
        );
        this.dropdownLeft =
          childrenArrayKList[computedParam.index - 1]?.getBoundingClientRect()
            ?.right -
          labelDom?.getBoundingClientRect()?.left +
          12;
      } else {
        this.overLabelList = [];
        this.dropdownLeft = 0;
      }
    },
    getDomIndexItem(childrenArrayKList) {
      if (isEmpty(childrenArrayKList)) {
        return {
          index: 0,
          width: 0,
          leftWith: 0,
        };
      }
      for (let index = 0; index < childrenArrayKList.length; index++) {
        const domItem = childrenArrayKList[index];
        const domeItemLeft = domItem.offsetLeft;
        if (index != 0 && domeItemLeft == 0) {
          const domBeforeItem = childrenArrayKList[index - 1];
          return {
            index: index,
            width: domBeforeItem.offsetLeft + domBeforeItem.clientWidth,
          };
        }
      }
      return {
        index: 0,
        width: 0,
        leftWith: 0,
      };
    },

12.关于http

域名残缺的时候,添加//会自动将域名补充,但是补充的域名协议是https的而不是http

13.关于页面卡顿排查内存在用问题

我有个echarts图,是从vue2升级成vue3,数据处理改用成对象,此时会导致页面很卡,所以需要查看一下为什么看,排查过程:

控制台中选中:

刷新页面立即点击

页面刷新好之后点击停止

查看内存情况:

第一个XHR占用运行时间最多,点击活动查看:

看图上面两个图可以得到两个信息:1:decryptData在每个微任务都被调用了,2:图中红框框中的两个方法占比过高,即floatAdd和floatSub方法

所以优化思路:

1.decryptData只调一次

在初始化对象时调用并记录数据

2.优化floatAdd和floatSub两个方法

14.关于devtools图标为显示的问题

有点烦,nuxt3项目devtools用的好好的,结果这两天突然失效了找不到了,我再改改东西了,全程使用log+debugger在调测,难受死了。ps:图标是亮的。

百度了一下,百度的问题都不能解决问题,所以想着可能是版本问题,因为之前合并过代码还删除了node_modules,重新pnpm之后版本可能下载的不对应,我查了一下我的devtools版本

我这个版本是1.1.3,就问了同事用了什么版本,同事的是1.0.6。感觉稳定了应该是了,在问了同事用了什么版本的pnpm ,他是8.14.1,我的是8.7.0。哈???为什么我pnpm版本比同事的低但是devtools版本却比他高呢?所以我删掉了node_moduls,全局安装pnpm版本为8.14.1,在重新pnpm install安装依赖。查看devtools版本。

和同事的一样了,运行项目,打开控制台:

终于出来了QAQ,不用在用log+debugger来查看数据了!!!!!!!!!!!!!!

最终解释:我们安装的vue devtools插件的数据是通过项目中的devtools依赖提供了,项目启动的时候,项目中的devtools会收集数据提供给拓展插件。因为浏览器的拓展插件已经亮了但是控制台却没有显示,所以可能就是项目中的devtools未能提供数据导致的,所以可能是版本不对应或者冲突,又因为devtools是依赖于pnpm版本,所以更新pnpm到对应版本即可解决!!

注意:重新安装依赖,需要删掉pnpm-lock.yaml文件,要不然下载的还是原来的版本!!!!!!!!

ps:发生了一件尴尬的事情,因为我在我的分支运行没有vue,切换到dev分支之后删除node_modules重新install下载下来1.0.6版本,这个是因为log文件依赖就是1.0.6版本。运行之后vue图标就出来的,但是切换到我的开发分支之后,因为分支不同,删除node_moduls和pnpm-lock文件之后,重新下载,这时候版本是1.1.4版本,但是运行之后vue图标出来 ,也就是说1.1.3版本出了问题!但是总体的解决思路都是版本问题!!!

15.关于数据共享的一些操作

接手一个模块,使用了vuex,产品数据页面产品数据共享,添加产品、删除产品、切换tab以及一些相关数据操作都是用了vuex,数据太乱了,这个页面升级成vue3的时候,本来打算用props+emit实现算了,但是我想到一些骚操作,使用对象统一数据,要改变的时候直接对这个对象进行赋值不就行了吗,想到要在不同的组件实现数据共享还是对象,我就想到了类,有因为对象是类的实体,所以想到使用代理实现数据响应式。封装类似如下:

export class CommonData {
    num1: string
    num2: string
    private static instanceData: any
    constructor(num1: string, num2: string) {
        this.init(num1, num2)
    }

    /* 初始化 */
    init(num1: string, num2: string) {
        this.num1 = num1
        this.num2 = num2
    }

    static getInstance(num1?: string, num2?: string) {
        if (!CommonData.instanceData) {
            const targetObject = new CommonData(num1, num2)
            const targetReact = new Proxy(targetObject, {
                get(target, key) {
                    return target[key]
                },
                set(target, key, value) {
                    target[key] = value // target就是data对象
                }
            })
            CommonData.instanceData = targetReact
        }
        return CommonData.instanceData
    }
}

使用了单例,保证在一个页面的对象都是同一个,使用了代理,保证响应式。

测试页面如下图所示:

初始化的时候需要保证初始化类先创建对象,所以我是用了v-if控制。

使用的地方如下图所示:

那我们在左边的子组件来修改右边组件的兄弟组件的数据,

右边代码:

左边子组件代码:

点击“点我修改右边数据”,结果如下图所示:

注意:代码会报错,如下图所示

解决的方案就是使用反射代理即可,我的测试vue3项目版本比较高,所以会报这个错误,低版本应该不会报错。

优点是:修改比较明确,缺点就是这个属于定制化的了,如果有修改,需要添加属性。

16.微信开发者工具的一些问题

问题描述:uniapp使用canvas画图表后滚动时,canvas固定不动了,布局也会乱掉。

有个需求,使用需要写图表,我使用的是lime-echart组件库,再微信开发者工具画出来之后会有个固定定位的效果,都会有这个效果。

原来

滚动后

固定在原来占视口所在位置了,问题主要是:微信开发者工具的问题,真机调试或者发布后就不会出现这个问题了。

17.关于vue-charts渲染问题

有个事情,就是我的options改变的时候,数据是改变了 ,图也改变了,但是tooltip的数据还是原来的,数据增加的时候,tooltip的数据可以增加,但是数据变少的时候,tooltip的数据还是原来的,

原因:渲染问题,tooltip的实例还是原来的数据。

解决方法:重新刷新实例:

17.坑,大坑(关于拖动datazoom实现echarts数据归一时,datazoom滚动到原来为止)

这个datazoom拖动左边的之后又滚到最左边了。

问题描述:实现归一,拖动之后数据会原点对齐

这时候就有个问题就是拖动之后又滚回原来的位置

一开始我觉得可能是因为从vue2升级成vue3之后,代码升级的有问题,但是对比代码之后,代码逻辑都是一样的,后面又觉得是数据有问题,但是对比了vue2的走势图之后,数据是一样的,所以在想可能是因为在vue3中使用echarts有问题,后面在归一算法代码中重新赋值了datazoom的end和start,这时候就好了

原因:vue3中使用是最新版本的ecahrts, 在数据更新的时候会导致dataZoom重新渲染。

解决:手动拉dataZoom的时候,记录这个位置,后面在把这位置重新赋值一次就行了。

记录位置

重新赋值

18,依赖问题错误

 ✖ Nuxt Fatal Error                                                                       │
   │                                                                                            │
   │   Error:                                                                                   │
   │                                                                                            │
   │   Vue packages version mismatch:                                                           │
   │                                                                                            │
   │   - vue@2.7.16                                                                             │
   │   - vue-server-renderer@2.6.14                                                             │
   │                                                                                            │
   │   This may cause things to work incorrectly. Make sure to use the same version for both.   │
   │                                                                                          

解决

原先有一个"^",去掉这个“^”就可以了

19.大坑,关于微信小程序ios渲染慢的问题

问题描述:iOS点击echart图标的时候,左右移动日期为响应或者响应慢

如上图:首先点击5月10号这个点移动到左边或者右边的时候,其他数据变量但是日期没有变,ios17出现的问题。

原因:日期用了view包裹住了,换成text即可

无界相关问题

需要后端配合,部署的时候需要部署在同一个域名下,如果不是同一个域名,则需要解决token跨域问题,url带参时需要加token。

例如我这个项目A嵌入的是项目B的,项目A项目域名为:http://zyfp-amp.ssb.gofund.cn/,项目B的实际域名为:http://zyfp-fof.ssb.gofund.cn/。这时候有两种解决方案:

方案一:项目A的无界带入一个token,在项目B中全局做处理,获取无界中的token并进行token置换处理再写道cookie中,实现免登录。

方案二:部署项目B的时候,顺便将项目B部署到项目A的域名下,这个使用nginx和docker实现,需要后端配合。

我们使用了方案二

url无需写域名只需要写路由即可。

对于无界的大部分问题,官方都给了解答。

无界 | 无界 (wujie-micro.github.io)

在一个项目中使用了无界实现单页面应用,首先创建一个项目作为父项目,该项目使用了无界,每个路由下存在一个无界,即一个子项目。父项目的职责有:切换路由时改变路由地址同时获取到地址传递给无界,如果只是query变化,也需要改变导航地址的query;子项目封装一个getRoute,方法的职责是可以监听到路由的变化。同时子项目需要封装一个跳转方法,该方法的职责是用于在改子项目实现跳转,即子页面内部自己跳的时候需要改变导航的url。

1.子应用引用样式不生效和无法获取等问题

例如上面所示,图标“?”是vue2的,但是弹框的内容是vue3的使用了无界进行嵌套。

解决方法:通过无界的props向子应用的html插入样式类名

2.统一的对象实现控制换肤或者传参

例如封装subscribe,封装思路,如果改页面存在无界(即子引用),则使用父引用传入的subscribe,如果没有传入subscribe,则使用子应用自己的subscribe。

例如换皮肤操作是在父应用操作的,子引用也想要跟着改变,这时候就可以通过一个subscribe传给子应用实现。

3.子页面监听url的query问题

这个是一个统一的处理过程,每个项目都是需要做过处理了,主要是分项目,减少服务器压力。一个项目为一个顶级项目,顶级项目下分为多个子项目,这时候需要考虑跳转的问题。

父项目路由:

http://zyfp-fof.ssb.gofund.cn/fof/info-portal?url=/fa/information/search-result?search_word=%E6%B5%8B&search_type=1&dst=null&fund_id=null&flag=0

其中参数url为子项目的路由和子路由所需的query参数

跳转有三个场景:父项目跳不同的子项目,子项目内部跳转,子项目内部跳转。

跳转场景一:父跳子,这个比较容易,直接是路由跳转即可。

跳转场景二:子跳子,统一在父项目处理。

跳转场景三:子项目内部跳转,统一在副项目处理。

场景二和场景三的处理方式的一致的,主要是靠无界的消息通知实现的。

首先子项目跳转的时候需要监听路由,子项目路由方式变化,则通知父项目获取到路由和参数

export function useSubApp() {
    //判断是不是无界子项目,如果是,则通知父项目
    if (EnvTools.isSubApp()) {
        const route = useRoute()
        const config = useRuntimeConfig()
        watch(
            route,
            (to) => {
                window.$wujie?.bus.$emit("subAppRouteChange", { baseUrl: config.public.baseURL, ...to });
            },
            { flush: 'pre', immediate: true, deep: true }
        )
    }
}

子应用需要做一个全局拦截,如果是属于无界子应用的话,路由不让跳转。我负责的项目是nuxt项目,是写在插件中,比较复杂,但是思路大致就是这样了。

父项目接收到无界通知的事件,处理参数。这里涉及的主要是修改链接的url参数

同时实现路由的跳转,子跳子项目在父项目全局判断,获取到路由跳转的通知之后,切换路由并在无界封装的组件修改路由的url参数的值。

子项目内部跳转只要在无界组件中修改参数即可。

部分代码:

4,无界嵌入页面,域名不同token问题

这个就需要在子项目进行token置换或者token写入了,无界props中加token,子项目获取token进行换置或者写入cookie即可达成免密登录

未完待更新.......

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值