zoukankan      html  css  js  c++  java
  • 【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=" 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=" 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
            })
        },
    }

    -

  • 相关阅读:
    结对作业
    黄金分割点(第五周 c语言版)
    小程序(第四周)
    读程序作业(第三周)
    vs2013的安装及测试(第三周)
    学习进度条(第6周)
    努力爬的蜗牛
    学习日记1
    团队作业(七)
    团队作业(六)
  • 原文地址:https://www.cnblogs.com/yangchongxing/p/10750994.html
Copyright © 2011-2022 走看看