【Element UI】使用問題記錄


【Element UI】使用問題記錄

轉載:https://www.cnblogs.com/yangchongxing/p/10750994.html

下載地址:

https://unpkg.com/browse/element-ui@2.11.1/

https://unpkg.com/element-ui@2.11.1/lib/index.js

https://unpkg.com/element-ui@2.11.1/lib/theme-chalk/index.css

=============================================================

1、el-cascader 級聯選擇器

2、重置 form 表單字段的值 或 清除驗證結果

3、form 表單的校驗

4、強制組件渲染

5、設置光標 focus

6、校驗及規則

7、元素默認border-color

8、自定義input樣式

9、from表單數組對象元素的校驗

10、視頻 video 自動適應 el-col 寬度

11、el-table 操作

12、el-tree 操作

13、谷歌瀏覽器 input 自動填充顏色改變或透明

14、可輸入可選擇級聯器組件

15、展開el-tree指定的結點

16、日期、時間、日期時間控件

17、表格樹 el-table-tree-column 問題

18、el-dialog彈出框的body設置高度

=============================================================

1、el-cascader 級聯選擇器

a. 顯示無法清空

<el-cascader 
    ref="mycascader" 
    :options="dataArray" 
    v-model="selectData"
    :show-all-levels="false" expand-trigger="click"
    clearable
    change-on-select>
</el-cascader>

定義一個 ref ,使用 clearValue 方法清空

let obj = {};
obj.stopPropagation = () =>{};
this.$refs.mycascader.clearValue(obj);

clearValue 源碼如下,此處clearValue需要傳入一個事件對象 這里是自己模擬一個事件對象來避免報錯

clearValue: function clearValue(ev) {
    ev.stopPropagation();
    this.handlePick([], true);
}

b. 每一層都選擇

追加 change-on-select 屬性,去掉則只能選擇葉子結點

c. 選中指定的值

let position = [];
position.push(value);
this.$refs.mycascader.handlePick(position);

d. 顯示和隱藏菜單

this.$refs.mycascader.showMenu();
this.$refs.mycascader.hideMenu();

e. 實現可輸入可選擇

<template>
    <el-cascader filterable ref="cstmInputDepartmentDascader" :options="departmentCascader" v-model="departmentValue"
                 :props="{ checkStrictly: true }"
                 :show-all-levels="showAllLevels"
                 :size="showSize"
                 :debounce="500" style="width: 100%"
                 :before-filter="beforeFilterDepartment"
                 @blur="blurDepartment"
                 @focus="focusDepartment"
                 @change="changeDepartment"
                 @visible-change="visibleChange"
                 :placeholder="showPlaceholder" clearable
    ></el-cascader>
</template>

<script>
    import {deepClone} from '@/util/util';
    import {getCascaderAttach} from '@/api/admin/department';

    export default {
        name: "input-department-cascader",
        props: {
            value: {},
            showAllLevels: {
                type: Boolean,
                default: false
            },
            showSize: {
                type: String,
                default: 'medium'
            },
            showPlaceholder: {
                type: String,
                default: ''
            }
        },
        data() {
            return {
                departmentList: [],
                departmentCascader: [],
                departmentCascaderBack: [],
                departmentCascaderLength: undefined,
                departmentValue:[],
                inputDepartmentName: undefined,
                increment: 1
            }
        },
        created() {
            this.getDepartmentCascader();
        },
        mounted() {
            this.init();
        },
        methods: {
            getDepartmentCascader() {
                getCascaderAttach().then(response => {
                    // 部門列表數據 id,parentId,treePosition, 根節點parentId是0,treePosition沒有
                    this.departmentList = response.data.attachData;
                    // 部門級聯數據 label,value,children,disabled
                    this.departmentCascader = response.data.cascaderData;
                    this.departmentCascaderLength = this.departmentCascader.length;
                    // 部門級聯數據備份
                    this.departmentCascaderBack = deepClone(this.departmentCascader);
                    this.init();
                })
            },
            init() {
                if (!this.value) return;
                let value = [];
                let list = deepClone(this.departmentCascaderBack);
                let department = this.getDepartmentById(this.value);
                // 沒有找到就認為是輸入的數據
                if (!department) {
                    list.push(this.getItem(this.value));
                    value.push(this.value);
                } else {
                    if (department.treePosition) {
                        value = department.treePosition.substr(1).split('&');
                    }
                    value.push(this.value);
                }
                this.departmentCascader = list;
                this.departmentValue = value;
            },
            getDepartmentById(id) {
                let department = undefined;
                if (this.departmentList && id) {
                    for (let item of this.departmentList) {
                        if (id === item.id) {
                            department = deepClone(item);
                            break;
                        }
                    }
                }
                return department;
            },
            getItem(name) {
                return {
                    value: name,
                    label: name,
                    children: undefined,
                    disabled: false
                }
            },
            beforeFilterDepartment: function(value) {
                this.inputDepartmentName = value;
                return false;
            },
            blurDepartment() {
                if (!this.inputDepartmentName) return;
                this.inputDepartmentName = this.inputDepartmentName.trim();
                if (this.inputDepartmentName === "") return;
                this.$set(this.departmentCascader, this.departmentCascaderLength, this.getItem(this.inputDepartmentName));
                this.departmentValue = [this.inputDepartmentName];
                this.inputDepartmentName = undefined;
                this.changeDepartment(this.departmentValue);
            },
            focusDepartment() {
                this.$refs.cstmInputDepartmentDascader.$refs.input.$refs.input.select();
            },
            changeDepartment(v) {
                if (v && v.length > 0) {
                    this.$emit('input', v[v.length - 1]);
                } else {
                    this.$emit('input', '');
                }
            },
            visibleChange(flag) {
                if (flag) return;
                if (this.departmentValue && this.departmentValue.length > 0) {
                    let departmentId = this.departmentValue[this.departmentValue.length - 1];
                    let departmentName = '';
                    let department = this.getDepartmentById(departmentId);
                    if (department) {
                        departmentName = department.name;
                    } else {
                        departmentName = departmentId;
                    }
                    this.$emit('departmentChange', departmentId, departmentName);
                } else {
                    this.$emit('departmentChange', '', '');
                }

            },
            setDepartmentValue(v) {
                this.departmentValue = v;
            }
        }
    }
