vue2企业级项目(七)

vue2企业级项目(七)

组件封装

  • src目录下创建components/index.js

    const components = require.context("./modules", true, /index\.js$/);
    
    export default {
      install: (Vue) => {
        components.keys().forEach((key) => {
          let component = components(key).default;
          component && Vue.component(component.name, component);
        });
      },
    };
    
    
  • 创建src/components/modules目录

1、form

  • modules下创建modules/x-form/index.js

    import XForm from "./index.vue";
    export default XForm;
    
    
  • 创建modules/x-form/index.vue

    
    
    
  • src/components创建createInput.js

    import { isEqual } from "lodash";
    
    export const tagsMenu = new Map([
      ["text", "el-input"],
      ["xnumber", "x-input-number"],
      ["button", "el-button"],
      ["input", "el-input"],
      ["password", "el-input"],
      ["textarea", "el-input"],
      ["number", "el-input-number"],
      ["radio", "el-radio-group"],
      ["radio-item", "el-radio"],
      ["radio-button", "el-radio-button"],
      ["checkbox", "el-checkbox-group"],
      ["checkbox-item", "el-checkbox"],
      ["checkbox-button", "el-checkbox-button"],
      ["select", "el-select"],
      ["select-group", "el-option-group"],
      ["select-item", "el-option"],
      ["cascader", "el-cascader"],
      ["switch", "el-switch"],
      ["slider", "el-slider"],
      ["time-select", "el-time-select"],
      ["time", "el-time-picker"],
      ["date", "el-date-picker"],
      ["rate", "el-rate"],
      ["color", "el-color-picker"],
      ["transfer", "el-transfer"],
    ]);
    
    export const defaultValuesMenu = new Map([
      ["radio", ""],
      ["checkbox", []],
      ["text", ""],
      ["input", ""],
      ["password", ""],
      ["textarea", ""],
      ["number", ""],
      ["xnumber", ""],
      ["select", null],
      ["cascader", null],
      ["switch", ""],
      ["slider", 0],
      ["time-select", ""],
      ["time", ""],
      ["date", ""],
      ["rate", null],
      ["color", null],
      ["transfer", []],
    ]);
    
    export function getDefaultValue(form, defaultValue = {}, item) {
      if (!item.prop) return;
    
      let value = defaultValuesMenu.get(item.type);
      if (item?.props?.multiple || item?.props?.isRange) value = [];
    
      form[item.prop] =
        form[item.prop] || item.default || defaultValue[item.prop] || value;
    }
    
    export function getPlaceholder(item) {
      const inputTypes = ["input", "password", "textarea", "number", "xnumber"];
      const selectType = ["select", "cascader", "time-select", "time", "date"];
      const dateRangeTypes = ["datetimerange", "daterange", "monthrange"];
    
      item.attrs = item.attrs || {};
      item.props = item.props || {};
    
      // 添加date-range的标识
      if (item.props?.type && dateRangeTypes.includes(item.props.type)) {
        item.props.isRange = true;
      }
    
      if (item.placeholder) {
        item.attrs.placeholder = item.placeholder;
      } else {
        if (inputTypes.includes(item.type))
          item.attrs.placeholder = `请输入${item.label}`;
        if (selectType.includes(item.type))
          item.attrs.placeholder = `请选择${item.label}`;
        if (item.props.isRange) {
          item.props.startPlaceholder = `请选择开始${item.label}`;
          item.props.endPlaceholder = `请选择结束${item.label}`;
        }
      }
    
      return item;
    }
    
    export function getRules(item, rules) {
      if (item.rules) return item;
      else if (rules && rules[item.prop]) {
        item.rules = rules[item.prop];
      } else if (item.required) {
        item.rules = [
          {
            required: true,
            message:
              item.attrs.placeholder ||
              item.props.startPlaceholder ||
              item.props.endPlaceholder,
            trigger: "blur",
          },
        ];
      }
    
      return item;
    }
    
    export function createInput(h, item, _this) {
      item.attrs = {
        type: item.type,
        options: item.type === "cascader" ? item.options : null,
        ...item.attrs,
      };
    
      item.props = {
        disabled: item.disabled !== undefined ? item.disabled : _this.disabled,
        ...item.props,
      };
    
      if (item.btnType) item.attrs.type = item.btnType;
      if (item.btnIcon) item.attrs.icon = item.btnIcon;
      if (item.marking) item.attrs.marking = item.marking;
    
      item.style = {
        width: item.type !== "button" ? "100%" : null,
        ...item.style,
      };
    
      let {
        type,
        prop,
        className = {},
        style = {},
        attrs = {},
        props = {},
        on = {},
        text = "",
      } = item;
    
      const config = {
        type,
        prop,
        class: className,
        style,
        attrs,
        props,
        on,
        text,
        children: generateOptions(h, item) || [],
      };
    
      if (type === "time-select" || type === "date") {
        let minTimeKey = props?.pickerOptions?.minTimeKey;
        let maxTimeKey = props?.pickerOptions?.maxTimeKey;
    
        if (minTimeKey) {
          if (type === "time-select") {
            config.props = {
              ...config.props,
              pickerOptions: {
                ...config.props.pickerOptions,
                minTime: _this.form[minTimeKey],
              },
            };
          } else {
            let disabledDate = config.props.pickerOptions.disabledDate;
            if (typeof disabledDate === "function") {
              config.props = {
                ...config.props,
                pickerOptions: {
                  ...config.props.pickerOptions,
                  disabledDate: (time) =>
                    disabledDate(time, _this.form[minTimeKey]),
                },
              };
            }
          }
        }
    
        if (maxTimeKey) {
          if (type === "time-select") {
            config.props = {
              ...config.props,
              pickerOptions: {
                ...config.props.pickerOptions,
                maxTime: _this.form[maxTimeKey],
              },
            };
          } else {
            let disabledDate = config.props.pickerOptions.disabledDate;
            if (typeof disabledDate === "function") {
              config.props = {
                ...config.props,
                pickerOptions: {
                  ...config.props.pickerOptions,
                  disabledDate: (time) =>
                    disabledDate(time, _this.form[maxTimeKey]),
                },
              };
            }
          }
        }
      }
    
      if (type === "text") {
        config.class["el-readonly-input"] = true;
        config.attrs.readonly = true;
      }
    
      return generateTag(h, config, _this);
    }
    
    export function generateOptions(h, item) {
      const canTag = ["radio", "checkbox", "select"];
      if (!canTag.includes(item.type)) return null;
    
      // 后续需要添加字典
      const options = item?.options || [];
    
      return (options || []).map((option) => {
        let type = `${item.type}-${item.button ? "button" : "item"}`;
        if (option.options) {
          const cloneItem = { ...item };
          cloneItem.options = option.options;
          type = `${item.type}-group`;
    
          return h(
            tagsMenu.get(type),
            {
              attrs: {
                label: option.label,
              },
            },
            generateOptions(h, cloneItem),
          );
        }
    
        return h(
          tagsMenu.get(type),
          {
            attrs: {
              label: item.type === "select" ? option.label : option.value,
              value: item.labelInValue ? option : option.value,
            },
          },
          [item.type === "select" ? null : [option.label]],
        );
      });
    }
    
    export function generateTag(h, config, _this) {
      config.props.value = _this.form[config.prop];
      const inputEvent = config.on?.input;
      const clickEvent = config.on?.click;
      config.on = {
        ...config.on,
        input: (value) => {
          value = formatDateValue(value, config);
          if (!isEqual(_this.form[config.prop], value)) {
            _this.form[config.prop] = value;
            typeof inputEvent === "function" && inputEvent(value, config);
          }
        },
        click: (event) => {
          typeof clickEvent === "function" && clickEvent(event, config);
        },
      };
    
      config.nativeOn = {
        keydown: (e) => {
          if (e.keyCode === 13 && this.enterSubmit && config.type !== "textarea") {
            _this.submit();
          }
        },
      };
    
      return h(tagsMenu.get(config.type), config, [
        ...config.children,
        config.text,
      ]);
    }
    
    export function formatDateValue(value, config) {
      if ((config.type === "time" || config.type === "date") && !value) {
        return config.props.isRange ? ["", ""] : "";
      }
      return value;
    }
    
    
  • 创建src/styles/components.less,并引入style/index.less

    /* x-form 组件样式 */
    .el-readonly-input {
      .el-input__inner {
        border: none;
      }
    
      .el-input__inner:focus {
        border-color: #DCDFE6;
      }
    }
    
    .form-item-col {
      .el-form-item {
        margin-bottom: 22px;
      }
    }
    
    /* x-table 组件样式 */
    
    
  • 使用案例

    
    
    
    
    
    
    

