环境搭建

https://element.eleme.cn/#/zh-CN/component/installation


1、根据官网提示,npm i element-ui


小坑:

终端在运行,无法安装

解决办法:ctrl + C停止终端


安装完成后,可在package.json查看到element UI的版本

"dependencies": {

"element-ui": "^2.15.3",

"vue": "^2.5.2",

"vue-router": "^3.0.1"

},


2、根据提示需要输入npm audit fix :检测项目依赖中的漏洞并自动安装需要更新的有漏洞的依赖,而不必再自己进行跟踪和修复。

https://blog.csdn.net/weixin_40817115/article/details/81007774


3、在 main.js 中导入element-ui:(这些官网都有)

import ElementUI from 'element-ui'

import 'element-ui/lib/theme-chalk/index.css';


Vue.use(ElementUI);


4、随便找一个组件模板,复制template里的代码,运行测试。






好用的插件

【pinyin-match】拼音匹配

https://blog.csdn.net/Jie_1997/article/details/125557403

评价:这个插件其实不好用,需要切换成英文输入法才识别拼音。

1、安装:npm install pinyin-match --save

2、在组件中引入:import PinYinMatch from "pinyin-match";

3、data中定义两个数组:

listCharge: [], //初始的数据

listCharge2: [], //拼音匹配后的结果

4、el-select标签中定义属性:

注1:@visible-change表示下拉框隐藏的时候触发的事件。用来重置下拉选项。因为当你输入过拼音后,搜索结果变少了。所以需要借助这个事件来重置下拉选项。

注2:filterable表示下拉框可以有输入功能。

注3:filter-method表示数据过滤使用的方法。这个方法默认传入一个参数value,表示当前输入的值。如果想要传入自定义的参数,可以这样写:(value) => xxx(value, 自定义参数)

<el-select v-model="xxx"

@visible-change="handleEventrProject"

filterable

:filter-method="matchPinYin2">

5、@visible-change绑定的方法

//当下拉框消失,要让下拉选项变回到原来的,含有所有选项

handleEventrProject() {

this.projectList2 = this.projectList;

this.listCharge2 = this.listCharge;

},

6、filter-method绑定的方法

matchPinYin2(val) { //这个val是默认传入的

if (val) {

let result = [];

this.listCharge.forEach((item) => {

//匹配不上,则返回false。

//匹配上,则返回包含两个元素的数组,第一个元素表示从第几位开始匹配,第二个元素表示匹配上了几个。

let matchRes = PinYinMatch.match(item.xxx, val); //这里xxx是label对应的属性

if (matchRes) {

result.push(item);

}

});

this.listCharge2 = result;

} else {

this.listCharge2 = this.listCharge;

}

},



【element-china-area-data】省市区选择器

博文:https://blog.csdn.net/bamboozjy/article/details/82220894

官网:https://blog.csdn.net/bamboozjy/article/details/82220894


安装插件:npm install element-china-area-data -S


在需要使用的页面,进行引入:

import {

provinceAndCityData, //省市二级联动数据(不带“全部”选项)

regionData, //省市区三级联动数据(不带“全部”选项)

provinceAndCityDataPlus, //省市区三级联动数据(带“全部”选项)

regionDataPlus,省市区三级联动数据(带“全部”选项)

CodeToText, //是个大对象,属性是区域码,属性值是汉字 用法例如:CodeToText['110000']输出北京市

TextToCode //是个大对象,属性是汉字,属性值是区域码 用法例如:TextToCode['北京市'].code输出110000,TextToCode['北京市']['市辖区'].code输出110100,TextToCode['北京市']['市辖区']['朝阳区'].code输出110105

} from 'element-china-area-data'


示例:

<template>

<div style="margin: 50px;">

<el-cascader size="large"

:options="options"

v-model="selectedOptions"

@change="addressChange">

</el-cascader>

</div>

</template>

<script>

import { regionData, CodeToText } from "element-china-area-data";

export default {

data() {

return {

options: regionData,

selectedOptions: [],

};

},

methods: {

addressChange(arr) {

console.log(arr);

console.log(CodeToText[arr[0]], CodeToText[arr[1]], CodeToText[arr[2]]);

},

},

};

</script>


【el-table-infinite-scroll】无限加载数据

https://blog.csdn.net/cxwtsh123/article/details/127806045


安装:npm install --save el-table-infinite-scroll


在main.js中引入:import ElTableInfiniteScroll from 'el-table-infinite-scroll';

在main.js中使用:Vue.use(ElTableInfiniteScroll)


坑:启动以后报错!!!说vue缺少一个东西。我推测我安装了最新版的el-table-infinite-scroll,它需要用到vue3中的依赖。但是我用的是vue2,所以我指定了版本1.0.10


临时记一下:

1、2、6

v-el-table-infinite-scroll="loadMore"

ref="tableRef"

height="670"

stripe

3、5

loadMore() {

if (this.queryParams.pageNum * this.queryParams.pageSize > this.total) {

console.log("已经到底啦!");

return;

}

this.queryParams.pageNum++;

this.loading = true;

listUser(this.queryParams).then(

(response) => {

const newData = response.rows;

this.userList = this.userList.concat(newData);

this.loading = false;

}

);

},

4、handleQuery

if (this.queryParams.pageNum != 1) {

this.$refs.tableRef.bodyWrapper.scrollTop = 0;

}

7、分页改成15,把getList替换成handleQuery


关键步骤其实就这几步:

1)设置表格高度

2)给表格添加属性v-el-table-infinite-scroll,绑定触底事件

3)触底事件给分页+1,然后数组拼接。

const newData = response.rows; //新数据

this.xxxData= this.xxxData.concat(newData); //用concat拼接

4)让表格回到顶部:先让table绑定ref,再执行:

