难点

119 阅读4分钟

二次封装elementUI

三个问题:1.透传属性和事件 2.透传插槽 3.透传ref

问题1解决:通过attrs获取父组件传递过来的属性,这些属性在子组件中没用使用props和emits声明,再使用v-bind:'$attrs'绑定在原始elmentUI组件上 实现属性透传。

问题2解决:原始elmentUI组件可能提供了很多插槽,我重新封装的组件可能也需要这些传递插槽,那么我就必须将原始elmentUI组件的插槽全部写完来接受二次封装的组件传递过来的插槽,因为不知道要传递哪些插槽过来,以至于我必须提前写好,这样就很麻烦,我还需要查看文档把所有插槽都写完。第二个问题是,别人在使用我封装的二次组件时,肯呢个并没有传递那么多插槽,但是我在封装原始elmentUI组件时,把这个组件的插槽全部都写完了。这样可能会导致一些问题,这个原始elmentUI组件在设计时会判断是否传递插槽,传了做啥事,没传做啥事,那么这个逻辑会永远判断为传递了所有插槽,无论二次封装的组件是否传递了插槽,可能会产生一些问题。。。 所以解决目标是:二次封装的组件传几个插槽,内部原始elmentUI组件就传递几个插槽,实现动态插槽。那么就需要在封装的组件内获取外部到底传进了几个插槽,传递了哪些插槽。使用$slots获取传进来的插槽,再使用v-for遍历,动态生成插槽。

computed 拦截v-model

v-model 是一个语法糖,传递了modelValue这个属性给子组件,子组件可以使用这个值,当子组件在改变这个值时,应该抛出事件 emit:update:modelValue。 问题是,子组件拿到modelValue可能会乱操作,可能拿着modelValue使用v-model绑定到一些其他组件身上,导致modelValue数据的某些字段直接在子组件里被修改了。就是父组件使用v-model传递了modelValue这个对象,子组件拿到modelValue这个对象后把他的某个属性使用v-model绑定到了一个文本框,文本框一改变,就代表子组件直接修改了modelValue,打破了单向数据流,应避免子组件直接修改父组件传递过来的数据。

解决:在父组件和子组件的文本框之间,夹一个计算属性。即父组件的数据来到子组件时,不直接使用,,把他放到计算属性,要用的时候,从计算属性中拿放到文本框,文本框改动时,改的是计算属性,计算属性不直接修改数据,然后抛出一个事件。

当你需要将计算属性与 v-model 结合使用时,可以通过 getset 实现双向绑定。

可写计算属性:通过 computed({ get, set }) 创建,支持读取和设置时的自定义逻辑。

脚本加载失败后如何重试?

在生产环境中我们会在html文件中引入很多的js脚本文件,但是可能会出现网络问题或者其他问题导致脚本加载失败,现在很多网站都是单页面应用,脚本加载失败页面是没办法正常渲染的。就需要解决这个问题。

可以对加载失败的脚本进行重试,重新加载多个备用域名下的js文件。

  1. 什么时候重试?
  2. 如何重试?

1.js加载失败时重试,怎么知道js加载失败了?script元素上面有一个事件onerror事件,但是工程化后的html文件中的script元素是打包工具帮我们生成的,不好直接在上面监听error事件,处理比较麻烦。那怎么监听?想在一个单独的地方统一监听这个error事件。-> 事件委托,给整个窗口增加一个监听error事件。在页面最开始的地方加上这个监听函数,以实现在所有js文件之前监听? 有个问题,还是没监听到error事件,因为这个事件是不支持冒泡的,script元素上的错误事件没有冒泡到window上面去。那我们就在捕获阶段去处理这个事,addEventListener第个参数设置为true。并且我们捕获错误只捕获脚本加载错误,要吧其他错误都过滤掉,使用事件参数e中的一些属性,脚本执行错误的事件类型为ErrorEvent要过滤掉,还有就是标签错误,如img标签的图片加载错误,所以要把e.target不为“script”的错误也要过滤掉。这样就实现了只处理脚加载错误。第一个问题搞定了。

准备好备用域名,捕获到一个script错误时就换域名重试。这例需要获取script标签的src属性,然后获取他的路径值,将路径值和域名进行组合得到新的域名,然后创建script元素并设置src为新域名,再把这个元素插入到旧script元素前面,然后可以再把这个发生加载错误的script原始移除了。问题:有时候script标签是有顺序的,要按照顺序进行执行,所以我们进行重试时也要保证顺序。保证在加入新元素之前停止解析后面的脚本,使用document.wirte来加入新得到的script元素,可以阻塞页面解析。

扩展:使用构建工具的插件来完成 html-plugin 让插件去注入这些脚本;考虑到脚本中可能带的一些关键字,资源提示符,要做特殊处理。