vue2企业级项目(九)
组件封装(三)
7、input-number
-
创建
components/input-number/index.js
import XInputNumber from "./index.vue"; export default XInputNumber;
-
创建
components/input-number/index.vue
<template> <el-input :value="inputValue" @input="handleInput"></el-input> </template> <script> import Big from "big.js"; /** * @param { String } value: 绑定value * @param { Number } min: 最小值 * @param { Number } max: 最大值 * @param { Boolean } permillage: 是否需要千分号 */ export default { name: "XInputNumber", props: { value: { type: String, default: "", }, min: { type: Number, default: null, }, max: { type: Number, default: null, }, permillage: { type: Boolean, default: false, }, }, data() { return { inputValue: "", }; }, created() { this.inputValue = this.handleInput(this.value); }, methods: { handleInput(val) { let num = val; if (this.permillage) num = num.replaceAll(",", ""); if (isNaN(num)) return; num = num === "" ? num : new Big(num); if (this.min && num && this.min > num) num = this.min; if (this.max && num && this.max < num) num = this.max; num = num.toString(); this.inputValue = num; if (this.permillage) { this.inputValue = this.inputValue.replace(/\B(?=(\d{3})+(?!\d))/g, ","); } this.$emit("input", num); }, }, }; </script>
8、update
主要适配xform
,统一文件上传接口,其他作用不是特别大。
-
创建
components/updateFile/index.js
import XUpload from "./index.vue"; export default XUpload;
-
创建
components/updateFile/index.vue
<template> <el-upload action="#" :multiple="multiple" :on-change="onChange" :http-request="httpRequest" :on-success="handleSuccess" v-bind="$attrs" v-on="$listeners" > <slot></slot> <template #trigger> <slot name="trigger"></slot> </template> <template #tip> <slot name="tip"></slot> </template> </el-upload> </template> <script> import { cloneDeep } from "lodash"; import { checkDataType } from "@/utils/utils"; export default { name: "XUpload", props: { value: { type: [Array, Object], default: null, }, multiple: { type: Boolean, default: false, }, api: { type: Function, default: null, }, }, data() { return { fileList: [], }; }, mounted() { this.init(); }, methods: { init() { if (!this.value) return; if (checkDataType(this.value, "array")) { this.fileList = cloneDeep(this.value); } if (checkDataType(this.value, "object")) { this.fileList = [this.value]; } }, onChange(file, fileList) { if (!this.api) { this.fileList = fileList; if (this.multiple) this.$emit("input", fileList); else this.$emit("input", fileList[0]); } }, /* 存在固定的文件服务器是, 可以统一文件上传接口 */ httpRequest() { return null; // return this.api({ file: obj.file }); }, handleSuccess(response, file, fileList) { this.fileList = fileList; if (this.multiple) this.$emit("input", fileList); else this.$emit("input", fileList[0]); }, }, }; </script>
9、theme-color
切换主题色、使用上面的动态切换主题原理实现
-
创建
components/theme-color/index.js
import XThemeColor from "./index.vue"; export default XThemeColor;
-
创建
components/theme-color/index.vue
<template> <el-color-picker v-model="color"></el-color-picker> </template> <script> import client from "webpack-theme-color-replacer/client"; /** * @deprecated 目前先写变量,后期根据业务调整,看是放在本地存储,还是跟随用户配置信息 */ export default { name: "XThemeColor", data() { return { color: "#409EFF", }; }, watch: { color: { immediate: true, handler(color) { client.changer.changeColor({ newColors: ["" + color] }); }, }, }, }; </script>
10、screenfull
全屏按钮、使用插件screenfull@4.2.0
npm install --save screenfull@4.2.0
请原谅我臭不要脸的抄袭了vue-element-admin
的代码。捂脸
-
创建
components/screenfull/index.js
import XScreenfull from "./index.vue"; export default XScreenfull;
-
创建
components/screenfull/index.vue
<template> <el-button icon="el-icon-full-screen" type="primary" circle @click="click" ></el-button> </template> <script> import screenfull from "screenfull"; export default { name: "XScreenfull", data() { return { isFullscreen: false, }; }, mounted() { this.init(); }, beforeDestroy() { this.destroy(); }, methods: { click() { if (!screenfull.enabled) { this.$message({ message: "you browser can not work", type: "warning", }); return false; } screenfull.toggle(); }, change() { this.isFullscreen = screenfull.isFullscreen; }, init() { if (screenfull.enabled) { screenfull.on("change", this.change); } }, destroy() { if (screenfull.enabled) { screenfull.off("change", this.change); } }, }, }; </script>
11、screenshot
截屏按钮、使用插件html2canvas
npm install --save html2canvas
-
创建
components/screenshot/index.js
import XScreenshot from "./index.vue"; export default XScreenshot;
-
创建
components/screenshot/index.vue
<template> <el-button icon="el-icon-camera-solid" type="primary" circle @click="click" ></el-button> </template> <script> import html2canvas from "html2canvas"; /** * @param { String } dom 截图的dom * @param { String } fileName 截图的文件名 */ export default { name: "XScreenshot", props: { dom: { type: String, default: "#app", }, fileName: { type: String, default: "screenshot.png", }, }, methods: { click() { const screenshotContainer = document.querySelector(this.dom); console.log(screenshotContainer); html2canvas(screenshotContainer) .then((canvas) => { const eLink = document.createElement("a"); eLink.download = this.fileName; eLink.style.display = "none"; eLink.href = canvas.toDataURL(); document.body.appendChild(eLink); eLink.click(); document.body.removeChild(eLink); }) .catch((error) => { console.error(error); }); }, }, }; </script>
12、navTabs
-
目的:由于
el-tabs
并不具备左右拖动的功能,所以在某些业务需要添加这个功能 -
推荐使用插件
vue-tabs-chrome
-
这里提供一个使用
sortablejs
封装的,仅针对el-tabs
的扩展方法// src/utils/utils.js ... import Sortable from "sortablejs"; ... /** * @deprecated 直接作用el-tabs,让el-tabs的标签可以拖拽重新排序 * * @param { VNode } vnode: 获取到的ref对象,用来区分多个el-tabs * @param { Function } handleEnd: 拖拽完成后回调函数 */ export function initSortable(vnode, handleEnd) { if (!vnode) return; const el = vnode.$el.querySelector(".el-tabs__nav"); Sortable.create(el, { draggable: ".el-tabs__item", handle: ".el-tabs__item", direction: "horizontal", onEnd: handleEnd || null, }); }
-
使用案例
<template> <el-tabs v-model="editableTabsValue" type="card" ref="navtabs"> <el-tab-pane v-for="item in editableTabs" :key="item.name" :label="item.title" :name="item.name" > {{ item.content }} </el-tab-pane> </el-tabs> </template> <script> import { initSortable } from "@/utils/utils"; export default { data() { return { editableTabsValue: "2", editableTabs: [ { title: "Tab 1", name: "1", content: "Tab 1 content", }, { title: "Tab 2", name: "2", content: "Tab 2 content", }, ], } }, mounted() { initSortable(this.$refs.navtabs); }, } </script>