el-cascader 内容过长,但要完整展示最后一个节点的全部内容问题

1,049 阅读1分钟

问题描述:最近遇到一个需求,使用el-cascader组件,单选选择多层级节点后,选择框内展示不全,业务需要全面的节点可以省略,最后一个节点必须全部展示。

image.png 但当屏幕比较窄时,输入框内的内容显示不全,右侧会溢出省略

image.png 但根据业务的需求,父级节点可以省略,最后一个节点需要完整的展示出来,也就是要把“雁塔区”显示出来,理想效果为

image.png 当时查询了资料,只要给el-sascader设置一个style=“direction:rtl;"就可以实现上图效果,但是这么操作引发一个新的问题

image.png

选择框里所有的内容都居右了。

为此想到了一个办法,比较内容的长度(contentWidth),和el-cacsader中的input的长度(inputWidth)进行比较,当contentWidth > inputWidth是给el-cascader加上style=“direction:rtl;",否则去掉。 但是如何获取contentWidth呢?
首先想到的办法是,使用字符串长度 和inputWidth/fontSize进行对比

<el-cascader
    id="cascader"
    ref="cascder"
    :options="options"
    @change="handleChange"
    style="width:100%;"
    :props="{ checkStrictly: true }"
    clearable>
</el-cascader>

methods: {
    handleChange () {
        let $input = document.querySelector('#cascader .el-input__inner');
        let fz = parsetInt(window.getComputedStyle($input).fontSize);
        let inputWidth = parseInt(window.getComputedStyle($input).width);
        this.$nextTick(() => {
            let checkNode = this.$refs.cascader.getCheckedNodes();
            if (checkNode && checkNode.length) {
                let labels = checkNode[0].pathLabels.join(',');
                if (labels.legnth > inputWidth) {
                    this.$refs.cascader.$el.querySelector('input').style.direction = 'rtl';
                } else {
                    this.$refs.cascader.$el.querySelector('input').style.direction = 'ltr';
                }
            }
        })
    }
}

试了下,有的时候生效有的时候不生效,突然想起font-size实际和高度有关,和宽度没有关系,而且不同的字体的宽度也不同,因此通过字符串长度 和inputWidth/fontSize对比的方式判断是否添加direction无法准确实现需求。
如果生成一个dom,把labels填入,并禁止换行,然后读取长度,是否能实现呢?代码如下:

methods: {
    handleChange () {
        let $input = document.querySelector('#cascader .el-input__inner');
        let inputWidth = parseInt(window.getComputedStyle($input).width);
        this.$nextTick(() => {
            let checkNode = this.$refs.cascader.getCheckedNodes();
            if (checkNode && checkNode.length) {
                let labels = checkNode[0].pathLabels.join(',');
                setTimeout(() => {
                    let $div = document.createElement('div');
                    $div.style = 'white-space:nowrap;';
                    $div.innerText = labels;
                    document.body.append($div);
                    let contentWidth = $div.scrollWidth;
                    if (contentWidth > inputWidth) {
                        this.$refs.cascader.$el.querySelector('input').style.direction = 'rtl';
                    } else {
                        this.$refs.cascader.$el.querySelector('input').style.direction = 'ltr';
                    }
                    $div.remove();
                })        
            }
        })
    }
}

如上代码解决问题。