2、table

  • 创建components/modules/x-table/index.js

    import XTable from "./index.vue";
    export default XTable;
    
    
  • 创建components/modules/x-table/index.vue

    
    
    
    
    
  • 修改src/styles/components.less

    ...
    /* x-table 组件样式 */
    .x-table-wrap {
      width: 100%;
    
      .x-table-bottom {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-top: 3px;
        font-size: 13px;
        font-weight: 400;
        color: #606266;
        flex-direction: row-reverse;
      }
    }
    
    .x-table-radio {
      ::v-deep {
        .el-table__header-wrapper {
          .el-checkbox {
            display: none;
          }
        }
      }
    }
    
    /* dialog 组件样式 */
    
    
  • 使用案例

    
    
    
    
    
    
    
  • mockjs

    function getList() {
      let list = new Array(99).fill({});
      list = list.map((item, index) => {
        return {
          name: index > 20 ? `张三${index}` : "张三",
          age: index.toString(),
          date: Mock.mock("@date('yyyy-MM-dd')"),
          sex: (index % 2).toString(),
          address: `北京市朝阳区${index}`,
        };
      });
      return new MockPort({
        template: {
          code: 200,
          msg: "success",
          data: {
            records: [],
            pagesiez: 0,
            current: 1,
            total: 0,
          },
        },
        action(options) {
          const params = this.paramsBackRes(options.body) || {};
          let { pagesize, pageno, ...search } = params;
          pagesize = pagesize || 10;
          pageno = pageno || 1;
          let records = list.filter((item) => isMatch(item, search));
          this.template.data = {
            records: [...records].splice((pageno - 1) * pagesize, pagesize),
            total: records.length,
            pagesize,
            current: pageno,
          };
          return this.template;
        },
      });
    }
    

3、dialog

4、searchForm

5、searchTable

6、dialogForm

7、navTab

8、updateFile

9、lazy

10、theme-color

切换主题色、使用上面的动态切换主题原理实现

11、screenfull

全屏按钮、使用插件screenfull

12、screenshot

截屏按钮、使用插件html2canvas

13、input-number

14、tree

你可能感兴趣的:(vue2企业级,vue.js,javascript,前端)