</script>

<style scoped>

</style>

 

filterable 開啟過濾,也就是變成可輸入

before-filter 篩選之前的鈎子,參數為輸入的值,若返回 false 或者返回 Promise 且被 reject,則停止篩選

blur 失去焦點

f、獲取當前的 label

<el-cascader ref="myCascader" :options="myList" v-model="myPosition" @change="myChange" size="small"></el-cascader>

getMyList(){
    this.myList = [];
    // 查詢結果
    getMyListFromDB().then(response => {
        this.myList = response.data;
        if(this.myList.length > 0){
            let v = [];
            this.getDefault(v, this.myList);//取出默認第一個的數組
            this.myPosition = v;//選中第一個
            if (v.length > 0) {
                let selectValue = v[v.length - 1];
                let selectLabel = this.currentLabels(v);
            }
        }
    })
},
getDefault(result, list) {
    if (list) {
        result.push(list[0].value);
        this.getDefault(result, list[0].children);
    }
},
currentLabels(v) {
    let options = this.myList;
    let labels = [];
    v.forEach(value => {
        const targetOption = options && options.filter(option => option['value'] === value)[0];
        if (targetOption) {
            labels.push(targetOption['label']);
            options = targetOption['children'];
        }
    });
    // 拼接標簽數組
    let label = this.$refs.myCascader.showAllLevels ? labels.join('/') : labels[labels.length - 1];
    return label;
},
myChange(v){
    if (v.length > 0) {
        let selectValue = v[v.length - 1];
        let selectLabel = this.currentLabels(v);
    }
}

g、選中可輸入級聯中的所有值

this.$refs.mycascader.$refs.input.$refs.input.select();

 

 

2、重置 form 表單字段的值 或 清除驗證結果

validate

對整個表單進行校驗的方法,參數為一個回調函數。該回調函數會在校驗結束后被調用,並傳入兩個參數:是否校驗成功和未通過校驗的字段。若不傳入回調函數,則會返回一個 promise

Function(callback: Function(boolean, object))

例:this.$refs['myForm'].validate((valid, obj) => {});

validateField

對部分表單字段進行校驗的方法

Function(props: array | string, callback: Function(errorMessage: string))

例:this.$refs['myForm'].validateField('myField', errorMsg => {});

resetFields

對整個表單進行重置,將所有字段值重置為初始值並移除校驗結果

例:this.$refs['myForm'].resetFields();

clearValidate

移除表單項的校驗結果。傳入待移除的表單項的 prop 屬性或者 prop 組成的數組,如不傳則移除整個表單的校驗結果

Function(props: array | string)

例:

this.$refs['myForm'].clearValidate();
this.$refs['myForm'].clearValidate(["myField1","myField2"]);

 

3、form 表單的校驗

表單定義 ref="myForm"

Form Methods 表單方法

