当前位置: 首页 > news >正文

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

    <script>
    import { cloneDeep } from "lodash";
    import {getDefaultValue,getPlaceholder,getRules,createInput,
    } from "../../createInput.js";/*** 配置说明文档* @param { Array } columns: 表单配置项* @param { String } labelWidth: 设置el-form-item的label宽度。(优先级低于item)* @param { Number } contentSpan: 设置el-form-item的内容占比宽度* @param { Object } defaultValue: 设置el-form的默认值。(优先级低于item)* @param { Object } rules: 设置el-item的校验规则。(优先级低于item)* @param { Number } gutter: 设置el-row的gutter* @param { Number, Array } grid: 设置el-col的span,如果没有,则不创建el-col* @param { Boolean } disabled: 表单统一仅用。(优先级低于item)** @param { Boolean } ctrl: 是否显示表单控制按钮* @param { Boolean } submitBtn: 是否显示提交按钮* @param { String } submitText: 提交按钮内容* @param { Boolean } resetBtn: 是否显示重置按钮* @param { String } resetText: 重置按钮内容** @param { Function } submit: 表单提交方法,返回表单值和校验结果* @param { Function } reset: 表单重置方法* @param { Function } clear: 表单清空方法* @param { Function } getFormByKey: 获取表单单值方法* @param { Function } getForm: 获取表单全值方法* @param { Function } setForm: 设置表单单值方法*//*** 表单配置项 columns-item* @param { Object } form: 单独作用form的配置* @param { Object } table: 单独作用table的配置* @param { Object } search: 单独作用search的配置* 以上的配置和下面一样,但优先级高*** @param { String } type: 表单控件的类型。(参考element-ui的控件类型)* @param { String } label: 字段名称* @param { String } prop: 字段绑定key* @param { Any } default: 控件默认值。(级别最高)* @param { String } placeholder: 提示信息* @param { Array } rules: 校验规则。(级别最高)* @param { Number } order: 排序序号。(大到小)* @param { Number } span: 当前表单控件col占比。(级别高)* @param { Object } col: el-col的其他配置。(级别最高)* @param { String } labelWidth: label的宽度。(级别最高)* @param { Number } contentSpan: 内容占比宽度* @param { Boolean } required: 是否必填* @param { Boolean } disabled: 是否禁用。(权限最高)** @param { Object } children: 子节点, (一个el-form-item里面多个控件)* @param { Number } gutter: 子节点的el-row的gutter。(仅在设置children后生效)* @param { Number, Array } grid: 子节点的栅格布局col排布** @param { Object } className: 表单控件的类名,对象的形式:{ box: true }* @param { Object } style: 样式控制* @param { Object } attrs: element-ui表单控件的attribute,参考element-ui文档。* @param { Object } props: element-ui表单控件的props。(有的时候文档上写的时attrs设置,其实时props设置。所以不生效的时候可以尝试一下)* @param { Object } on: 表单控件的绑定事件。{ input: (value) => console.log(value) }* @param { Array } options: radio,checkbox, select, cascader,* @param { String } text: button按钮的文字内容* @param { String } btnType: button按钮的类型* @param { String } btnIcon: button的icon* @param { String } marking: button的标记* @param { Boolean } hasFilter: 是否进行筛选,只有存在options才可以进行** @param { Function } slotDefault: el-table-column 的 default的插槽* @param { Function } slotHeader: el-table-column 的 header的插槽*/export default {name: "XForm",props: {labelWidth: String,columns: {type: Array,default: () => [],},defaultValue: {type: Object,default: () => ({}),},contentSpan: {type: Number,default: 24,},rules: {type: Object,default: () => ({}),},gutter: {type: Number,default: 0,},grid: [Number, Array],disabled: Boolean,ctrl: {type: [Boolean, String],default: "left",},submitBtn: {type: Boolean,default: true,},submitText: {type: String,default: "提交",},resetBtn: {type: Boolean,default: true,},resetText: {type: String,default: "重置",},},render(h) {return h("el-form",{attrs: { ...this.$attrs },props: {model: this.form,},style: {padding: `0 ${this.gutter / 2}px`,},ref: "form",nativeOn: {submit(e) {e.preventDefault();e.stopPropagation();},},},[this.renderRow(h, this.fields, this.gutter), this.$slots.default],);},data() {return {form: {},fields: [],};},watch: {columns: {immediate: true,deep: true,handler() {this.init();},},},methods: {init() {let form = cloneDeep(this.form);// 获取配置属性this.fields = this.handleFieldsChild(form, this.columns);// 添加校验按钮if (this.ctrl) {let _this = this;this.fields.push({render: ({ h }) => {return h("div",{class: { formBtns: true },style: {textAlign: this.ctrl,},},[_this.submitBtn &&createInput(h,{type: "button",btnType: "primary",text: _this.submitText,on: {click: _this.submit,},},_this,),_this.resetBtn &&createInput(h,{type: "button",text: _this.resetText,on: {click: _this.reset,},},_this,),],);},});}this.form = { ...form };},handleFieldsChild(form, columns, parent = null) {let fields = columns.filter((item) => item?.isShow !== false);fields = fields.map((item) => {let formItem = { ...item, ...item?.form };delete formItem.table;delete formItem.search;delete formItem.form;if (formItem.children && Array.isArray(item.children)) {formItem.children = this.handleFieldsChild(form,formItem.children,formItem,);}if (parent && !formItem.label) formItem.label = parent?.label;getDefaultValue(form, this.defaultValue, formItem);getPlaceholder(formItem);getRules(formItem, this.rules);if (parent) {formItem.grid = parent?.grid;delete formItem.label;}return formItem;});fields = fields.sort((a, b) => (b?.order || 0) - (a?.order || 0));return fields;},renderRow(h, fields, gutter, isChild = false) {let style = null;if (isChild) {style = {position: "relative",left: `-${gutter / 2}px`,marginLeft: "0",marginRight: "0",width: `calc(100% + ${gutter}px)`,};}return h("el-row",{ attrs: { gutter }, style },this.renderItem(h, fields, isChild),);},renderItem(h, fields, isChild) {return fields.map((item, index) =>this.renderCol(h, { ...item, isChild }, index),);},renderCol(h, item, index) {delete item.order;const gridConfig = item.grid || this.grid;let grid = 0;if (typeof gridConfig === "number") grid = gridConfig;if (Array.isArray(gridConfig))grid = this.grid[index % gridConfig?.length];let span = item.span || item?.col?.span || grid;if (span) {return h("el-col",{class: { "form-item-col": true },attrs: { span, ...item.col },},[this.renderFormItem(h, item)],);} else {return this.renderFormItem(h, item);}},renderFormItem(h, item) {let labelWidth = item?.labelWidth || this.labelWidth || "0px";let isChild = item.isChild;let hasChild = Array.isArray(item.children);if (isChild) labelWidth = "0px";delete item?.labelWidth;delete item?.isChild;let childDom = null;if (hasChild) {const gutter = item?.gutter || this.gutter;const children = item?.children || [];childDom = this.renderRow(h, children, gutter, true);} else {childDom = h("el-col",{attrs: {span: isChild ? 24 : item.contentSpan || this.contentSpan,},},[createInput(h, { ...item }, this)],);}delete item?.children;delete item?.gutter;let itemRender = null;if (item.render && typeof item.render === "function") {itemRender = item.render({h: this.getHypeScript(),value: this.form[item.prop],item,_this: this,});}delete item.render;return h("el-form-item",{style: { marginBottom: hasChild ? "0px" : "22px" },attrs: { ...item, labelWidth },},[childDom, itemRender],);},// 表单方法getHypeScript() {return this.$parent.$createElement;},submit() {this.$refs.form.validate((valid) => {this.$emit("submit", this.getForm(), valid);});},reset() {this.$refs.form.resetFields && this.$refs.form.resetFields();this.form = {};this.init();this.$emit("reset");},clear() {this.$refs.form.clearValidate && this.$refs.form.clearValidate();},getFormByKey(key) {return this.form[key];},getForm() {return this.form;},setForm(key, value) {key && (this.form[key] = value);},},
    };
    </script>
  • 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 组件样式 */
  • 使用案例

    <template><div><!-- 基础表单 --><hr /><x-form :columns="columns1" labelWidth="100px" :ctrl="false"></x-form><!-- 禁用表单 --><hr /><x-form:columns="columns1"labelWidth="100px":ctrl="false"disabled></x-form><!-- 表单布局 --><hr /><x-form:columns="columns2"labelWidth="100px":ctrl="false":gutter="10":grid="8"label-suffix=":"></x-form><!-- 灵活表单布局 --><hr /><x-form:columns="columns3"labelWidth="100px":gutter="8"label-suffix=":":contentSpan="20"></x-form><!-- 自定义表单元素 --><hr /><x-form:columns="columns4"labelWidth="100px"@submit="handleSubmit"></x-form></div>
    </template><script>
    import { cloneDeep } from "lodash";export default {data() {return {columns1: [{ type: "text", label: "标题", prop: "title", default: "基础表单" },{ type: "input", label: "用户名", prop: "username" },{ type: "password", label: "密码", prop: "password" },{ type: "textarea", label: "信息", prop: "info", disabled: false },],columns2: [{type: "text",label: "标题",prop: "title",default: "表单布局",span: 24,},{ type: "input", label: "输入1", prop: "value1" },{ type: "input", label: "输入2", prop: "value2" },{ type: "input", label: "输入3", prop: "value3" },{ type: "input", label: "输入4", prop: "value4" },{ type: "input", label: "输入5", prop: "value5" },{ type: "input", label: "输入6", prop: "value6" },],columns3: [{ type: "text", label: "标题", prop: "title", default: "灵活表单" },{type: "input",label: "输入1",prop: "value1",},{type: "input",label: "输入2",prop: "value2",required: true,},{label: "输入3",required: true,children: [{ type: "input", prop: "value31", required: true, span: 10 },{ type: "input", prop: "value32", required: true, span: 10 },{ type: "input", prop: "value33", required: true, span: 10 },{ type: "input", prop: "value34", required: true, span: 10 },{ type: "input", prop: "value35", required: true, span: 10 },{ type: "input", prop: "value36", required: true, span: 10 },],},{type: "input",label: "输入4",prop: "value4",required: true,},{type: "input",label: "输入5",prop: "value5",contentSpan: 24,required: true,},{type: "input",label: "输入6",prop: "value6",required: true,},{label: "时间选择",gutter: 10,required: true,children: [{type: "time-select",label: "开始时间",prop: "startTime",required: true,span: 10,props: {pickerOptions: {start: "08:30",step: "00:15",end: "18:30",maxTimeKey: "endTime",},},},{type: "time-select",label: "结束时间",prop: "endTime",required: true,span: 10,props: {pickerOptions: {start: "08:30",step: "00:15",end: "18:30",minTimeKey: "startTime",},},},],},{label: "日期选择",gutter: 10,required: true,children: [{type: "date",label: "开始日期",prop: "startDate",required: true,span: 10,props: {pickerOptions: {maxTimeKey: "endDate",disabledDate: (time, date) => {if (!date) return false;return time.getTime() > new Date(date).getTime();},},},},{type: "date",label: "结束日期",prop: "endDate",required: true,span: 10,props: {pickerOptions: {minTimeKey: "startDate",disabledDate: (time, date) => {if (!date) return false;return time.getTime() < new Date(date).getTime();},},},},],},{label: "动态1",gutter: 10,marking: "1",children: [{ type: "input", prop: "active1", span: 20 },{type: "button",btnType: "primary",btnIcon: "el-icon-plus",span: 2,marking: "1",on: {click: this.addForm,},},{type: "button",btnIcon: "el-icon-delete-solid",span: 2,marking: "1",on: {click: this.delForm,},},],},],activeItem: {label: "动态",gutter: 10,children: [{ type: "input", prop: "active", span: 20 },{type: "button",btnType: "primary",btnIcon: "el-icon-plus",span: 2,on: {click: this.addForm,},},{type: "button",btnIcon: "el-icon-delete-solid",span: 2,on: {click: this.delForm,},},],},columns4: [{ type: "text", label: "标题", prop: "title", default: "灵活表单" },{label: "自定义",prop: "input",render: ({ value, _this }) => {return (<el-inputvalue={value}onInput={(value) => {_this.setForm("input", value);}}/>);},},],};},methods: {handleSubmit(form, valid) {console.log(form, valid);},addForm(e, item) {let marking = item.attrs.marking;let newMarking = Number(marking) + 1;let columns = cloneDeep(this.columns3);let index =this.columns3.findIndex((formItem) => formItem?.marking === marking) +1;let addItem = cloneDeep(this.activeItem);addItem.label += newMarking;addItem.children[0].prop += newMarking;addItem.children[1].marking = newMarking;addItem.children[2].marking = newMarking;addItem.marking = newMarking;columns.splice(index, 0, addItem);this.columns3 = columns;},delForm(e, item) {let marking = item.attrs.marking;if (marking === "1") return;let columns = cloneDeep(this.columns3);let index = this.columns3.findIndex((formItem) => formItem?.marking === marking,);columns.splice(index, 1);this.columns3 = columns;},},
    };
    </script><style lang="less" scoped></style>

2、table

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

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

    <script>
    import { cloneDeep, isMatch } from "lodash";
    import dayjs from "dayjs";/*** 配置说明文档* @param { Boolean } autoHeight: 是否自动填充表格高度* @param { Array } columns: 表格的配置项,见下面详细说明* @param { Array } tableData: 表格的值* @param { Object } search: 表单搜索值、或者api入参* @param { Function } api: 接口* @param { String } itemAlign: 单元格align风格(left、center、right)* @param { String } emptyText: 无数据描述* @param { Any } emptyImage: 无数据图片展示地址* @param { Number } emptyImageSize: 无数据图片大小* @param { Boolean } hasPagination: 是否显示分页* @param { String } paginationLayout: 分页显示内容* @param { Boolean } multiple: 是否多选* @param { Boolean } hasRadio: 是否单选** @param { function } getSelection: 获取选中结果* @param { function } toggleSelection:设置默认多选* @param { function } setCurrent: 设置单选* @param { function } clearFilter:清空筛选项*//*** 表单配置项 columns-item* @param { Object } form: 单独作用form的配置* @param { Object } table: 单独作用table的配置* @param { Object } search: 单独作用search的配置* 以上的配置和下面一样,但优先级高*** @param { String } type: 表单控件的类型。(参考element-ui的控件类型)* @param { String } label: 字段名称* @param { String } prop: 字段绑定key* @param { Any } default: 控件默认值。(级别最高)* @param { String } placeholder: 提示信息* @param { Array } rules: 校验规则。(级别最高)* @param { Number } order: 排序序号。(大到小)* @param { Number } span: 当前表单控件col占比。(级别高)* @param { Object } col: el-col的其他配置。(级别最高)* @param { String } labelWidth: label的宽度。(级别最高)* @param { Number } contentSpan: 内容占比宽度* @param { Boolean } required: 是否必填* @param { Boolean } disabled: 是否禁用。(权限最高)** @param { Object } children: 子节点, (一个el-form-item里面多个控件)* @param { Number } gutter: 子节点的el-row的gutter。(仅在设置children后生效)* @param { Number, Array } grid: 子节点的栅格布局col排布** @param { Object } className: 表单控件的类名,对象的形式:{ box: true }* @param { Object } style: 样式控制* @param { Object } attrs: element-ui表单控件的attribute,参考element-ui文档。* @param { Object } props: element-ui表单控件的props。(有的时候文档上写的时attrs设置,其实时props设置。所以不生效的时候可以尝试一下)* @param { Object } on: 表单控件的绑定事件。{ input: (value) => console.log(value) }* @param { Array } options: radio,checkbox, select, cascader,* @param { String } text: button按钮的文字内容* @param { String } btnType: button按钮的类型* @param { String } btnIcon: button的icon* @param { String } marking: button的标记* @param { Boolean } hasFilter: 是否进行筛选,只有存在options才可以进行** @param { Function } slotDefault: el-table-column 的 default的插槽* @param { Function } slotHeader: el-table-column 的 header的插槽*/export default {name: "XTable",props: {autoHeight: {type: Boolean,default: true,},columns: {type: Array,default: () => [],},tableData: {type: Array,default: () => [],},search: {type: Object,default: () => ({}),},api: {type: Function,default: null,},itemAlign: {type: String,default: "left",},emptyText: {type: String,default: "暂无数据",},emptyImage: null,emptyImageSize: {type: Number,default: null,},hasPagination: {type: Boolean,default: true,},paginationLayout: {type: String,default: "total, sizes, prev, pager, next, jumper",},multiple: {type: Boolean,default: false,},hasRadio: {type: Boolean,default: false,},},data() {return {height: 0,fields: [],showData: [],pageInfo: {total: 0,pagesize: 10,current: 0,},multipleSelection: [],};},render(h) {return h("div",{class: { "x-table-wrap": true, "x-table-radio": this.hasRadio },style: { height: `${this.height}px` },},[this.renderTable(h), this.renderPagination(h)],);},watch: {columns: {immediate: true,deep: true,handler() {this.handleFields();},},tableData: {immediate: true,deep: true,handler() {this.getTableData();},},},mounted() {this.init();},methods: {init() {this.getParentHeight();window.addEventListener("reset", this.getParentHeight.bind(this));},handleFields() {this.fields = this.handleFieldsChild(this.columns);if (this.multiple || this.hasRadio) {this.fields.unshift({type: "selection",width: "40",});}},handleFieldsChild(columns) {let fields = columns.filter((item) => item?.isShow !== false);fields = fields.map((item) => {item.inputType = item.type;delete item.type;const tableItem = { ...item, ...item?.table };delete tableItem.table;delete tableItem.search;delete tableItem.form;if (tableItem.children && Array.isArray(tableItem.children)) {delete tableItem.prop;tableItem.children = this.handleFieldsChild(tableItem.children);}tableItem.align = tableItem.align || this.itemAlign;return tableItem;});fields = fields.sort((a, b) => (b?.order || 0) - (a?.order || 0));return fields;},getParentHeight() {const parentDom = this.$el.parentElement;const height = parentDom.clientHeight;const paddingTop = parseFloat(getComputedStyle(parentDom, false)["padding-top"],);const paddingBottom = parseFloat(getComputedStyle(parentDom, false)["padding-bottom"],);this.height = height - paddingTop - paddingBottom;},renderTable(h) {if (!this.height) return null;const config = {props: {highlightCurrentRow: this.hasRadio,...this.$attrs,data: this.showData,},on: {"selection-change": this.handleSelectionChange,"current-change": this.selectCurrentChange,},ref: "table",};if (this.autoHeight) {let paginationHeight = this.hasPagination ? 35 : 0;config.props.height = this.height - paginationHeight;}return h("el-table", config, [...this.renderColumns(h, this.fields),this.renderEmpty(h),this.$slots.default,]);},/* 空内容 */renderEmpty(h) {if (this.showData && this.showData.length) return null;const config = {props: { description: this.emptyText },slot: "empty",};if (this.emptyImage) config.props.image = this.emptyImage;if (this.emptyImageSize) config.props.imageSize = this.emptyImageSize;return h("el-empty", config);},/* table-column */renderColumns(h, fields) {return fields.map((item) => this.renderTableItem(h, item));},renderTableItem(h, item) {const scopedSlots = {};if (item.slotDefault && typeof item.slotDefault === "function") {scopedSlots.default = (scope) =>item.slotDefault(this.getHypeScript(), scope);}if (item.slotHeader && typeof item.slotHeader === "function") {scopedSlots.header = (scope) =>item.slotHeader(this.getHypeScript(), scope);}if (!item.slotDefault && item.children && Array.isArray(item.children)) {item.childrenDom = this.renderColumns(h, item.children);}const attrs = { ...item, ...item?.attrs };let props = item.props;delete item.props;delete item.attrs;// 后续需要添加字典if (!item.children && item.options) {props = {formatter: (row, column) => {const property = column["property"];const value = row[property];const findItem = item.options.find((item) => item.value === value);return findItem.label;},...props,};}let formatType = ["time-select", "time", "date"];if (!item.slotDefault &&item?.props?.valueFormat &&formatType.includes(item.inputType)) {let formatReg = item.props.valueFormat.replace(/yyyy/g, "YYYY");props = {formatter: (row, column) => {const property = column["property"];const value = row[property];return dayjs(value).format(formatReg);},...props,};}if (item.options && item.hasFilter) {props = {...props,filters: item.options.map(({ label, value }) => ({text: label,value,})),filterMethod: (value, row, column) => {const property = column["property"];return row[property] === value;},};}return h("el-table-column",{ attrs, props, scopedSlots },item.childrenDom,);},/* 分页 */renderPagination(h) {if (!this.hasPagination) return null;return h("div", { class: { "x-table-bottom": true } }, [h("el-pagination", {props: {layout: this.paginationLayout,...this.pageInfo,},on: {"size-change": this.handleSizeChange,"current-change": this.handleCurrentChange,},}),this.multiple &&h("div", null, [`已选中 ${this.multipleSelection.length} 个`]),]);},handleSizeChange(size) {this.pageInfo.pagesize = size;this.getTableData();},handleCurrentChange(current) {this.pageInfo.current = current;this.getTableData();},/* 方法 */getHypeScript() {return this.$parent.$createElement;},getTableData() {if (this.tableData && this.tableData.length) {const { pagesize, current } = this.pageInfo;let tableData = cloneDeep(this.tableData);tableData = tableData.filter((item) => isMatch(item, this.search));this.pageInfo.total = tableData.length;this.showData = [...tableData].splice((current - 1) * pagesize,pagesize,);} else if (this.api && typeof this.api === "function") {const param = {...this.search,pagesize: this.pageInfo.pagesize,pageno: this.pageInfo.current,};// 需要和后端协商好接口字段,保持所有table接口返回统一this.api(param).then((res) => {this.showData = res.data.records;const { total, current, pagesize } = res.data;this.pageInfo = { total, current, pagesize };}).catch(() => {this.showData = [];this.pageInfo = {total: 0,current: 1,pagesize: 10,};});}},handleSelectionChange(val) {if (this.hasRadio && val.length > 1) {const delItem = this.multipleSelection[0];const item = val.find((child) => !isMatch(child, delItem));this.$refs.table.clearSelection();this.setCurrent(item);} else {this.multipleSelection = val;}},toggleSelection(rows = []) {if (!this.multiple) return false;if (rows) {rows.forEach((row) => {const findItem = this.findRow(row);this.$refs.table.toggleRowSelection(findItem);});} else {this.$refs.table.clearSelection();}},selectCurrentChange(val) {this.multipleSelection = [val];if (this.hasRadio) {this.$refs.table.clearSelection();const findItem = this.findRow(val);this.$refs.table.toggleRowSelection(findItem);}},setCurrent(row) {if (!this.hasRadio) return false;this.$refs.table.setCurrentRow(row);},findRow(row) {return this.showData.find((item) => isMatch(item, row));},clearFilter(key) {this.$refs.table.clearFilter(key);},getSelection() {return this.multipleSelection;},},
    };
    </script><style lang="scss" scoped></style>
  • 修改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 组件样式 */
  • 使用案例

    <template><div class="wrap"><!-- 基础空表单 --><h3>基础空表单</h3><div class="box"><x-tableitemAlign="center":border="true":autoHeight="false":hasPagination="false":columns="columns1":tableData="[]"></x-table></div><!-- 基础表单 --><h3>基础表单</h3><div class="box"><x-tableitemAlign="center":border="true":autoHeight="false":hasPagination="false":columns="columns1":tableData="tableData1"></x-table></div><!-- 自动填充和分页 --><h3>自动填充和分页</h3><p>自动填充高度,并且能自动处理radio、checkbox、select的值</p><div class="box"><x-tableitemAlign="center":border="true":columns="columns2":tableData="tableData2"></x-table></div><!-- 自定义内容 --><h3>自定义内容</h3><div class="box"><x-tableitemAlign="center":border="true":columns="columns3":tableData="tableData3"></x-table></div><!-- 多表头 --><h3>多表头</h3><div class="box"><x-tableitemAlign="center":border="true":columns="columns4":tableData="tableData4"></x-table></div><!-- 多选 --><h3>多选</h3><div><el-button @click="getSelection('multipleTable')">获取选中结果</el-button><el-button @click="setSelection([tableData1[1], tableData1[2]])">设置选择第二项, 第三项</el-button><el-button @click="setSelection()">清空选中</el-button></div><div class="box"><x-tableref="multipleTable"itemAlign="center":border="true":multiple="true":columns="columns1":tableData="tableData1"></x-table></div><!-- 单选 --><h3>单选</h3><div><el-button @click="getSelection('singleTable')">获取选中结果</el-button><el-button @click="setRadio(tableData1[2])">设置选择第三项</el-button><el-button @click="setRadio()">清空选中</el-button></div><div class="box"><x-tableref="singleTable"itemAlign="center":border="true":hasRadio="true":columns="columns1":tableData="tableData1"></x-table></div><!-- 排序和筛选 --><h3>排序和筛选</h3><div class="box"><x-tableitemAlign="center":border="true":autoHeight="false":hasPagination="false":columns="columns5":tableData="tableData5"></x-table></div><!-- 嵌套内容 --><h3>嵌套内容</h3><div class="box"><x-tableitemAlign="center":border="true":autoHeight="false":hasPagination="false":columns="columns6":tableData="tableData5"></x-table></div><!-- 接口获取 --><h3>接口获取</h3><div class="box"><x-tableitemAlign="center":border="true":columns="columns7":api="getList"></x-table></div><!-- 搜索 --><h3>搜索</h3><div class="box"><x-tableitemAlign="center":border="true":columns="columns7":api="getList":search="{ name: '张三' }"></x-table></div></div>
    </template><script>
    import { getList } from "../api/mock.js";export default {name: "Page5",data() {return {search: "",columns1: [{ label: "姓名", prop: "name" },{ label: "年龄", prop: "age" },{ label: "地址", prop: "address" },],tableData1: [{ name: "张三1", age: 12, address: "北京市" },{ name: "张三2", age: 12, address: "北京市" },{ name: "张三3", age: 12, address: "北京市" },{ name: "张三4", age: 12, address: "北京市" },{ name: "张三5", age: 12, address: "北京市" },],columns2: [{ label: "姓名", prop: "name" },{ label: "年龄", prop: "age" },{label: "性别",prop: "sex",options: [{ label: "男", value: "0" },{ label: "女", value: "1" },],},{ label: "地址", prop: "address" },],tableData2: [{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },{ name: "张三", age: 12, sex: "1", address: "北京市" },{ name: "张三", age: 12, sex: "0", address: "北京市" },],columns3: [{ label: "姓名", prop: "name" },{ label: "年龄", prop: "age" },{ label: "地址", prop: "address" },{slotHeader: () => {return (<el-inputvalue={this.search}onInput={(val) => (this.search = val)}size="mini"placeholder="输入关键字搜索"/>);},slotDefault: (h, scope) => {return (<div><el-buttonsize="mini"onClick={() => this.handleEdit(scope.$index, scope.row)}>Edit</el-button><el-buttonsize="mini"type="danger"onClick={() => this.handleDelete(scope.$index, scope.row)}>Delete</el-button></div>);},},],tableData3: [{ name: "张三", age: 12, address: "北京市" },{ name: "张三", age: 12, address: "北京市" },{ name: "张三", age: 12, address: "北京市" },],columns4: [{label: "用户",children: [{ label: "姓名", prop: "name" },{ label: "年龄", prop: "age" },{label: "信息",children: [{ label: "身高", prop: "height" },{ label: "体重", prop: "weight" },{label: "性别",prop: "sex",options: [{ label: "男", value: "0" },{ label: "女", value: "1" },],},],},],},{ label: "地址", prop: "address" },],tableData4: [{name: "张三",age: 12,sex: "0",height: "175cm",weight: "65kg",address: "北京市",},{name: "张三",age: 12,sex: "1",height: "175cm",weight: "65kg",address: "北京市",},{name: "张三",age: 12,sex: "0",height: "175cm",weight: "65kg",address: "北京市",},],columns5: [{ label: "姓名", prop: "name" },{ label: "年龄", prop: "age", sortable: true },{label: "性别",prop: "sex",hasFilter: true,options: [{ label: "男", value: "0" },{ label: "女", value: "1" },],},{ label: "地址", prop: "address" },],tableData5: [{ name: "张三1", age: 12, sex: "1", address: "北京市" },{ name: "张三2", age: 13, sex: "0", address: "北京市" },{ name: "张三3", age: 14, sex: "0", address: "北京市" },{ name: "张三4", age: 15, sex: "1", address: "北京市" },{ name: "张三5", age: 16, sex: "0", address: "北京市" },],columns6: [{table: { type: "expand" },slotDefault: (h, scope) => {return (<el-form label-position="left"><el-form-item label="姓名"><span>{scope.row.name}</span></el-form-item><el-form-item label="年龄"><span>{scope.row.age}</span></el-form-item><el-form-item label="性别"><span>{scope.row.sex}</span></el-form-item><el-form-item label="地址"><span>{scope.row.address}</span></el-form-item></el-form>);},},{ label: "姓名", prop: "name" },{ label: "年龄", prop: "age", sortable: true },{label: "性别",prop: "sex",hasFilter: true,options: [{ label: "男", value: "0" },{ label: "女", value: "1" },],},{ label: "地址", prop: "address" },],columns7: [{ label: "姓名", prop: "name" },{ label: "年龄", prop: "age" },{label: "性别",prop: "sex",options: [{ label: "男", value: "0" },{ label: "女", value: "1" },],},{ label: "日期", prop: "date", props: { valueFormat: "yyyy-MM-DD" } },{ label: "地址", prop: "address" },],};},methods: {getList: getList,handleEdit(index, row) {console.log(index, row);},handleDelete(index, row) {console.log(index, row);},getSelection(key) {const selection = this.$refs[key].getSelection();console.log(selection);},setSelection(rows) {this.$refs.multipleTable.toggleSelection(rows);},setRadio(row) {this.$refs.singleTable.setCurrent(row);},},
    };
    </script><style lang="less" scoped>
    .wrap {width: 100%;height: 100%;display: flex;align-items: center;flex-direction: column;
    }.box {width: 800px;height: 500px;padding: 10px;margin-bottom: 20px;background: #1f03034d;
    }
    </style>
  • 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企业级项目(七)

vue2企业级项目&#xff08;七&#xff09; 组件封装 src目录下创建components/index.js const components require.context("./modules", true, /index\.js$/);export default {install: (Vue) > {components.keys().forEach((key) > {let component compo…...

PDPS教程:导出带颜色的JT格式2D布局图文件的另一种方法

目录 概述 布局图平面化与边缘化处理 导出为JT格式文件 JT格式文件查看 概述 在PDPS软件中导入机器人生产线或工作站2D布局图之前&#xff0c;要先将布局图文件转换为JT格式。 使用Crossmanager软件转换出来的2D布局图文件会将图形元素原有的颜色自动修改为黑白颜色&…...

AI面试官:Asp.Net 中使用Log4Net (二)

AI面试官&#xff1a;Asp.Net 中使用Log4Net (二) 当面试涉及到使用log4net日志记录框架的相关问题时&#xff0c;通常会聚焦在如何在.NET或.NET Core应用程序中集成和使用log4net。以下是一些关于log4net的面试题目&#xff0c;以及相应的解答、案例和代码&#xff1a; 文章目…...

C# Solidworks二次开发:向量相关的数学函数API的使用介绍

今天要讲的是Solidworks二次开发时候&#xff0c;如何使用一些与数学相关的API方法的介绍&#xff0c;在Solidworks中本身提供了一个函数用于对数学对象的访问&#xff0c;函数名为MathUtility。借助这个函数&#xff0c;我们来引出今天要介绍的几个API。 &#xff08;1&#…...

table 导出表格 Excel

在请求中需要设置 responseType: blob export const requestExport (api, method, params {}, config) > {const apiToken localStorage.getItem(token);const data method GET ? params : data;let headers {BackServer-Token: ${apiToken},};if (config?.headers…...

基于 Flink SQL CDC 数据处理的终极武器

文章目录 一、传统的数据同步方案与 Flink SQL CDC 解决方案1.1 Flink SQL CDC 数据同步与原理解析1.2 基于日志的 CDC 方案介绍1.3 选择 Flink 作为 ETL 工具 二、 基于 Flink SQL CDC 的数据同步方案实践2.1 CDC Streaming ETL2.2 Flink-CDC实践之mysql案例 来源互联网多篇文…...

uniapp使用HQChart的k线,用webSocket更新数据

项目&#xff1a;不借用HQChart的各种接口数据&#xff0c;即数据后端返回&#xff0c;但是数据格式要和原数据格式一样。 //k线图 CreateHQChartKLine(){var chartHeightuni.upx2px(this.ChartHeight);let hqchartCtrlthis.$refs.HQChartCtrl;hqchartCtrl.KLine.Option.Type&…...

idea的Plugins中搜索不到插件

1、ctrlalts 打开设置 ; 2、搜索框输入plugins; 3、点击plugins; 4、点齿轮按钮&#xff0c;选择HTTP Proxy settings; 如下操作&#xff1a; 5、刷新DNS&#xff0c;ipconfig /flushdns 6、重新打开idea 的plugins 插件列表出来了...

flask 实现简单的登录系统demo

你提供的代码是一个基本的Flask应用程序&#xff0c;实现了一个简单的登录系统。以下是代码的详细解释&#xff1a; 1. 导入必要的模块&#xff1a;os 用于生成密钥&#xff0c;Flask 用于创建Web应用程序。 2. 创建Flask应用程序的实例&#xff0c;并为会话管理设置一个密钥。…...

Spring Security安全配置

使用Spring Boot与Spring MVC进行Web开发时&#xff0c;如果项目引入spring-boot- starter-security依赖启动器&#xff0c;MVC Security 安全管理功能就会自动生效&#xff0c;其默认的安全配置是在SecurityAutoConfiguration和UserDetailsServiceAutoConfiguration中实现的。…...

2023Java后端开发之100道常见经典面试题

目录 1.重载和重写的区别? 2.String 和 StringBuffer、StringBuilder 的区别是什么&#xff1f; 3. 与 equals 的区别&#xff1f; 4.抽象类和接口的区别是什么&#xff1f; 5. 面向对象的特点 6.Collection 和 Collections 有什么区别&#xff1f; 7.List、Set、Map 之…...

Redis详解,包括安装命令,应用场景,优缺点,案列分析,各个开发语言如何应用

目录 1、安装命令2、应用场景3、优缺点4、案例分析5、各个开发语言如何应用&#xff1f; Redis 是一个基于内存的开源数据库系统&#xff0c;被广泛应用于 Web 应用、消息队列、缓存、实时统计等领域。下面是 Redis 的详解&#xff0c;包括安装命令、应用场景和优缺点&#xff…...

AI数字人:金融数字化转型的“关键先生”

今年年初ChatGPT的火热&#xff0c;在全球掀起一阵生成式AI&#xff08;AIGC&#xff09;热潮。国外的OpenAI、国内的百度等企业&#xff0c;都在AIGC上强力布局。 各种应用场景中&#xff0c;AIGC助力的数字人引起了市场注意。 事实上&#xff0c;数字人不是个新鲜事。早在1…...

mac关闭VPN之后,浏览器就不能够正常上网了(图解)

可能打开谷歌浏览器会显示无法正常连接网络等信息&#xff0c;这个时候可以按照以下步骤&#xff1a; 点击"检查代理服务器地址" 会显示以下这段话&#xff0c;按照这个步骤来操作就可以了。 打开系统偏好设置&#xff0c;点击网络 点击高级 取消掉所有已勾选代…...

YOLOv5改进系列(17)——更换IoU之MPDIoU(ELSEVIER 2023|超越WIoU、EIoU等|实测涨点)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制...

基于WSL2、Ubuntu和VS Code的CUDA平台运行C语言程序

一、CUDA程序执行方法 执行步骤为&#xff1a; 安装Visual Studio Code。在Visual Studio Code中安装插件WSL与电脑的WSL2进行连接。点击左下角&#xff0c;然后再选择连接到WSL。 在WSL中创建以 .cu 为后缀的文件。 rootDESKTOP-HR6VO5J:~# mkdir CUDA /…...

构建外卖系统小程序,订单管理功能实现步骤详解

外卖系统小程序是近年来越来越受欢迎的一种订餐方式&#xff0c;方便快捷&#xff0c;并且可以减少人与人之间的接触&#xff0c;更加卫生安全。为了搭建一个完善的外卖系统小程序&#xff0c;订单管理功能是必不可少的一部分。在本文中&#xff0c;我们将详细介绍如何实现订单…...

用asp.net开发h5网页版视频播放网站,类似优酷,jellyfin,emby

之前用jellyfin开源软件搞了一个视频播放服务器,用来共享给家里人看电影和电视剧,jellyfin虽然各方面功能都很强大,但是界面和使用习惯都很不适合,于是就想着利用下班休息时间做一套自己喜欢的视频网站出来. 本来是打算直接用jellyfin的源码进行修改,源码是用C# netcore 写的服…...

Redis—相关背景

Redis—相关背景 &#x1f50e;Redis—特性In-memory data structures—在内存中存储数据Programmability—可编程性Extensibility—可扩展性Persistence—持久化Clustering—集群High availability—高可用 &#x1f50e;Redis 为什么快&#x1f50e;Redis 的使用场景Real-tim…...

SSL 证书过期巡检脚本

哈喽大家好&#xff0c;我是咸鱼 我们知道 SSL 证书是会过期的&#xff0c;一旦过期之后需要重新申请。如果没有及时更换证书的话&#xff0c;就有可能导致网站出问题&#xff0c;给公司业务带来一定的影响 所以说我们要每隔一定时间去检查网站上的 SSL 证书是否过期 如果公…...

leetcode 面试题 01.03. URL化

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;面试题 01.03. URL化 思路&#xff1a; 计算出空格的个数&#xff0c;我们可以知道最后一个字符的位置 endPos&#xff0c;再从后 end 向前遍历若不是空格正常拷贝&#xff0c;是空格则替换成 %20&#xff0c;最终当空格…...

uni-app在小米手机上运行【步骤细节】

注意细节重点&#xff1a; 1.手机使用数据线与电脑连接&#xff0c;手机连接模式必须是传输文件模式 2.手机必须打开开发者模式 3.打开开发者模式后&#xff0c;仔细浏览并调整USB调试权限&#xff0c;重点打开USB是否允许安装按钮&#xff01;&#xff01;&#xff01; 操作步…...

微信小程序实现日历功能、日历转换插件、calendar

文章目录 演示htmlJavaScript 演示 效果图 微信小程序实现交互 html <view wx:if"{{calendarArr.length}}"><view class"height_786 df_fdc_aic"><view class"grid_c7_104"><view class"font_weight_800 text_align…...

【浩鲸科技】济南Java后端面经

本文目录 写在前面试题总览题目解析1.说一下SpringBoot中常用的注解2.Redis中的基本数据类型3.TCP的网络协议4.java中常见的锁5.Hashmap的底层数据结构、底层源码、扩容机制源码6.java面向对象的特点 写在前面 关于这个专栏&#xff1a; 本专栏记录一些互联网大厂、小厂的面试实…...

VMware搭建Hadoop集群 for Windows(完整详细,实测可用)

目录 一、VMware 虚拟机安装 &#xff08;1&#xff09;虚拟机创建及配置 &#xff08;2&#xff09;创建工作文件夹 二、克隆虚拟机 三、配置虚拟机的网络 &#xff08;1&#xff09;虚拟网络配置 &#xff08;2&#xff09;配置虚拟机 主机名 &#xff08;3&#xf…...

【Rust 基础篇】Rust关联类型:灵活的泛型抽象

导言 Rust是一种以安全性和高效性著称的系统级编程语言&#xff0c;其设计哲学是在不损失性能的前提下&#xff0c;保障代码的内存安全和线程安全。为了实现这一目标&#xff0c;Rust引入了"所有权系统"、"借用检查器"等特性&#xff0c;有效地避免了常见…...

学习笔记21 list

一、概述 有两种不同的方法来实现List接口。ArrayList类使用基于连续内存分配的实现&#xff0c;而LinkedList实现基于linked allocation。 list接口提供了一些方法&#xff1a; 二、The ArrayList and LinkedList Classes 1.构造方法 这两个类有相似的构造方法&#xff1a…...

微信小程序弱网监控

前言 在真实的项目中&#xff0c;我们为了良好的用户体验&#xff0c;会根据用户当前的网络状态提供最优的资源&#xff0c;例如图片或视频等比较大的资源&#xff0c;当网络较差时&#xff0c;可以提供分辨率更低的资源&#xff0c;能够让用户尽可能快的看到有效信息&#xf…...

【Linux】进程通信 — 共享内存

文章目录 &#x1f4d6; 前言1. 共享内存2. 创建共享内存2.1 ftok()创建key值&#xff1a;2.2 shmget()创建共享内存&#xff1a;2.3 ipcs指令&#xff1a;2.4 shmctl()接口&#xff1a;2.5 shmat()/shmdt()接口:2.6 共享内存没有访问控制&#xff1a;2.7 通过管道对共享内存进…...

“从零开始学习Spring Boot:快速搭建Java后端开发环境“

标题&#xff1a;从零开始学习Spring Boot&#xff1a;快速搭建Java后端开发环境 摘要&#xff1a;本文将介绍如何从零开始学习Spring Boot&#xff0c;并详细讲解如何快速搭建Java后端开发环境。通过本文的指导&#xff0c;您将能够快速搭建一个基于Spring Boot的Java后端开发…...