if (this.queryParams.pageNum != 1) {

this.$refs.xxxRef.bodyWrapper.scrollTop = 0;

}

5)触底

if (this.queryParams.pageNum * this.queryParams.pageSize > this.total) {

console.log("已经到底啦!");

return;

}


子组件:

1、标签

<el-table :data="tableData"

v-el-table-infinite-scroll="load"

:infinite-scroll-disabled="disabled"

:height="500"

style="width: 100%; margin-top: 20px;"

:stripe="true"

:border="true"

:highlight-current-row="true">

2、参数

props: {

tableData: { type: Array },

tableColumn: { type: Array },

disabled: { type: Boolean, default: true },

scrollLoading: { type: Boolean },

},

3、在js中定义方法

load() {

console.log("这里是子组件,下拉滚动加载触发了……");

//子组件调用父组件中的方法,用$emit

this.$emit("update:scrollLoading", true);

this.$emit("loadMore"); //自定义事件loadMore

},

4、监听

watch: {

scrollLoading(val) {

this.scrollLoading = val;

},

},


父组件

1、标签

<HhmTable :tableData="tableData"

:tableColumn="tableColumn"

@loadMore="loadMoreToDo"

:scrollLoading.sync="scrollLoading"

:disabled="disabled"

ref="hhm_table_ref"></HhmTable>

2、data

scrollLoading: false, //是否加载

disabled: false, //是否不能加载

3、自定义事件

//滚动加载更多数据

loadMoreToDo() {

console.log("这里是父组件");

if (this.disabled) return;

this.searchModel.pageNum++; //加载下一页内容

this.$http

.get("/processHis/page", {

params: this.searchModel,

})

.then((e) => {

const newData = e.data.data.records;

console.log("新的数据", newData);

const newTableData = this.tableData.concat(newData); //合并数组

console.log("表格数据:", newTableData);

this.tableData = newTableData;

});

},







【v-infinite-scroll】无限加载数据

这个可以用在div身上。

v-infinite-scroll="loadMore"




【sortablej】表格的行列可拖拽

快速上手示例:https://blog.csdn.net/weixin_45232247/article/details/125411977

sortablej官网:http://www.sortablejs.com/


安装插件:

npm install sortablejs --save

引入插件:

import Sortable from "sortablejs";


data中分别定义初始的prop列和变化后的prop列:

表格的动态列

dropCol: [{

序号",

prop: "index",

},

{

贡献值",

prop: "contributionValue",

}

],

生命周期:

mounted() {

// 阻止默认行为

document.body.ondrop = function(event) {

event.preventDefault();

event.stopPropagation();

};

this.$nextTick(() => {

this.columnDrop(); //列拖拽

})

},

方法实现:

//列拖拽

columnDrop() {

const wrapperTr = document.querySelector(".el-table__header-wrapper tr");

this.sortable = Sortable.create(wrapperTr, {

animation: 180,

delay: 0,

onEnd: (evt) => {

const oldItem = this.dropCol[evt.oldIndex];

this.dropCol.splice(evt.oldIndex, 1);

this.dropCol.splice(evt.newIndex, 0, oldItem);

},

});

},


难点1:有多行tr时,选择问题。

document.querySelector(".el-table__header-wrapper tr");

querySelector是查询所有???

后代选择器,所有儿子、孙子tr

Element UI 个人笔记_ui


Element UI 个人笔记_组件库_02


改用:

const wrapperTr = document.querySelectorAll(".el-table__header-wrapper tr");

