頁面tooltip組件限制工具函數(shù)使用示例詳解
需求描述
有這樣一個(gè)需求:頁面已經(jīng)寫了太多的詳情表單元素,并且每一個(gè)表單元素都使用了Tooltip
組件來包裹,這樣是不符合需求的,因?yàn)橛脩粜枰薅ó?dāng)表單元素的文本太多時(shí),也就是說出現(xiàn)了省略號(hào)才會(huì)出現(xiàn)Tooltip
組件的包裹。比如項(xiàng)目采用的element UI組件庫。在一個(gè)頁面有太多的這樣的表單元素:
<el-form> <el-form-item label="姓名" prop="name"> <el-tooltip :content="form.name"> <el-input v-model="form.name" disabled="true"></el-input> </el-tooltip> </el-form-item> .....后續(xù)出現(xiàn)多個(gè)這樣的元素 </el-form>
如果我每一個(gè)都加disabled
屬性,那么頁面模板元素有將近一百個(gè),很顯然我這樣加是很耗費(fèi)時(shí)間的,很顯然對(duì)于追求高效的我是不喜歡一個(gè)一個(gè)加,然后一個(gè)一個(gè)判斷的。
在這之前,我們需要確定一點(diǎn),那就是我們控制文本的截?cái)嗍峭ㄟ^CSS代碼來實(shí)現(xiàn)的。也就是如下這段代碼:
.el-input { text-overflow:ellipsis; white-space:nowrap; overflow:hidden; }
因此,完成以上的需求的第一步就是需要先判斷哪些元素滿足被截?cái)嗟臈l件。那么如何判斷文本是否被截?cái)嗄??關(guān)于這個(gè)實(shí)現(xiàn),我想element ui
的表格組件符合這種場景,所以我只需要去參考一下element ui
的表格組件的截?cái)嗯袛鄬?shí)現(xiàn)就知道了。沒錯(cuò),我在源碼中找到了實(shí)現(xiàn)方式。
創(chuàng)建range元素
核心思路就是創(chuàng)建一個(gè)range元素,通過獲取range元素width然后與元素的offsetWidth進(jìn)行判斷就行了。所以,我按照element ui的實(shí)現(xiàn)思路完成了這個(gè)工具函數(shù)。如下所示:
function isTextOverflow(element) { // use range width instead of scrollWidth to determine whether the text is overflowing // to address a potential FireFox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1074543#c3 if (!element || !element.childNodes || !element.childNodes.length) { return false; } const range = document.createRange(); range.setStart(element, 0); range.setEnd(element, element.childNodes.length); const rangeWidth = range.getBoundingClientRect().width; // if the element has padding style,should add the padding value. const padding = (parseInt(getStyle(element, 'paddingLeft'), 10) || 0) + (parseInt(getStyle(element, 'paddingRight'), 10) || 0); return rangeWidth + padding > element.offsetWidth || element.scrollWidth > element.offsetWidth; } function hasClass(el, cls) { if (!el || !cls) { return false; } if (cls.indexOf(" ") > -1) { return console.error(`className should not contain space!`); } if (el.classList) { return el.classList.contains(cls); } else { return (" " + el.className + " ").indexOf(" " + cls + " ") > -1; } } function camelCase(name) { return name.replace(/([\:\_\-]+(.))/g, (_, separator, letter, offset) => offset ? letter.toUpperCase() : letter).replace(/^moz([A-Z])/, "Moz$1") } // IE version more than 9 function getStyle(el, styleName) { if (!element || !styleName) return null; styleName = camelCase(styleName); if (styleName === 'float') { styleName = 'cssFloat'; } try { var computed = document.defaultView.getComputedStyle(element, ''); return element.style[styleName] || computed ? computed[styleName] : null; } catch (e) { return element.style[styleName]; } }
收集所有的tooltip組件實(shí)例
這只是完成了第一步,接下來是第二步,就是我需要將頁面上所有包含tooltip組件的vue組件實(shí)例都要收集起來。首先我們可以確定頁面所有的toolTip組件實(shí)例應(yīng)該都是當(dāng)前這個(gè)表單組件實(shí)例的所有子組件,因此,我想到了遞歸去收集所有包含tooltip組件的組件實(shí)例。代碼如下:
export function findToolTip(children,tooltips = []){ //這里寫代碼 }
所有的tooltip組件實(shí)例都是vue組件實(shí)例的子組件,所以我們可以知道我們?nèi)パh(huán)組件實(shí)例的子組件,即vm.$children
屬性。然后tooltip組件有什么標(biāo)志呢?或者說我們?nèi)绾闻袛嘣撟咏M件實(shí)例就是一個(gè)tooltip組件呢?我又參考了element ui tooltip
組件的實(shí)現(xiàn),發(fā)現(xiàn)element ui tooltip
組件都會(huì)有一個(gè)doDestory
方法。所以我們就可以根據(jù)這個(gè)來做判斷。所以遞歸方法,我們就可以寫好了。如下:
//參數(shù)1:子組件實(shí)例數(shù)組 //參數(shù)2:收集組件實(shí)例的數(shù)組 export function findToolTip(children,tooltips = []){ for(let i = 0,len = children.length;i < len;i++){ //遞歸條件 if(Array.isArray(children[i]) && children[i].length){ findToolTip(children[i],tooltips); }else{ //判斷如果doDestroy屬性是一個(gè)方法,則代表是一個(gè)tooltip組件,添加到數(shù)組中 if(typeof children[i].doDestroy === "function"){ tooltips.push(children[i]); } } } //把收集到的組件實(shí)例返回 return tooltips; } //調(diào)用方式,傳入當(dāng)前組件實(shí)例this對(duì)象的所有子組件實(shí)例 //如:findToolTip(this.$children)
我們找到所有tooltip組件實(shí)例了,接下來,我們要遍歷它,然后判斷是否符合截?cái)鄺l件,不符合我們就需要將組件給銷毀,事實(shí)上,我們直接設(shè)置tooltip組件實(shí)例的disabled屬性為true就可以了。接下來,就是這個(gè)工具函數(shù)的實(shí)現(xiàn)了。如下:
// 參數(shù)1:當(dāng)前組件實(shí)例this對(duì)象 // 參數(shù)2:用于獲取被tooltip包裹的子元素的類名 export function isShowToolTip(vm,className="el-input"){ //這里寫代碼 }
如何修改tooltip組件?
接下來,我們就要實(shí)現(xiàn)這個(gè)工具函數(shù)。首先,我們需要確定的是,因?yàn)閐isabled是props數(shù)據(jù),props是單向數(shù)據(jù)流,vue.js是不建議我們直接修改的,那么我們應(yīng)該如何做到設(shè)置disabled呢?我想了很久,想的辦法就是重新渲染整個(gè)組件,利用Vue.compie API
也就是編譯API直接重新編譯整個(gè)tooltip組件,然后替換原本渲染的tooltip組件。如下:
const res = Vue.compile(`<el-tooltip disabled><el-input value="${ child && child.innerText }" disabled></el-input></el-tooltip>`); const reRender = new Vue({ render:res.render, staticRenderFns:res.staticRenderFns }).$mount(parent);//parent為獲取的tooltip組件實(shí)例根元素
所以,接下來在工具函數(shù)里,我們可以這樣實(shí)現(xiàn):
// 參數(shù)1:當(dāng)前組件實(shí)例this對(duì)象 // 參數(shù)2:用于獲取被tooltip包裹的子元素的類名 export function isShowToolTip(vm,className="el-input"){ //為了確保能夠獲取到DOM元素,需要調(diào)用一次nextTick方法 vm.$nextTick(() => { const allTooltips = findToolTip(vm.$children); allTooltips.forEach(item => { //獲取子元素 const child = item.$el.querySelector("." + className); //判斷是否被截?cái)? if(!isTextOverflow(child)){ //獲取渲染元素 const parent = item.$el; const res = Vue.compile(`<el-tooltip disabled><el-input value="${ child && child.innerText }" disabled></el-input></el-tooltip>`); const reRender = new Vue({ render:res.render, staticRenderFns:res.staticRenderFns }).$mount(parent); } }) }}; }
如何使用這個(gè)工具函數(shù)?
如此一來,就做到了一個(gè)方法完成了以上的需求。如何使用這個(gè)方法呢,很簡單,我們可以在詳情組件里面監(jiān)聽表單詳情數(shù)據(jù)的變化。如:
watch:{ form(val){ if(typeof val === "object" && val && Object.keys(val).length){ //將this當(dāng)做參數(shù)傳入即可 isShowToolTip(this); } } }
關(guān)于這個(gè)需求更好的實(shí)現(xiàn),如有更好的方法,望不吝賜教。
以上就是頁面tooltip組件的限制工具函數(shù)使用示例詳解的詳細(xì)內(nèi)容,更多關(guān)于頁面tooltip組件限制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue+echarts實(shí)現(xiàn)數(shù)據(jù)實(shí)時(shí)更新
這篇文章主要為大家詳細(xì)介紹了vue+echarts實(shí)現(xiàn)數(shù)據(jù)實(shí)時(shí)更新,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04vue在手機(jī)中通過本機(jī)IP地址訪問webApp的方法
這篇文章主要介紹了vue在手機(jī)中通過本機(jī)IP地址訪問webApp的方法,需要的朋友可以參考下2018-08-08vue?el-table中使用el-select選中后無效的解決
這篇文章主要介紹了vue?el-table中使用el-select選中后無效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08詳解vue3?defineModel如何實(shí)現(xiàn)雙向綁定
隨著?Vue?3.3?引入的?defineModel?宏,開發(fā)者可以更加簡潔地實(shí)現(xiàn)組件內(nèi)部的雙向數(shù)據(jù)綁定,下面就跟隨小編一起來學(xué)習(xí)一下如何使用defineModel實(shí)現(xiàn)雙向綁定吧2024-12-12Vue中.env、.env.development及.env.production文件說明
這篇文章主要給大家介紹了關(guān)于Vue中.env、.env.development及.env.production文件說明的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-09-09