validate  對整個表單進行校驗的方法,參數為一個回調函數。該回調函數會在校驗結束后被調用,並傳入兩個參數:是否校驗成功和未通過校驗的字段。若不傳入回調函數,則會返回一個 promise Function(callback: Function(boolean, object))

validateField  對部分表單字段進行校驗的方法 Function(props: array)

清除表單值和校驗信息
this.$refs['myForm'].resetFields();

 
         

清除表單校驗信息
this.$refs['myForm'].clearValidate();

 
         

校驗單校
this.$refs['myForm'].validate(valid => {
  if(valid) {
    // 檢驗成功,沒有問題
  } else {
    // 校驗失敗,有錯誤
  }
});

 
         

校驗字段
this.$refs['myForm'].validateField('name', errorMsg => {
  if (!errorMsg) {
  } else {
    callback(new Error("請輸入姓名"));
  }
});

跟規則校驗,nameEnable == 0時不校驗,其他時候校驗

const checkName = (rule, value, callback) => {
    if (/^[\u4e00-\u9fa5]{2,4}$/.test(value)) {
        callback();
    } else {
        callback(new Error('請輸入漢字'));
    }
};        
settingRules: {
    name: [
        {required: true, message: '請輸入姓名'},
        {validator: checkName, trigger: ['blur','change']}
    ],
}
<el-form-item label="姓名" prop="name" ref="nameField" :rules="nameEnable == 0 ? [] : userRules.name">
    <el-input v-model="user.name" maxlength="4"></el-input>
</el-form-item>

 

4、強制組件渲染

this.$forceUpdate();

5、設置光標 focus

在vue中並不是每次數據改變都會觸發更新dom,而是將這些操作都緩存在一個隊列,在一個事件循環結束之后,刷新隊列,統一執行dom更新操作。 而如果想在DOM狀態更新后做點什么,則需要用到nextTick。在vue生命周期的created()鈎子函數進行的DOM操作要放在Vue.nextTick()的回調函數中,因為created()鈎子函數執行的時候DOM並未進行任何渲染,而此時進行DOM操作是徒勞的,所以此處一定要將DOM操作的JS代碼放進Vue.nextTick()的回調函數中。

通過下面的方式設置光標

this.$nextTick(() => {
    this.$refs['viewFocus'].focus();
});

6、校驗

userRules: {
    name: [
        {required: true, message: '請輸入名稱'}
        {validator: checkName, trigger: ['blur','change']}
    ]
}
const checkName = (rule, value, callback) => {
    isNameExist(name: name}).then(response => {
        if (response.status == 200 && response.data) {
            callback(new Error(response.message));
            return;
        }
    });
    callback();
};

 全局匹配非數字,/[^\d]/g.test(value) true說明有非數字需要提示錯誤,false說明都是數字驗證通過

7、元素默認border-color

正常:border-color: #dcdfe6;

焦點:border-color: #409EFF;

出錯:border-color: #f56c6c;

8、自定義input樣式

input::-webkit-input-placeholder {
    color: #C0C4CC;
    font-size: 14px;
}
input:-moz-placeholder {
    color: #C0C4CC;
    font-size: 14px;
}
input:-ms-input-placeholder {
    color: #C0C4CC;
    font-size: 14px;
}

.imageNameInput {
    margin-top: 2px;
    -webkit-appearance: none;
    background-color: #fff;
    background-image: none;
    border-radius: 4px;
    border: 1px solid #dcdfe6;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    color: #606266;
    display: inline-block;
    color: #303133;
    font-size: 14px;
    height: 40px;
    line-height: 40px;
    outline: 0;
    padding: 0 15px;
    -webkit-transition: border-color .2s cubic-bezier(.645,.045,.355,1);
    transition: border-color .2s cubic-bezier(.645,.045,.355,1);
    width: 160px;
}
.imageNameInput input[type=text]:focus{
    outline: 1px solid #409EFF;
}

9、from表單數組對象元素的校驗

直接給prop綁定為數組下的名稱

參考文章:https://www.cnblogs.com/beileixinqing/p/10969828.html

model: {
    images: undefined,
    imageArray: []
}

imageArray的屬性{name: undefined, url: undefined, del: false}

<el-form-item label="圖片" prop="images">
    <el-input v-model="model.images"></el-input>
    
    <div v-for="(o,i) in model.imageArray" class="image-uploader">
        <el-form-item :prop="`imageArray[${i}].name`" :rules="{ required: true, message: '圖片名稱', trigger: 'blur' }">
            <img :src="o.url" class="image-add">
            <el-input v-model="o.name" maxlength="20"></el-input>
        </el-form-item>
    </div>
