element-ui总结

380 阅读2分钟

element-ui是非常不错的一个pc端的ui库。用vue配合element-ui去打造pc端的项目非常好用。 不过element-ui毕竟是针对大众去使用的,无法做到私人订制。 所以为了复用和开发效率的考虑, 有必要对element-ui提供的组件进行二次封装。

1.一些定义和基本概念

$parent: 获取当前组件的父组件
$children:获取当前组件的子组件
$root:获取new Vue的实例 (即上面的:vm)
$el: 获取当前组件的DOM元素

  • 直接在组件上无法使用原生@click方法, 这时候用@click.native 就可以了

安装和使用方法

  1. 全局安装 npm i element-ui -S
  2. 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'
})
  1. 按照官网的示例和文档, 在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>