element-ui是非常不错的一个pc端的ui库。用vue配合element-ui去打造pc端的项目非常好用。 不过element-ui毕竟是针对大众去使用的,无法做到私人订制。 所以为了复用和开发效率的考虑, 有必要对element-ui提供的组件进行二次封装。
1.一些定义和基本概念
$parent: 获取当前组件的父组件
$children:获取当前组件的子组件
$root:获取new Vue的实例 (即上面的:vm)
$el: 获取当前组件的DOM元素
- 直接在组件上无法使用原生
@click方法, 这时候用@click.native就可以了
安装和使用方法
- 全局安装
npm i element-ui -S - 在
main.js中引入。 主要有下面三行代码
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
ElementUI.Dialog.props.closeOnClickModal.default = false
ElementUI.Autocomplete.props.triggerOnFocus.default = false
ElementUI.Autocomplete.props.highlightFirstItem.default = true
ElementUI.Table.props.border = { type: Boolean, default: true }
ElementUI.Table.props.highlightCurrentRow = { type: Boolean, default: true }
ElementUI.DatePicker.props.unlinkPanels = { type: Boolean, default: true }
ElementUI.DatePicker.props.startPlaceholder = { type: String, default: '开始日期' }
ElementUI.DatePicker.props.endPlaceholder = { type: String, default: '结束日期' }
ElementUI.Button.props.round = { type: Boolean, default: true }
Vue.use(ElementUI, {
size: 'mini',
zIndex: 3000, // 默认值2000
menuType: 'text'
})
- 按照官网的示例和文档, 在vue中的各个组件中使用element-ui的组件
2. form表单
- el-form 上,model绑定的数据必须是json对象格式
- form表单提交的时候,提交按钮要写在el-form-item中,提交方法要用element-ui提供的方法,这样,element-ui会在提交前进行表单校验
<div class="formContainer">
<el-form
ref="ruleForm"
:model="ruleForm"
:rules="rules"
label-width="100px"
class="demo-ruleForm"
>
<el-form-item label="登录账号:" prop="username">
<el-input v-model="ruleForm.username" />
</el-form-item>
<el-form-item label="登录密码:" prop="password">
<el-input v-model="ruleForm.password" />
</el-form-item>
<el-form-item label="确认密码:" prop="passwordConfirm">
<el-input v-model="ruleForm.passwordConfirm" />
</el-form-item>
<el-form-item label="姓名:" prop="name">
<el-input v-model="ruleForm.name" />
</el-form-item>
<el-form-item label="所属部门" prop="department">
<el-select v-model="ruleForm.department" placeholder="请选择活动区域">
<el-option label="销售部" value="销售部"></el-option>
<el-option label="技术部" value="技术部"></el-option>
</el-select>
</el-form-item>
<el-form-item label="联系电话:" prop="phone">
<el-input v-model="ruleForm.phone" />
</el-form-item>
<el-form-item label="联系邮箱:" prop="email">
<el-input v-model="ruleForm.email" />
</el-form-item>
<el-form-item label="账号启用状态: " prop="delivery">
<el-switch v-model="ruleForm.status" />
</el-form-item>
<el-form-item>
<div class="flex-between">
<el-button type="primary" @click="validateForm('ruleForm')"
>提交</el-button
>
<el-button @click="resetForm('ruleForm')">取消</el-button>
</div>
</el-form-item>
</el-form>
</div>
// data 数据
data() {
return {
ruleForm: {
username: "",
password: "",
passwordConfirm: "",
name: "",
department: "",
phone: "",
email: "",
status: ""
},
rules: {
username: [
{ required: true, message: "请输入登录账号", trigger: "blur" },
{ min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" }
],
password: [
{ required: true, message: "请输入登录密码", trigger: "blur" },
{ min: 6, max: 6, message: "请输入6位数字", trigger: "blur" }
],
passwordConfirm: [
{ required: true, message: "请输入登录密码", trigger: "blur" },
{ min: 6, max: 6, message: "请输入6位数字", trigger: "blur" }
],
name: [
{
pattern: /^[\u4e00-\u9fa5a-z0-9]{2,12}$/,
message: "只允许输入汉字数字和小写字母",
required: true,
trigger: 'blur'
}
],
department: [
{
required: true,
type: "string",
message: "请选择时间",
trigger: "change"
}
],
phone: [
{
required: true,
type: "string",
message: "请输入联系方式",
trigger: "blur"
}
],
email: [{ type: "string", message: "请输入联系方式", trigger: "blur" }]
}
};
},
// 在created生命周期里给ruleForm赋值。
created() {
let source = this.$route.query;
Object.keys(this.ruleForm).forEach(v => (this.ruleForm[v] = source[v]));
},
// 提交方法
validateForm(formName) {
this.$refs[formName].validate(valid => {
if (!valid) {
// 验证不通过禁止提交
console.log("验证不通过");
return false;
}
console.log("验证通过");
});
}
3. el-switch切换按钮
如果是在table,
<el-table-column label="操作" width="300">
<template slot-scope="scope">
<el-switch
v-model="scope.row.status"
active-value="1"
inactive-value="0"
active-text="启用"
inactive-text="禁用"
style="margin:0 5px"
@change="switchChange(scope.row)"
/>
</template>
</el-table-column>
// 切换启用禁用
switchChange(rowVal) {
let {id, status, name, department} = rowVal;
let sendData = {
id,
status,
name,
department
}
Object.keys(sendData).forEach((item, val, idx )=>{
if(sendData[item] === undefined) {
errorMsg(`${item}不能为空`) // 错误提示
this.refreshTableData(); // 刷新table
return ;
}
})
// 封装的put请求
putAxios(greatApi.sysUser, "system_user_admin", sendData).then(res => {
infoMsg('变更成功');
})
}
4. pagination分页
<template>
<div class="pagenationContainer">
<el-pagination
background
:current-page="page.currentPage"
:page-sizes="[10, 20, 50, 100]"
:page-size="page.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="page.totalNumber"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
</el-pagination>
</div>
</template>
<script>
export default {
name: "GPagination",
props: {
page: {
type: Object,
default: () => {
return {}
}
}
},
data() {
return {
};
},
created() {
},
mounted() {
},
methods: {
handleSizeChange(val) {
this.$emit('handlePaginationChange', val);
},
handleCurrentChange(val) {
this.$emit('handleCurrentChange', val);
},
}
};
</script>
<style scoped lang='scss'>
.pagenationContainer {
margin-top: 20px;
}
</style>
5. 有开始和结束日期的DatePicker双日期选择框
有配合vuex进行日期的处理
<template>
<div class="block">
<el-date-picker
v-model="value1"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
:picker-options="pickerOptions"
@change="getChangeTime"
/>
</div>
</template>
<script>
import store from "@/store";
export default {
name: "DoubleDate",
props: {
sendTime: {
type: [Array, String, Number]
}
},
data() {
return {
pickerOptions: {
shortcuts: [
{
text: "今天",
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
const start = new Date(new Date().toLocaleDateString());
start.setTime(start.getTime());
picker.$emit("pick", [start, end]);
}
},
{
text: "昨天",
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
const start = new Date(new Date().toLocaleDateString());
start.setTime(start.getTime() - 3600 * 1000 * 24);
end.setTime(end.getTime() - 3600 * 1000 * 24);
picker.$emit("pick", [start, end]);
}
},
{
text: "7天",
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
const start = new Date(new Date().toLocaleDateString());
start.setTime(start.getTime() - 3600 * 1000 * 24 * 6);
picker.$emit("pick", [start, end]);
}
},
{
text: "本月",
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
const start = new Date(new Date().toLocaleDateString());
const monthDate = new Date(
new Date().toLocaleDateString()
).getDate();
start.setTime(
start.getTime() - 3600 * 1000 * 24 * (monthDate - 1)
);
picker.$emit("pick", [start, end]);
}
},
{
text: "上月",
onClick(picker) {
const end = new Date(new Date().toLocaleDateString());
const start = new Date(new Date().toLocaleDateString());
const endMonthDate = new Date(
new Date().toLocaleDateString()
).getDate();
const day = new Date(
new Date(new Date().toLocaleDateString()).getFullYear(),
new Date().getMonth(new Date().toLocaleDateString()) + 1,
0
);
const dayCount = day.getDate();
start.setTime(
start.getTime() - 3600 * 1000 * 24 * (endMonthDate + dayCount)
);
end.setTime(end.getTime() - 3600 * 1000 * 24 * endMonthDate);
picker.$emit("pick", [start, end]);
}
}
]
}
};
},
watch: {
sendTime() {
this.$emit("pick", this.sendTime);
this.value1 = this.sendTime;
}
},
computed: {
value1: {
get() {
return this.$store.state.greatwall.doubleDate;
},
set(val) {
return this.$store.commit("greatwall/CHANGE_DATE", val);
}
}
},
created() {
// 当没有传递的值的时候, 传默认今天的日期
this.value1 = this.sendTime || [
new Date(new Date().toLocaleDateString()),
new Date(new Date().toLocaleDateString())
];
},
methods: {
getChangeTime() {
const sendData = [this.value1[0].getTime(), this.value1[1].getTime()];
this.$emit("func", sendData);
}
}
};
</script>
<style></style>
5. el-table的封装。 动态生成表格
el-table的表格是可以实现动态渲染的。 可以省下很大一部分精力用在处理其他的事情上。 如果对表格的定制化样式要求不高或者需求比较明确, 建议使用动态生成表格的方法, 去生成表格
- 如果由后端提供表头的名字。 那么就把表头对应的中文名写在数据中
<template>
<div>
<el-table :data="datas">
<el-table-column
v-for="info in header"
:key="info.key"
:property="info.key"
:label="info.label"
>
<template slot-scope="scope">
{{scope.row[scope.column.property] && scope.row[scope.column.property].val}}
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: "Index",
data() {
return {
generateHeader: [
{
label: '编码',
key: 'code'
},
{
label: '姓名',
key: 'name'
},
],
header: [],
datas: [{
"id": 221,
"code": "01",
"name": { ch: "名字", val: "西药开立权限111" },
"description": { ch: "描述", val: "大萨达撒2222" },
}],
};
},
created() {
this.getHeader();
},
methods: {
getHeader() {
this.datas.forEach(v => {
for (let key in v) {
if (typeof v[key] === 'object') {
let obj = {};
obj.label = v[key].ch;
obj.key = key;
this.header.push(obj);
}
}
})
}
}
};
</script>
- 如果由前端提供表头的名字。 前端建立一个字典的映射, 然后通过循环去生成表头
<template>
<div>
<el-table :data="datas">
<el-table-column
v-for="info in header"
:key="info.key"
:property="info.key"
:label="info.label"
>
<template slot-scope="scope">
{{scope.row[scope.column.property]}}
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: "Index",
data() {
return {
header: [],
datas: [{
"id": 221,
"code": "01",
"name": "西药开立权限111",
"description": "大萨达撒2222321321",
}],
dictionnary: {
name: '名字',
age: '年龄',
description: '描述',
other: '其他',
}
};
},
created() {
this.matchHeader(this.datas, this.dictionnary);
},
methods: {
matchHeader(val, dic) {
this.datas.forEach(v => {
for (let key in v) {
if (dic[key]) {
let obj = {};
obj.key = key;
obj.label = dic[key];
this.header.push(obj);
}
}
})
}
}
};
</script>