</el-form-item>

10、視頻 video 自動適應 el-col 寬度

給視頻指定樣式即可

參考文檔:https://blog.csdn.net/wuqingyou_w/article/details/51671356

video {
        width: 100%;
        height: 100%;
        object-fit:fill;
    }

11、el-table 操作

選中行

給 el-table 定義 ref="menuTable" :data="menuList"

this.$refs.menuTable.toggleRowSelection(this.menuList[0]);

列內容過長隱藏

el-table-column show-overflow-tooltip 當內容過長被隱藏時顯示 true/false
例::show-overflow-tooltip="true"
el-table tooltip-effect 控制顏色 dark/light
例:tooltip-effect="light"

 

 

12、el-tree 操作

a.設置樹選中行的顏色

.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
    background-color: #a6d1ff;
}

b.選中樹結點

// 通過 key 設置某個節點的當前選中狀態,使用此方法必須設置 node-key 屬性
// (key) 待被選節點的 key,若為 null 則取消當前高亮的節點
this.$refs.myTree.setCurrentKey(myKey);

// 通過 node 設置某個節點的當前選中狀態,使用此方法必須設置 node-key 屬性
this.$refs.myTree.setCurrentNode(myNode);

選中單個

this.$refs['catalogTree'].setChecked(catalogId, true, false);

清空選中

this.$refs['catalogTree'].setCheckedKeys([])

 

 

 

13、谷歌瀏覽器 input 自動填充顏色改變或透明

設置黃色背景變成白色背景

input:-webkit-autofill {
 box-shadow: 0 0 0px 1000px white inset !important;
}  
input:-webkit-autofill:focus {
 box-shadow: 0 0 0px 1000px white inset !important;
} 

設置透明:

input:-internal-autofill-previewed,
input:-internal-autofill-selected {
    -webkit-text-fill-color: #FFFFFF !important;
    transition: background-color 5000s ease-in-out 0s !important;
}

不要混合用、親測有效

 

14、可輸入可選擇級聯器組件

<template>
    <el-cascader filterable ref="cstmInputDepartmentDascader" :options="departmentCascader" v-model="departmentValue"
                 :props="{ checkStrictly: true }"
                 :show-all-levels="showAllLevels"
                 :debounce="500" style="width: 100%"
                 :before-filter="beforeFilterDepartment"
                 @blur="blurDepartment"
                 @focus="focusDepartment"
                 @change="changeDepartment"
    ></el-cascader>
</template>

<script>
    import {deepClone} from '@/util/util';
    import {getCascaderAttach} from '@/api/admin/department';

    export default {
        name: "input-department-cascader",
        props: {
            value: {},
            showAllLevels: {
                type: Boolean,
                default: false
            }
        },
        data() {
            return {
                departmentList: [],
                departmentCascader: [],
                departmentCascaderBack: [],
                departmentCascaderLength: undefined,
                departmentValue:[],
                inputDepartmentName: undefined,
                increment: 1
            }
        },
        created() {
            this.getDepartmentCascader();
        },
        mounted() {
            this.init();
        },
        methods: {
            getDepartmentCascader() {
                getCascaderAttach().then(response => {
                    // 部門列表數據 id,parentId,treePosition, 根節點parentId是0,treePosition沒有
                    this.departmentList = response.data.attachData;
                    // 部門級聯數據 label,value,children,disabled
                    this.departmentCascader = response.data.cascaderData;
                    this.departmentCascaderLength = this.departmentCascader.length;
                    // 部門級聯數據備份
                    this.departmentCascaderBack = deepClone(this.departmentCascader);
                    this.init();
                })
            },
            init() {
                if (!this.value) return;
                let value = [];
                let list = deepClone(this.departmentCascaderBack);
                let department = this.getDepartmentById(this.value);
                // 沒有找到就認為是輸入的數據
                if (!department) {
                    list.push(this.getItem(this.value));
                    value.push(this.value);
                } else {
                    if (department.treePosition) {
                        value = department.treePosition.substr(1).split('&');
                    }
                    value.push(this.value);
                }
                this.departmentCascader = list;
                this.departmentValue = value;
            },
            getDepartmentById(id) {
                let department = undefined;
                if (this.departmentList && id) {
                    for (let item of this.departmentList) {
                        if (id === item.id) {
                            department = deepClone(item);
                            break;
                        }
                    }
                }
                return department;
            },
            getItem(name) {
                return {
                    value: name,
                    label: name,
                    children: undefined,
                    disabled: false
                }
            },
            beforeFilterDepartment: function(value) {
                this.inputDepartmentName = value;
                return false;
            },
            blurDepartment() {
                if (!this.inputDepartmentName) return;
                this.$set(this.departmentCascader, this.departmentCascaderLength, this.getItem(this.inputDepartmentName));
                this.departmentValue = [this.inputDepartmentName];
                this.inputDepartmentName = undefined;
                this.changeDepartment(this.departmentValue);
            },
            focusDepartment() {
                this.$refs.cstmInputDepartmentDascader.$refs.input.$refs.input.select();
            },
            changeDepartment(v) {
                if (v && v.length > 0) {
                    this.$emit('input', v[v.length - 1]);
                } else {
                    this.$emit('input', '');
                }
            }
        }
    }
