vite.config.ts中添加
|
1 2 3 4 5 6 |
resolve: { // 文件系统路径的别名 alias: { 'vue': 'vue/dist/vue.esm-bundler.js' } } |
更多配置参考:https://vitejs.dev
vite.config.ts
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
import vue from '@vitejs/plugin-vue' import vueJsx from '@vitejs/plugin-vue-jsx' import { defineConfig } from "vite" const fs = require("fs") const path = require("path") // Dotenv 是一个零依赖的模块,它能将环境变量中的变量从 .env 文件加载到 process.env 中 const dotenv = require("dotenv") const envFiles = [ /** default file */ `.env`, /** mode file */ `.env.${process.env.NODE_ENV}` ] for (const file of envFiles) { const envConfig = dotenv.parse(fs.readFileSync(file)) for (const k in envConfig) { process.env[k] = envConfig[k] } } export default defineConfig({ define: { 'process.env': process.env }, // 开发或生产环境服务的公共基础路径 base: './', // 作为静态资源服务的文件夹 publicDir: 'assets', plugins: [vue(), vueJsx()], resolve: { // 文件系统路径的别名 alias: { '@': path.resolve(__dirname, 'src'), 'vue': 'vue/dist/vue.esm-bundler.js', 'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js' } }, css: { preprocessorOptions: { scss: { additionalData: '@import "./src/assets/style/index.scss";' } } }, build: { // 压缩 minify: process.env.VITE_NODE_ENV === 'production' ? 'esbuild' : false, // 服务端渲染 ssr: false, outDir: 'dist', chunkSizeWarningLimit: 2000, emptyOutDir: true, rollupOptions: { output: { manualChunks(id) { if (id.includes('node_modules')) { return id.toString().split('node_modules/')[1].split('/')[0].toString() } } } } }, server: { host: process.env.VITE_HOST, port: +process.env.VITE_PORT, // 是否自动在浏览器打开 open: false, hmr: true, proxy: { '/api': { target: "http://127.0.0.1:99999", changeOrigin: true } } } }) |
.env
|
1 2 3 4 5 |
# loaded in all cases VITE_HOST = '0.0.0.0' VITE_PORT = 8080 VITE_BASE_URL = './' VITE_OUTPUT_DIR = 'dist' |
&[……]
核心是使用v-if控制列的显隐
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
<template> <div> <div v-for="(item, index) in tables" :key="index"> <el-table :data="item.data" @filter-change="value => filterChange(value,index, 'tables')" :span-method="value => cellMerge(value,'tables')" :header-cell-style="{background:'#fbfbfb'}" size="mini" doLayout border > <el-table-column v-for="(ele,index) in item.columns" :label="ele.text" :prop="ele.value" show-overflow-tooltip v-if="ele.flag" :key="ele.value + index" :resizable="false" > <template slot-scope="scope"> <span>{{scope.row[scope.column.property]}}</span> </template> </el-table-column> <el-table-column :key="item.columns.length + 1" fixed="right" width="50" v-if="item.stash_columns" :filters="item.stash_columns" :filtered-value="item.filter_value" :resizable="false" > <template slot="header" slot-scope="scope"> <i class="el-icon-menu" style="cursor: pointer"></i> </template> </el-table-column> </el-table> </div> </div> </template> <script> export default { data () { return { tables: [ { data: [], columns: [ { text: '滴滴', value: 'didi', flag: true }, { text: '哒哒', value: 'dada', flag: true }, { text: '嘿嘿', value: 'heihei', flag: true }, { text: '哈哈', value: 'haha', flag: false } ] } ] } }, methods: { // 处理数据 handlerData (type) { const data = [{didi: '11', dada: '22', heihei: '33', haha: '44'}] const tables = this[type] tables && tables.length > 0 && tables.map((item, index) => { this.$set(this[type][index], 'data', data) this.$set(this[type][index], 'stash_columns', item.columns) this.$set(this[type][index], 'filter_value', []) const columns = item.stash_columns const filter_value = item.filter_value columns && columns.length > 0 && columns.map((ele, idx) => { if (ele.flag) { filter_value.push(ele.value) } }) this.$set(this[type][index], 'filter_value', filter_value) }) }, // 控制列显隐 filterChange (value, idx, type) { switch (type) { case type: for (const ele in value) { this.$set(this[type][idx], 'show_columns', value[ele]) } const tables = this[type] tables && tables.length > 0 && tables.map((item, index) => { const columns = item.columns const show_columns = item.show_columns if (show_columns && show_columns.length > 0) { columns && columns.length > 0 && columns.map((val, key) => { this.$set(this[type][index].columns[key], 'flag', false) show_columns.map((ele) => { if (val.value === ele) { this.$set(this[type][index].columns[key], 'flag', true) } }) }) } }) break default: break } }, // 合并单元格 cellMerge ({row, column, rowIndex, columnIndex}, type) { this.$nextTick(() => { const tables = this[type] tables && tables.length > 0 && tables.map((item, index) => { const show_columns = item.show_columns const length = show_columns && show_columns.length > 0 ? show_columns.length : item.columns.length if (columnIndex === length - 1) { return [1, 0] } else if (columnIndex === length) { return [0, 0] } }) }) } }, mounted () { this.handlerData('tables') } } </script> |
访问者模式(Visitor Pattern)
|
1 2 3 |
定义:使用一个访问者类,改变元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。 目的:将数据结构与数据操作分离。 场景:您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
// 元素:圆形 class Circle { constructor(radius) { this.radius = radius } accept(visitor) { return visitor.visitCircle(this) } } // 元素:矩形 class Rectangle { constructor(width, height) { this.width = width this.height = height } accept(visitor) { return visitor.visitRectangle(this) } } // 访问者:计算面积 class AreaVisitor { visitCircle(circle) { return Math.PI * circle.radius ** 2 } visitRectangle(rectangle) { return rectangle.width * rectangle.height } } // 访问者:计算周长 class PerimeterVisitor { visitCircle(circle) { return 2 * Math.PI * circle.radius } visitRectangle(rectangle) { return 2 * (rectangle.width + rectangle.height) } } // 使用 const rectangle = new Rectangle(3, 4) const circle = new Circle(1) const areaVisitor = new AreaVisitor() const perimeterVisitor = new PerimeterVisitor() console.log(rectangle.accept(areaVisitor)) // 12 console.log(rectangle.accept(perimeterVisitor)) // 14 console.log(circle.accept(areaVisitor)) // 约 3.14 console.log(circle.accept(perimeterVisitor)) // 约 6.28 |
解释器模式(Interpreter Pattern)
|
1 2 3 |
定义:提供了评估语言的语法或表达式的方式。 目的:对于一些固定文法构建一个解释句子的解释器。 场景:编译器、运算表达式计算。 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
// 基础表达式:判断是否包含关键词 class Keyword { constructor(word) { this.word = word } interpret(context) { return context.includes(this.word) } } // 或表达式:满足任意一个条件 class Or { constructor(left, right) { this.left = left this.right = right } interpret(context) { return this.left.interpret(context) || this.right.interpret(context) } } // 与表达式:必须同时满足两个条件 class And { constructor(left, right) { this.left = left this.right = right } interpret(context) { return this.left.interpret(context) && this.right.interpret(context) } } // 构建规则:(John OR Robert) AND Married const rule = new And( new Or( new Keyword('John'), new Keyword('Robert') ), new Keyword('Married') ) // 解释输入,得到结果 console.log(rule.interpret('John Married')) // true console.log(rule.interpret('Robert Married')) // true console.log(rule.interpret('John')) // false console.log(rule.interpret('Julie Married')) // false |
中介者模式(Mediator Pattern)
|
1 2 3 |
定义:用来降低多个对象和类之间的通信复杂性。 目的:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 场景:MVC框架中的控制器C就是模型M和识图V的中介者。 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
// 中介者:统一协调跑道 const tower = { currentPlane: null, requestLanding(plane) { if (this.currentPlane) { console.log(`${plane.name}:跑道被占用,请等待`) return } this.currentPlane = plane plane.land() }, releaseRunway(plane) { if (this.currentPlane === plane) { this.currentPlane = null } } } // 参与者:只与塔台通信,不直接联系其他飞机 class Plane { constructor(name, tower) { this.name = name this.tower = tower } requestLanding() { this.tower.requestLanding(this) } land() { console.log(`${this.name}:开始降落`) } leaveRunway() { this.tower.releaseRunway(this) } } const planeA = new Plane('飞机A', tower) const planeB = new Plane('飞机B', tower) planeA.requestLanding() // 飞机A:开始降落 planeB.requestLanding() // 飞机B:跑道被占用,请等待 planeA.leaveRunway() planeB.requestLanding() // 飞机B:开始降落 |
Github地址:https://github.com/skillnull/Design-Mode-Example[……]
职责链模式(Chain of Responsibility Pattern)
|
1 2 3 |
定义:为请求创建了一个接收者对象的链。 目的:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。 场景:红楼梦中的"击鼓传花"。 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
class Approver { constructor(name, limit) { this.name = name this.limit = limit this.next = null } processRequest(request) { // 自己能处理,就处理并结束 if (request.amount < this.limit) { console.log(`${this.name}批准采购:${request.productName}`) return } // 自己不能处理,交给下一级 if (this.next) { return this.next.processRequest(request) } // 已经到达链尾,仍然无法处理 console.log(`采购金额超出审批权限:${request.productName}`) } } // 创建审批者 const manager = new Approver('经理', 10000) const vicePresident = new Approver('副总', 25000) const president = new Approver('总经理', 100000) // 连接职责链:经理 → 副总 → 总经理 manager.next = vicePresident vicePresident.next = president // 所有请求都从链头提交 manager.processRequest({ amount: 4000, productName: '电话' }) manager.processRequest({ amount: 10000, productName: '软件' }) manager.processRequest({ amount: 40000, productName: '电脑' }) manager.processRequest({ amount: 200000, productName: '服务器' }) |
输出:
经理批准采购:电话
副总批准采购:软件
总经理批准采购:电脑
采[……]