this.sortable = Sortable.create(wrapperTr[1], {这里看情况选择第几行


小胖还用了mounted中的setTimeout来解决,更好的是this.$nextTick(()=>{...})


难点2:含有插槽的复杂场景:

https://huaweicloud.csdn.net/638ee135dacf622b8df8d59a.html?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~activity-1-121464734-blog-125693810.235^v36^pc_relevant_default_base3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~activity-1-121464734-blog-125693810.235^v36^pc_relevant_default_base3&utm_relevant_index=2

Element UI 个人笔记_ui_03



<!-- 循环渲染字段,实现列可拖拽,需要让prop绑定dropCol -->

<el-table-column v-for="(item, index) in colList"

:key="`col_${index}`"

:prop="dropCol[index].prop"

:label="item.label">


<!-- 处理特殊数据,用具名插槽 -->

<template v-slot="scope">


<span v-if="dropCol[index].prop === 'index'">

{{taskList.indexOf(scope.row) + 1}}

</span>


<span v-else-if="dropCol[index].prop === 'startAndEndTime'">

{{parseTime(scope.row.startTime, "{h}:{i}") + " - " + parseTime(scope.row.endTime, "{h}:{i}")}}

</span>


<span v-else>

{{ scope.row[dropCol[index].prop] }}

</span>


</template>

</el-table-column>


【v-dialogDrag】弹框可拖拽

https://blog.csdn.net/Gx0525_/article/details/122713157?spm=1001.2014.3001.5506


这不是插件。

不知道是不是只能用在el-dialog身上。




【vue-count-to】动画:让数字滚动加载

https://blog.csdn.net/m0_51431448/article/details/125794123


安装:npm install vue-count-to

引入组件:import CountTo from 'vue-count-to'

注册组件:

components: {

CountTo

},


模板中使用:

<CountTo

:startVal='startVal'

:endVal='endVal'

:duratinotallow='duration'

/>

属性说明:

duration是动画的时间,单位为毫秒。


注意:用了这个插件以后,会自动把数字转换成国外的表达方式,即每三位用逗号隔开。


示例:

<div slot="header">{{item.title}}</div>

<div>

<CountTo :startVal="0"

:endVal="item.value"

:duration="3000" />

</div>




【vue-print-nb】打印

快速上手

https://blog.csdn.net/weixin_44867717/article/details/128168044


1、在控制台安装插件:npm i vue-print-nb

2、在main.js中引入插件:import Print from 'vue-print-nb'

3、在main.js中全局引用该插件:Vue.use(Print)

4、在组件中使用插件:

<div id="single-info">这是要打印的内容</div>


<el-button

id="info-btn"

v-print="'#single-info'"

@click="prints" >打印</el-button >

注:在按钮上使用v-print,绑定id,这个id就是你想要打印的内容。



批量打印

我的思路:把所有要打印的内容放在一个div中,然后用css让它隐藏。




坑:表格显示不全

https://blog.csdn.net/liangyiyiliang/article/details/124451553


这是网页:

Element UI 个人笔记_组件库_04


这是打印预览:

Element UI 个人笔记_ui_05


原因:原来是el-table 会计算100%宽度为具体多少px 然后再计算出每一列的宽度,通过设置table>colgroup>col 的width属性来设置每一列的宽度。问题是浏览器的打印区域的100%的具体px(如这里的1388px)肯定与打印纸的宽度不一致,所以导致部分区域打印不出来!







------------------【basic】-----------------------

【button】按钮

属性

type

按钮的颜色


注:用vsCode编写这个属性,没有提示,不要害怕,这是正常的。

primary:蓝色

success:绿色

info:灰色

warning:橙色

danger:红色



示例:

<el-button type="primary" @click="xxx()">发送</el-button>



------------------【form】-----------------------

【radio】单选框

https://element.eleme.cn/#/zh-CN/component/radio

标签【radio-group】单选框组

要使用 Radio 组件,只需要设置v-model绑定变量,选中意味着变量的值为相应 Radio label属性的值,label可以是String、Number或Boolean。

角色类型">

表单名.字段名">

值1">管理员</el-radio>

值2">学生</el-radio>

</el-radio-group>

</el-form-item>

注:

  1. 本来以为label是标签,结果这里label就是值!而展示的内容直接写在标签体里面。
  2. radio-group绑定的是一个普通对象。

属性【label】标签的值

本来以为label是标签,结果这里label就是值!而展示的内容直接写在标签体里面。




【checkbox】多选框

标签【checkbox-group】多选框组

checkbox-group元素能把多个 checkbox 管理为一组,只需要在 Group 中使用v-model绑定Array类型的变量即可。 el-checkbox 的 label属性是该 checkbox 对应的值,若该标签中无内容,则该属性也充当 checkbox 按钮后的介绍。label与数组中的元素值相对应,如果存在指定的值则为选中状态,否则为不选中。


<el-checkbox-group v-model="checkList">

<el-checkbox label="复选框 A"></el-checkbox>

<el-checkbox label="复选框 B"></el-checkbox>

<el-checkbox label="复选框 C"></el-checkbox>

</el-checkbox-group>


data() {

return {

checkList: ["复选框 A"],

};

},


1:checkbox-group绑定的是一个数组!!!

2:label是值,不是标签

3:checkbox-group设置了样式font-size=0,导致文本、<i>都看不见了!!!可以重新定义样式来解决。



属性【label】标签的值

本来以为label是标签,结果这里label就是值!


展示的内容:直接写在标签体里面。

注:如果标签体里面没有内容,则label也会作为内容展现出来。


也许可以用true-label和false-label来实现无展示的内容的效果。

Element UI 个人笔记_vue_06





需求:如何让方框在内容右侧?









【input】输入框

需求:修改样式

::v-deep .el-input__inner {

border-radius: 0px;

border-top-width: 0px;

border-left-width: 0px;

border-right-width: 0px;

border-bottom-width: 1px;

/*outline: medium;*/

}




需求:只能输入整数(正则表达式)

由于type=number不能限制长度,而且可以输入e、小数点、Π等数学相关的符号,不好用!

所以改用type=text,配合正则表达式。

type="text"

maxlength="3"

oninput="value=value.replace(/[^\d]/g,'')"

notallow="value=value.replace(/[^\d]/g,'')"的正则表达式来把除了数字以外的字符都变为空。



【select】选择器

基本结构

<template>

<el-select v-model="xxx" placeholder="请选择">

<el-option

v-for = "iteminxxx"

:key = "item.xxx"

:label = "item.xxx"

:value = "item.xxx">

</el-option>

</el-select>

</template>

说明:这个属性key,我感觉没用,但是不加的话会有warning,所以还是加上吧:

Element UI 个人笔记_前端_07


坑:el-select只显示值,不显示标签。el-option的标签可以正常显示。

原因:select和option的value的类型匹配不上!经常都是string和int搞错了。

属性【filterable】可搜索

是否可搜索,就是变成输入框,搜出label





【cascader】级联选择器

<el-cascader

v-model = "xxxValue"

:options = "xxxOptions"

:props = "{ expandTrigger: 'hover' }"

@change = "触发的方法" >

</el-cascader>

【v-model】选中的值

前端填入这个级联选择器的值,数组的形式,从0开始分别表示一级二级三级。


属性【options】选项值

可选择的项,这个数组必须是如下结构(也可以通过Props属性自定义键名):

{value:

label:

children: [

{

value:

label:

}

]}

需要通过一个接口去后端捞出所有选项,再赋值给options。(通常我们在created生命周期中调用方法,一开始就捞到这些数据)

dictGroup({}).then((resp) => {

为什么要先清空?

resp.data.forEach((item) => {

const v = item.id;

let row = { label: item.groupName, value: item.id, children: [] };//options固定的结构

item.groupList.forEach((y) => {

row.children.push({ label: y.staffName, value: y.staffId });

});

this.staffTreeOption.push(row);

});

this.getList();

});




属性【props】自定义键名

Element UI 个人笔记_element_08


用法:先在标签中定义props,然后在data中指定value、label、children


示例:

在标签中定义props

<el-cascader v-model="address"

:options="cityMap"

:props="props111">

</el-cascader>

在data中指定

props111: {

label: "province",

value: "code",

children: "cities",

},





事件【@change】

当选中节点变化时触发。即:级联选择器选好后会触发。比如我这里绑定一个自定义的方法handleChange,默认会传入event(就是这里的value)

handleChange(value) {

if (this.deptValue != null){

this.listQuery.xxx= this.xxxValue[1]; //可以用props中的一个配置,关掉这个复杂的父子结构,从而只显示子节点的数据,就不用这样麻烦了,而且父子结构会影响到v-model的值,从而让后端取不到。

}

}

emitPath建议设为false

在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值



【DatePicker】日期选择器

示例:

<el-date-picker v-model="changeTimeParam"

type="daterange"

value-format="yyyy-MM-dd"

range-separator="至"

start-placeholder="开始日期"

end-placeholder="结束日期"

size="mini"

style="width: 250px">

</el-date-picker>

属性【value】绑定数据

或者自定义一个v-model来绑定数据。


当我们把type设为daterange时,打印一下value绑定的数据对象的格式,发现是数组:

Element UI 个人笔记_vue_09


注:这个数组对象不能为空,否则报错。请留意后期查询赋值时如果为空,给它设为两个元素都是空字符串的数组。

坑:Element提供的清空按钮,会把这个数组变成null,导致报错!!!


属性【type】选择器的类型

值1:daterange,日期范围。此时value是一个数组,有开始日期和结束日期。

值2:date,日期



属性【value-format】日期格式(和后端联调)

值1:yyyy-MM-dd,年月日

值2:value-format="yyyy-MM-dd HH:mm:ss"


属性【format】日期格式(前端展现)

可以随心所欲地搭配yyyyMMdd这些。


示例:

format="yyyy年MM月dd日"


属性【prefix-icon】设置头部的图标

默认:el-icon-date

效果:

Element UI 个人笔记_前端_10


我试了一下,可以设置它的值为none,就能去掉图标。

prefix-icon="none"


设置宽度

只能自定义一个行内样式来修改宽度

style="width: 250px"




事件【change】

触发用户确认选定的值时


组件绑定值。格式与绑定值一致,可受 value-format 控制






【Form】表单

样式:简单粗暴去掉所有选择器的外框

定义一个样式xxxclass,想让哪个选择器的外框隐藏,就给他加这个class

.xxxclass /deep/ * {

border: none;

}


属性【inline】变为行内元素

设置 inline 属性可以让表单域变为行内的表单域

默认会换行的,不实用!

格式:

:inline="true"




标签【el-form-item】



表单验证(常规)

https://www.cnblogs.com/wozho/p/10955525.html

环境搭建:安装async-validator(Element自带了,我还搞了半天,被我自己蠢死了。)


1、在<el-form>中设置参数:

:model="要检查的表单对象"

:rules="rules"

ref="表单标识名"


2、在<el-form-item>中设置参数:

prop的属性来自第1步中model表单对象中的属性。

“Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可。”

prop="属性名"


3、定义表单验证的规则rules

rules: {

xxx: [

{ required: true, message: "xxx不能为空", trigger: "blur" },

],

changeTime: [

{ required: true, message: "出院时间不能为空", trigger: "blur" },

]

},


4、按钮的方法传入表单:@click="saveUser('表单名')"


5、方法里怎么写:

saveUser(formName) {

this.$refs[formName].validate((valid) => {

if (valid) {

合法的情况

……

} else {

//不合法的情况

……

return false;

}

});

},


表单校验(自定义校验规则)

需求:手机号格式校验、身份证格式校验

1、rules里面:

rules: {

idCard: [

{ required: false, validator: checkIdCard, trigger: "change" },

],

membersPhone: [

{ required: false, validator: checkPhone, trigger: "blur" },

],

2、data中定义属性(注意,这不是在return中定义的,是在外层)

data() {

// 身份证验证

var checkIdCard = (rule, value, callback) => {

const idcardReg =

/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;


if (!value) {

//暂时可以为空

// return callback(new Error("身份证号不能为空"));

callback(); //注:callback方法必须被调用

}


//有值,才进行格式校验

if (value) {

setTimeout(() => {

if (idcardReg.test(value)) {

this.selectBirAndSex(value);

var now = new Date();

var birthday = new Date(this.xxx.birthday);

if (birthday.getTime() > now.getTime()) {

callback(new Error("身份证号异常,出生日期异常"));

}

callback();

} else {

callback(new Error("身份证格式不正确"));

}

}, 100);

}

};


//手机号校验

var checkPhone = (rule, value, callback) => {

let regPone = null;

let mobile = /^((13|14|15|17|18)[0-9]{1}\d{8})$/; // 最新16手机正则

let tel = /^((0\d{2,3}\d{7,8})|(1[3584]\d{9}))$/; // 座机


if (!value) {

//暂时可以为空

// return callback(new Error("身份证号不能为空"));

callback(); //注:callback方法必须被调用

}


//有值,才进行格式校验

if (value) {

setTimeout(() => {

// Number.isInteger是es6验证数字是否为整数的方法,但是我实际用的时候输入的数字总是识别成字符串

// 所以我就在前面加了一个+实现隐式转换

if (!Number.isInteger(+value)) {

callback(new Error("请输入数字值"));

} else {

if (value !== null && value.charAt(0) === "0") {

// charAt查找第一个字符方法,用来判断输入的是座机还是手机号

regPone = tel;

} else if (value !== null && value.charAt(0) !== "0") {

regPone = mobile;

}

if (regPone.test(value)) {

callback();

} else {

callback(

new Error("请输入正确的电话格式,其中座机(区号+座机号码)")

);

}

}

}, 100);

}

};


3、方法中定义

/** 身份证查询出生日期,性别 */

selectBirAndSex(val) {

let iden = this.form.idCard;

let sex = null;

let birth = null;

let myDate = new Date();

let month = myDate.getMonth() + 1;

let day = myDate.getDate();

let age = 0;


if (val === 18) {

age = myDate.getFullYear() - iden.substring(6, 10) - 1;

sex = iden.substring(16, 17);

birth = iden.substring(6, 10) + "-" + iden.substring(10, 12) + "-" + iden.substring(12, 14);

if (iden.substring(10, 12) < month || iden.substring(10, 12) == month && iden.substring(12, 14) <= day)

age++;

}

if (val === 15) {

age = myDate.getFullYear() - iden.substring(6, 8) - 1901;

sex = iden.substring(13, 14);

birth = "19" + iden.substring(6, 8) + "-" + iden.substring(8, 10) + "-" + iden.substring(10, 12);

if (iden.substring(8, 10) < month || iden.substring(8, 10) == month && iden.substring(10, 12) <= day)

age++;

}

if (sex % 2 === 0)

sex = '1';

else

sex = '0';

this.form.patientSex = sex;

this.form.patientAge = age;

}



4、标签中的使用

<el-form-item label="联系电话"

prop="membersPhone">


<el-form-item label="身份证号码"

prop="idCard">








方法:表单验证-重置

定义一个方法:

resetForm(formName) {

this.$refs[formName].resetFields();

}

在表单标签中定义好表单的名称,用ref来定义。

然后调用的时候,传入表单的名称。


坑:公司场景遇到一个问题,想要重置表单,却获取不到vueComponent实例对象。从而无法使用resetFields方法。

解决方案:原来是要传入表单的名称,而不是表单对象












------------------【data】-----------------------

【Table】表格

功能:斑马纹【stripe】

stripe属性可以创建带斑马纹的表格


功能:排序【sortable】

在想要排序的列上面,加属性sortable即可。


注意:如果你使用了<template slot-scope=scope>的写法,则还需要在列标签上,加上prop属性,绑定那个字段!!!


如果你想让某一列初次加载的时候就有一个默认排序,而不是点击后才排序,可以这么做:

在<table>中添加属性default-sort

指定要排序的字段prop

指定排序的方式:order、ascending、descending

:default-sort = "{prop: 'xxx', order: 'descending'}"






功能:表尾合计行【show-summary】

首先必须要在<el-table>中使用属性show-summary来开启这个表尾合计行的功能。


方法1:无其他配置。只要是数值,就合并。

这种方法的可用性不太好,如果字段里有那种不需要合计的编号,也会错误地相加。


方法2:在<el-table>中使用属性summary-method触发一个自定义方法,注意上面那个属性show-summary还是要写的!

这个自定义方法默认携带一个参数,我打印出来,结果发现打印了两次???

Element UI 个人笔记_element_11


属性columns:第一次的columns是0条数据,第二次是5条数据,对应5列字段。

属性data:就是row的集合,就是每条记录,就是每行记录,和后端查出来的结果一致


其中,集合columns的每一项对象的属性中,这个property我经常用到,判断和prop是否相等。

Element UI 个人笔记_element_12



示例:

getSummaries(param) {

console.log("看看合计方法携带的参数:", param);

const { columns, data } = param; //解构表达式,对象解构

const sums = [];

columns.forEach((column, index) => {

if (index === 0) {

//如果是第1列

sums[index] = "总价"; //直接设为文字“总价”

return;

}

//我直接根据字段名称,粗暴判断!!!

if(column.property != 'amount2') return;


const values = data.map((item) => Number(item[column.property])); //把字段的属性值转为数字

//1、如果是数字

if (!values.every((value) => isNaN(value))) {

//这是什么语法???看不懂

//求和的算法

sums[index] = values.reduce((prev, curr) => {

const value = Number(curr);

//1.1、如果当前值是正常的数字,就进行相加

if (!isNaN(value)) {

return prev + curr;

}

//1.2、如果当前值不正常,就跳过当前值

else {

return prev; //(由于必须返回,所以这里返回上一次的值)

}

}, 0); //这整个箭头函数都是回调函数,0是初始值

sums[index] += " 元";

}

//2、如果不是数字

else {

sums[index] = "N/A";

}

});

return sums;

},





事件:单选

“Table 组件提供了单选的支持,只需要配置highlight-current-row属性即可实现单选。之后由current-change事件来管理选中时触发的事件,它会传入currentRow,oldCurrentRow。如果需要显示索引,可以增加一列el-table-column,设置type属性为index即可显示从 1 开始的索引号。”


示例:

标签中:

@current-change="handleCurrentChange"


js中:

handleCurrentChange(val) {

this.currentRow = val;

}

注:这个事件其实有两个参数currentRow、oldCurrentRow,第二次点击同一行,currentRow是空的,直接赋值会报错!要进行判空。



事件:右键

1、在指定区域绑定 右键事件:

@contextmenu.prevent="onContextmenu"

或者在element的table中,有这个

@row-contextmenu="rightClick"

2、绘制新菜单:

<div id="menu"

class="menuDiv">

<div class="menuUl">

<el-button class="li"

v-for="(item, index) in menus"

:key="index"

@click.stop="menuClick(item)"

v-hasPermi="[item.hasPermi]"

style="width: 100%; text-align: left">

<i :class="item.icon"></i> {{ item.name }}

</el-button>

</div>

</div>

3、右键事件:

onContextmenu(event) {

let contextmenu = [];

contextmenu.push({

label: "病人信息",

icon: "el-icon-caret-right",

onClick: () => {

this.chooseItem.status = 1;

this.turnTODetail(this.chooseItem, "archivesUpdate", "one");

},

});

this.$contextmenu({

items: contextmenu,

event, // 鼠标事件信息

customClass: "custom-class", // 自定义菜单 class

zIndex: 3, // 菜单样式 z-index

minWidth: 111, // 主菜单最小宽度,

});

return false;

},

// 表格右击的功能

rightClick(row, column, event) {

this.activeRow = row;

this.activeRow.status = 1;

event.preventDefault();

let menu = document.querySelector("#menu");

// 根据事件对象中鼠标点击的位置,进行定位

menu.style.left = event.clientX - 155 + "px";

menu.style.top = event.clientY - 75 + "px";

// 改变自定义菜单的隐藏与显示

menu.style.display = "block";

menu.style.zIndex = 1000;

},



强制修改样式

http://t.csdn.cn/qfyn2


在el-table 外加个div 自定义class

<div class="hhm_table" style="margin-top:20px;">

<el-table :data="skills" :header-cell-style="getRowClass">

<el-table-column label="#" type="index"></el-table-column>

<el-table-column label="专业技能" prop="data"></el-table-column>

</el-table>

</div>


二、在style标签中加上scpoed




三、重写样式

.hhm_table{

width: 50%;

margin: auto;

}

.hhm_table /deep/ .el-table--fit{

padding: 20px;

}

.hhm_table /deep/ .el-table, .el-table__expanded-cell {

background-color: transparent;

}


.hhm_table /deep/ .el-table tr {

background-color: transparent!important;

}

.hhm_table /deep/ .el-table--enable-row-transition .el-table__body td, .el-table .cell{

background-color: transparent;

}

.el-table::before {//去除底部白线

left: 0;

bottom: 0;

width: 100%;

height: 0px;

}



具名插槽【v-slot】

绑定字段的值:scope.row[xxx.prop]


示例:

<template v-slot="scope">

{{ scope.row[dropCol[index].prop] }}

</template>


作用域插槽【slot-scope】

绑定字段的值:scope.row.xxx


Element UI中,table就用到了这个作用域插槽,它维护了一个slot,提供了名为scope的对象,可以通过scope对象获取到一整行的信息:

<el-table-column label="操作">

<template slot-scope="scope">

<el-button @click="handleEdit(scope.$index, scope.row)">编辑</el-button>

<el-button @click="handleDelete(scope)">删除</el-button>

</template>

</el-table-column>

scope对象的结构:

Element UI 个人笔记_ui_13



引入插槽,下面蓝色部分代码:

<el-table :data="tableData">

字段名">

<template slot-scope="scope">

<span>{{scope.row.room}}</span>

</template>

</el-table-column>

</el-table>

js中把后台返回的数据response,赋值给tableData


this.tableData = response;


说明:原版是<el-table>里面的:data表示对象(每一条记录),然后<el-table-column>里的:prop表示对象的属性。升级版用了插槽slot,直接用scope.row.属性,代替原来的:prop


scope的结构:

Element UI 个人笔记_前端_14



索引

这是Element比较牛逼的地方。


创建索引:

官方:“如果需要显示索引,可以增加一列el-table-column,设置type属性为index即可显示从 1 开始的索引号。”

<el-table-column type="index" label="序号" width="50"></el-table-column>


获取索引:

<template slot-scope="scope">

<el-button @click="xxx(scope)"></el-button>

</template>


scope的结构:

Element UI 个人笔记_ui_15


js中:

let index = xxx.$index;







自定义样式

亲测有效:https://blog.csdn.net/qq_44758515/article/details/106944281

要用<style scoped>


一般环境:https://blog.csdn.net/shykevin/article/details/113984039

less环境:https://blog.csdn.net/weixin_43524214/article/details/125733507


合并单元格(李柏林的小妙招)

使用map来记录要合并的行数,巧妙地使用map来记录rowspan,用vue的this.$set设值。

<tbody>

<tr v-for="(item, index) in tableData"

:key="index">

<td v-if="item.isRowSpan"

:rowspan="map.get(item.group)">{{item.group}}</td>

<td>{{item.name}}</td>

</tr>

</tbody>


this.map = new Map();

this.tableData.forEach((item) => {

var rowspan = this.map.get(item.group);


//如果不为空,说明已经存在同组了,就更新这组的rowspan,让它+1

if (rowspan != null) {

this.$set(item, "isRowSpan", false); //this.$set是vue中深拷贝的写法,可以让页面回显

rowspan += 1;

this.map.set(item.group, rowspan);

}

//如果为空,说明这是第一次出现这一组,就让rowspan设为1

else {

this.$set(item, "isRowSpan", true);

item.isRowSpan = true;

this.map.set(item.group, 1);

}

});


合并单元格(结合element UI)

https://blog.csdn.net/qq_29468573/article/details/80742646

这篇文章有个小bug,即第二次调用生成数组的方法时,上一次的数据没清空,导致出现混乱。

生成合并单元格需要的数组

getSpanArr(data) {

初始化一下,防止第二次点击搜索,上一次的结果还在

初始化一下,防止第二次点击搜索,上一次的结果还在

for (var i = 0; i < data.length; i++) {

if (i === 0) {

this.spanArr.push(1);

this.pos = 0;

} else {

// 判断当前元素与上一个元素是否相同

if (data[i].xxx=== data[i - 1].xxx) {

this.spanArr[this.pos] += 1;

this.spanArr.push(0);

} else {

this.spanArr.push(1);

this.pos = i;

}

}

}

},

合并单元格

cellMerge({

row,

column,

rowIndex,

columnIndex

}) {

if (columnIndex === 0 || columnIndex === 1 || columnIndex === 2) {

const _row = this.spanArr[rowIndex];

const _col = _row > 0 ? 1 : 0;

return {

rowspan: _row,

colspan: _col

}

}

},

data中定义:

合并单元格的集合

数组下标

搜索中调用:

this.getSpanArr(this.tableData);





【tree】树形控件

默认展开

在标签里添加属性:default-expanded-keys

该属性的值为数组,要展开的所有节点的数组。

<el-tree :data="data" show-checkbox node-key="id"

:default-expanded-keys="[2, 3]"

:props="defaultProps">


</el-tree>


【pagination】分页

属性【layout】整体布局

设置layout,表示整体布局上内容的排版,用逗号分隔,布局元素会依次显示。

sizes:选择分页大小

total总页数(这个样式是固定的,就是“共xxx条”,改不了)

prev上一页

next下一页

pager页码列表

jumper跳页元素

-> :它后的元素会靠右显示

Element UI 个人笔记_前端_16



属性【total】总条数

属性【page-size】每页条数(当前)

当前的每页显示记录的个数。


属性【page-sizes】分页选项

总共有哪些分页选项。


注意:这个属性比上一个属性多了s,表示集合。



事件【@size-change】

@size-change="handleSizeChange"

js方法中可以直接获取到当前选择的值:

handleSizeChange(val) {

console.log(`每页${val}`);

},


事件【@current-change】

@current-change="handleCurrentChange"

handleCurrentChange(val) {

console.log(`当前页: ${val}`);

}


示例【小创云】

<div v-show="!listLoading" class="pagination-container">

<el-pagination

@size-change="handleSizeChange"

@current-change="handleCurrentChange"

:current-page.sync="listQuery.page"

:page-sizes="[10,20,30, 50]"

:page-size="listQuery.limit"

layout="total, sizes, prev, pager, next, jumper"

:total="total">

</el-pagination>

</div>


/**

改变分页的大小(limit表示一页显示几条数据)

*/

handleSizeChange(val) {

this.listQuery.limit = val;

this.getList();

},

/**

跳转到某一页(page表示当前页)

*/

handleCurrentChange(val) {

this.listQuery.page = val;

this.getList();

},

/**

查询列表信息

*/

getList() {

this.listLoading = true;

page(this.listQuery).then(response => {

列表的结构", response);

this.tableData = response.data.rows;

this.total = response.data.total;//显示所有页码

this.listLoading = false;

})

},

后端:

方法一,用封装好的类TableResultResponse:

@ResponseBody
@RequestMapping(value = "/pageOrg", method = RequestMethod.GET)
public TableResultResponse<User> pageOrg(@RequestParam Map<String, Object> params, HttpServletRequest request) {
//查询列表数据
String orgId = this.getCurrentOrgId();
params.put("orgId", orgId);

Query query = new Query(params);
Page<User> result = PageHelper.startPage(query.getPage(), query.getLimit());
//TODO 人员属于多个科室会出问题
List<User> list = userBiz.pageOrg(params);
return new TableResultResponse<User>(result.getTotal(), list);
}


方法二,手写

@RequestMapping(value = {"/hos/getAllScoresOfHos"}, method = RequestMethod.GET)
public JSONObject getAllScoresOfHos(@RequestParam Map<String, Object> params) {


int curPage = Integer.parseInt(params.get("page").toString());
int limit = Integer.parseInt(params.get("limit").toString());
……
List<Map<String, Object>> scores = new ArrayList<>();

Page<Object> result = PageHelper.startPage(curPage, limit);
List<HdProcessToday> views = this.hdProcessTodayBiz.sql;
for (HdProcessToday view :views){
……
scores.add(map);
}

Map<String,Object> map2 = new HashMap<>();
map2.put("data",scores);
map2.put("totalPage",result.getTotal() / limit+1);//总页数
map2.put("totalResult",result.getTotal());//总记录数
map2.put("curPage",curPage);//当前页码

JSONObject obj = new JSONObject();
obj.put("map2", map2);
return obj;
}




------------------【notice】---------------------

【Loading】加载

Element 提供了两种调用 Loading 的方法:指令、服务。


对于自定义指令v-loading,只需要绑定Boolean即可。默认状况下,Loading 遮罩会插入到绑定元素的子节点,通过添加body修饰符,可以使遮罩插入至 DOM 中的 body 上。







------------------【navigation】---------------------

【NavMenu】导航菜单

总体结构

格式:

<el-menu>

<el-submenu index="1">

<template slot="title">选项1</template>

<el-menu-item index="1-1">选项1-1</el-menu-item>

</el-submenu>


<el-submenu index="2">

<template slot="title">选项2</template>

<el-menu-item index="2-1">选项2-1</el-menu-item>

</el-submenu>

</el-menu>





【Menu】最外层

介绍:<el-menu>是最外层,必须先写这个!

参数

说明

可选值

默认值

mode

模式。默认是垂直排列,可以改成水平排列

horizontal / vertical

vertical

collapse

是否水平折叠收起菜单(仅在 mode 为 vertical 垂直排列时可用)

false

background-color

菜单的背景色(仅支持 hex 格式)

#ffffff

text-color

菜单的文字颜色(仅支持 hex 格式)

#303133

active-text-color

当前激活菜单的文字颜色(仅支持 hex 格式)

#409EFF

default-active

当前激活菜单的 index

default-openeds

当前打开的 sub-menu 的 index 的数组

unique-opened

是否只保持一个子菜单的展开

false

menu-trigger

子菜单打开的触发方式(只在 mode 为 horizontal 水平排列时有效)

hover / click

hover

router

是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转

false

collapse-transition

是否开启折叠动画

true

怎么没有“当前激活的菜单的背景颜色”这个参数呢?










【SubMenu】子菜单

介绍:<el-submenu>是<el-menu>下的直接子菜单项

问:怎么若依框架不加<el-menu>?

答:原来是外层父组件已经写了!

官方说明

参数

说明

默认值

index

唯一标志,类似id

null

popper-class

弹出菜单的自定义类名

show-timeout

展开 sub-menu 的延时

300

hide-timeout

收起 sub-menu 的延时

300

disabled

是否禁用

false

popper-append-to-body

是否将弹出菜单插入至 body 元素。在菜单的定位出现问题时,可尝试修改该属性

一级子菜单:true

非一级子菜单:false


自定义样式

https://blog.csdn.net/m0_56409834/article/details/126543172

要用/deep/,则需要先安装less

npm i less-loader@6(这个less-loader的版本要匹配你webpack的版本)

npm i less(可能还需要安装这个less)


/deep/.el-submenu .el-menu-item {

background-image: linear-gradient(#0099cc, #003366);

}





【Menu-Item】叶子节点

介绍:<el-menu-item>是最小的叶子节点



【Tabs】标签页

基础用法

<el-tabs v-model="activeName"

@tab-click="handleClick">

<el-tab-pane label="用户管理"

name="first">用户管理</el-tab-pane>

<el-tab-pane label="配置管理"

name="second">配置管理</el-tab-pane>

<el-tab-pane label="角色管理"

name="third">角色管理</el-tab-pane>

<el-tab-pane label="定时任务补偿"

name="fourth">定时任务补偿</el-tab-pane>

</el-tabs>


data() {

return {

activeName: "fourth",

};

},

methods: {

handleClick(tab, event) {

console.log(tab, event);

},

},


属性【value/v-model】指定当前标签页

<el-tabs>中指定value,就会去找<el-tab-pane>对应的name











------------------【others】---------------------

【Dialog】对话框

属性【width】宽度

默认50%


值是百分比,不是数字!

但是可以用像素来指定,这样的话一定要加上px


属性【close-on-click-modal】点击阴影,关闭弹框

功能:是否可以通过点击 modal 关闭 Dialog


我的评价:这个功能很烦,光标选择文本时会误触从而关闭弹框,烦。


示例:通常我们把它关掉,来提升用户体验。

<el-dialog :visible.sync="dialogVisible" width="30%" :close-on-click-modal="false">




功能:可拖拽

https://blog.csdn.net/Gx0525_/article/details/122713157?spm=1001.2014.3001.5506


官方不提供拖拽的功能,需要外部引入js文件!!!


1、新建一个directive.js文件

import Vue from 'vue'


// v-dialogDrag: 弹窗拖拽

Vue.directive('dialogDrag', {

bind(el, binding, vnode, oldVnode) {

const dialogHeaderEl = el.querySelector('.el-dialog__header')

const dragDom = el.querySelector('.el-dialog')

dialogHeaderEl.style.cursor = 'move'


获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);

const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)


dialogHeaderEl.onmousedown = (e) => {

鼠标按下,计算当前元素距离可视区的距离

const disX = e.clientX - dialogHeaderEl.offsetLeft

const disY = e.clientY - dialogHeaderEl.offsetTop


获取到的值带px 正则匹配替换

let styL, styT


注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px

if (sty.left.includes('%')) {

styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)

styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)

} else {

styL = +sty.left.replace(/\px/g, '')

styT = +sty.top.replace(/\px/g, '')

}


document.onmousemove = function(e) {

通过事件委托,计算移动的距离

const l = e.clientX - disX

const t = e.clientY - disY


移动当前元素

dragDom.style.left = `${l + styL}px`

dragDom.style.top = `${t + styT}px`


将此时的位置传出去

// binding.value({x:e.pageX,y:e.pageY})

}


document.onmouseup = function(e) {

document.onmousemove = null

document.onmouseup = null

}

}

}

})


// v-dialogDragWidth: 弹窗宽度拖大 拖小

Vue.directive('dialogDragWidth', {

bind(el, binding, vnode, oldVnode) {

const dragDom = binding.value.$el.querySelector('.el-dialog')


el.onmousedown = (e) => {

鼠标按下,计算当前元素距离可视区的距离

const disX = e.clientX - el.offsetLeft


document.onmousemove = function(e) {

移动时禁用默认事件


通过事件委托,计算移动的距离

const l = e.clientX - disX

dragDom.style.width = `${l}px`

}


document.onmouseup = function(e) {

document.onmousemove = null

document.onmouseup = null

}

}

}

})


2、在main.js中引入这个文件

import '@/utils/directive' // 拖拽弹窗,在需要用到拖拽功能的弹窗标签上加v-dialogDrag


3、在组件中使用:

<el-dialog v-dialogDrag









【Divider】分割线

https://element.eleme.cn/#/zh-CN/component/divider


比hr更淡的分割线,更加符合element风格。


也可以垂直分割。



【InfiniteScroll】无限滚动




【Popover】弹出框

属性【popper-class】为 popper 添加类名

如果对样式不满意,可以用这个属性带上自定义的类。


注意:因为它实际上是在根标签body下的,所以不能用<style scope>,否则不生效!

Element UI 个人笔记_vue_17



<el-popover title="医嘱数量"

popper-class="hhm_el_popper2"

placement="top-start"

@show="getStatusSum(item)"

width="200"

trigger="hover">

<div>

<span>进行中:{{notStopSum}}</span>

<span style="margin-left: 20px;">已停止:{{stopSum}}</span>

</div>

<i class="el-icon-info"

style="color: #5cb6ff;"

slot="reference"></i>

</el-popover>



阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6