</script>

<style scoped>

</style>

 

15、展開el-tree指定的結點

this.$refs['catalogTree'].store.currentNode.expanded = true
this.$refs['catalogTree'].store.nodesMap["id"].expanded = true

 

16、日期、時間、時間戳控件

<!-- 日期 -->
<el-date-picker v-model.trim="mydate"
                value-format="yyyy-MM-dd"
                format="yyyy-MM-dd"
                type="date"
                placeholder="請選擇日期"></el-date-picker>

<!-- 時間 -->
<el-time-picker v-model.trim="mytime"
                value-format="HH:mm:ss"
                format="HH:mm:ss"
                placeholder="請選擇時間"></el-time-picker>

<!-- 時間戳 -->
<el-date-picker v-model.trim="mydatetime"
                value-format="yyyy-MM-dd HH:mm:ss"
                format="yyyy-MM-dd HH:mm:ss"
                type="datetime"
                placeholder="請選擇時間戳"></el-date-picker>

value-format 控制值的格式,format 控制顯示的格式,這兩個可以不同,根據具體情況選擇控制

 

 17、表格樹 el-table-tree-column 問題

<el-table-tree-column 
    fixed                 是否固定
    :expand-all="false"   是否展開
    :indent-size="20"     子層相對於父層的縮進px
    child-key="children"  子層級數據(數組形式)
    levelKey="level"      層級1,2,3代表第幾層
    treeKey="value"       當前層級的ID, 子層級的parentKey與父層級treeKey一致
    parentKey="parentId"  父層級的ID, 與父層級treeKey一致
    prop="label"          顯示的屬性
    label="名稱"           表頭文字
>

注意:treeKey可以不指定,默認使用對象的ID屬性,若沒有ID屬性則需要使用treeKey明確指定屬性,否則會出現各個層級被同時操作的問題(都展開或關閉)。levelKey在沒有時子層和父層之間沒有縮進。

18、el-dialog彈出框的body設置高度

問題代碼

<el-dialog ref="taskDialog" title="標題" :fullscreen="true"
           :visible.sync="dialogTaskVisible"
           :close-on-click-modal="closeOnClickModal"
           @close="closeTaskDialog">
    <iframe ref="taskIframe" :style="{height: iframeHeight}"
            :src="this.currentTask.url"
            class="iframe" @load="iframeLoad"></iframe>
    <div slot="footer" class="dialog-footer">
        <el-button @click="closeTaskDialog">取消</el-button>
    </div>
</el-dialog>

iframe 的 style 設置 height:100% 沒有撐開 el-dialog__body 部分

解決方式是給 iframe 動態設置具體的高

定義 iframeHeight,給 el-dialog 定義 ref="taskDialog", 綁定 @load="iframeLoad" 加載完成事件,在事件方法中計算高度並設置,

監聽窗口大小變化,在事件方法中計算高度並設置

data() {
    return {
        screenWidth: document.documentElement.clientWidth,
        screenHeight: document.documentElement.clientHeight,
        iframeHeight: '100%'
    };
},
watch:{
    'screenWidth':function(val){ //監聽屏幕寬度變化
    },
    'screenHeight':function(val){ //監聽屏幕高度變化
        this.iframeLoad();
    }
},
mounted() {
    var _this = this;
    window.onresize = function(){ // 定義窗口大小變更通知事件
        _this.screenWidth = document.documentElement.clientWidth; //窗口寬度
        _this.screenHeight = document.documentElement.clientHeight; //窗口高度
    };
},
methods: {
    iframeLoad() {
        this.$nextTick(()=>{
            this.iframeHeight = this.$refs['taskDialog'].$el.offsetHeight - 130 + 'px'; // 用 dialog 總高減去 頭部和底部的高,總寬 offsetWidth
        })
    },
}

 

 

 

 

 

 

 

-


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM