需求描述有这样一个需求:页面写了太多详细的表单元素,每个表单元素都用Tooltip组件包裹,不符合要求是的,因为用户需要在form元素的文本过多的时候进行限制,也就是说只有出现省略号的时候才会出现Tooltip组件的封装。比如项目使用的elementUI组件库。一个页面上有太多这样的表单元素:.....稍后会出现不止一个这样的元素如果我每一个都加上disabled属性,那么页面模板元素就有近百个了。显然,我这样添加是非常耗时的。显然,为了追求高效率,我不喜欢一个一个加,然后一个一个加。一个判断性的。在此之前,我们需要确保我们的控件文本的截断是通过CSS代码实现的。即以下代码:.el-input{text-overflow:ellipsis;空白:nowrap;overflow:hidden;}因此,满足上述要求的第一步是判断哪些元素满足截断条件。那么如何判断文本是否被截断了呢?关于这个实现,我觉得elementui的表格组件适合这个场景,所以只需要参考elementui的表格组件的截断判断实现就知道了。没错,我在源码中找到了实现。创建范围元素的核心思想是创建范围元素,通过获取范围元素的宽度,然后通过元素的offsetWidth进行判断。因此,我按照elementui的实现思路完成了这个工具功能。如下所示:functionisTextOverflow(element){//使用范围宽度而不是scrollWidth来确定文本是否溢出//以解决潜在的FireFox错误:https://bugzilla.mozilla.org/show_bug.cgi?id=1074543#c3if(!element||!element.childNodes||!element.childNodes.length){returnfalse;}constrange=document.createRange();范围.setStart(元素,0);range.setEnd(元素,element.childNodes.length);constrangeWidth=range.getBoundingClientRect().width;//如果元素有padding样式,应该添加padding值。constpadding=(parseInt(getStyle(element,'paddingLeft'),10)||0)+(parseInt(getStyle(element,'paddingRight'),10)||0);返回rangeWidth+padding>element.offsetWidth||element.scrollWidth>element.offsetWidth;}functionhasClass(el,cls){if(!el||!cls){返回false;}if(cls.indexOf("")>-1){returnconsole.error(`className不应包含空格!`);}if(el.classList){returnel.classList.contains(cls);}else{return(""+el.className+"").indexOf(""+cls+"")>-1;}}functioncamelCase(name){returnname.replace(/([\:\_\-]+(.))/g,(_,separator,letter,offset)=>offset?letter.toUpperCase():letter).replace(/^moz([A-Z])/,"Moz$1")}//IE版本9以上functiongetStyle(el,styleName){if(!element||!styleName)returnnull;styleName=camelCase(styleName);如果(styleName==='float'){styleName='cssFloat';}try{varcomputed=document.defaultView.getComputedStyle(element,'');返回element.style[styleName]||计算?计算[样式名称]:空;}catch(e){returnelement.style[styleName];}}收集所有的tooltip组件实例这只是第一步的完成,接下来是第二步,也就是我需要收集页面上所有包含tooltip组件的vue组件实例。首先,我们可以确定页面上所有的toolTip组件实例应该都是当前表单组件实例的子组件。因此,我想到了递归收集所有包含tooltip组件的组件实例。代码如下:exportfunctionfindToolTip(children,tooltips=[]){//这里写代码}所有的tooltip组件实例都是vue组件实例的子组件,所以可以知道我们要循环组件实例的子组件,即vm.$children属性。那么tooltip组件的标志是什么?或者我们如何判断子组件实例是tooltip组件呢?也参考了elementuitooltip组件的实现,发现elementuitooltip组件会有一个doDestory方法。所以我们可以据此做出判断。所以递归的方法,我们可以这样写。如下//参数1:子组件实例数组//参数2:收集组件实例数组exportfunctionfindToolTip(children,tooltips=[]){for(leti=0,len=children.length;i`);constreRender=newVue({render:res.render,staticRenderFns:res.staticRenderFns}).$mount(parent);//parent是获取到的tooltip组件实例的根元素所以,接下来在tool函数中,我们可以像这样实现//参数1:当前组件实例this对象//参数2:用于获取tooltip导出函数包裹的子元素的类名isShowToolTip(vm,className="el-input"){//在为了保证能够获取到DOM元素,需要调用一次nextTick方法vm.$nextTick(()=>{constallTooltips=findToolTip(vm.$children);allTooltips.forEach(item=>{//获取子元素constchild=item.$el.querySelector("."+className);//判断是否截断if(!isTextOverflow(child)){//获取渲染元素constparent=item.$el;constres=Vue.compile(`