So verwenden Sie Vue3+ts zur Entwicklung von ProTable
Front-End-Implementierung
Erfolgseffekt
Technologie-Stack
vue3 + Typescript + Element-Plus
Nutzung
<template> <el-tabs type="border-card" v-model="activeName"> <el-tab-pane :label="item.label" v-for="(item, index) in templateConfig" :key="index" :name="item.name" lazy > <!--所有的 slot内容都在表格内部处理好, columnsType进行区分--> <pro-table :columns="item.columns" :type="item.name" :request-url="requestUrl" > </pro-table> </el-tab-pane> </el-tabs> </template> <script lang="ts" setup> import { ref } from 'vue' import ProTable from './components/ProTable/index.vue' import { ColumnProps, RequestUrl } from './components/ProTable/types' import { projectConfig, projectConfigBatchDelete } from './service/api' const activeName = ref('user') interface TemplateConfig { name: string label: string columns: ColumnProps[], } const requestUrl: RequestUrl = { create: projectConfig, list: projectConfig, update: projectConfig, destroy: projectConfig, batchDelete: projectConfigBatchDelete } const templateConfig = ref<TemplateConfig[]>([ { label: 'ProTable', name: 'user', columns: [ { key: 'userName', title: '用户名', searchType: 'el-input' }, { key: 'password', title: '密码', searchType: 'el-input' }, { key: 'email', title: '邮箱', searchType: 'el-input' }, { key: 'phone', title: '手机号', searchType: 'el-input' }, { key: 'role', title: '角色', searchType: 'z-select', attrs: { options: [ { label: '管理员', value: 'admin' }, { label: '普通用户', value: 'user' } ] } }, { key: 'status', title: '状态', searchType: 'z-select', attrs: { options: [ { label: '启用', value: 1 }, { label: '禁用', value: 0 } ] }, columnType: 'status' }, { key: 'hasUseArray', title: '是否使用数组参数?', search: false, searchType: 'useExpandField', show: false, add: false }, { key: 'arrayParams', title: '数组参数', searchType: 'z-array', search: false, width: 120, add: false, show: false }, { key: 'hasUseArray', title: '是否使用JSON参数?', search: false, searchType: 'useExpandField', show: false, add: false }, { key: 'jsonParams', title: 'JSON参数', searchType: 'z-json', search: false, width: 120, add: false, show: false }, { key: 'createdAt', title: '创建时间', width: 180, searchType: 'el-date-picker', add: false }, { key: 'updatedAt', title: '更新时间', width: 180, searchType: 'el-date-picker', add: false }, { key: 'action', title: '操作', search: false, add: false, width: 150 } ] } ]) </script> <style lang="less"> </style>
ProTable-Designidee
Die Seite ist in 5 Bereiche unterteilt,
Einzelner Suchbereich
Tabellenfunktionsschaltflächenbereich
Bedienbereich in der oberen rechten Ecke der Tabelle
Tabellenthemenbereich
Tabellenpaginierungsbereich
Welche Probleme sollten berücksichtigt werden?
Welche Bereiche sollten eingehende Slots unterstützen?
Soll der ursprüngliche Steckplatz des Formulars an den Benutzer übergeben werden oder intern gekapselt werden? Wenn beispielsweise
colum
ein Status ist, muss er einemtag
zugeordnet werden, und wenn es sich um einen Typarray
handelt, muss dies der Fall sein einer Tabelle zugeordnet, diejson
ist. Wann müssen Sie klicken, um Details anzuzeigen? Es wäre zu mühsam, jede Tabelle zu verarbeiten. Wir hoffen, sie über ein Feld steuern zu können.colum
是状态的时候需要映射成tag
,是数组
类型的时候映射成表格,是json
的时候需要点击查看详情?假设每个表格都要处理的的话就太麻烦,我们希望通过一个字段来控制它。有
column
的某一列是否需要复制的功能?列字段需要编辑的功能?
实现的过程中有哪些细节?
表格的高度,把可表格可视区域的大小交给用户自己来控制,把批量操作按钮放在最下面(
fixed
定位)。这样用户可以在最大区域内看到表格的内容。
编码风格
组件上面属性如果超过三个,就换行
eslint使用的是
standard
风格。
css 小知识
<div class='box'> <div class='z'></div> </div>
*{ box-sizing: border-box; } .box{ display: inline-block; vertical-align: top; } .z{ height: 32px; border: 1px solid; width: 100px; display: inline-block; }
如果把盒子变成了行内
元素之后,若其内部还是行内元素,那么就会产生间隙,就会导致其高度与父元素高度不同。如下。
解决方法也很简单,则需要设置其子元素的vertical-align
属性,或者设置font-size: 0
,其根本原因是因为中间的文本元素也占位置。再或者不使用inline-block
,换做inline-flex
属性完全没有问题,因为在element-plus
组件库中也大量的使用了这个属性,兼容性也很nice。
这个几个解决方法很早就知道了,就是关于vertical-algin
这个,以及与line-height
的关系还是有点模糊,一直也没去深究。
放两篇文章
CSS vertical-align 属性
还有联想到baseline
这个东西在flex
,align-items属性:交叉轴上的一个属性很像。
flex布局语法教程详解
表格操作
添加数据之后,重新获取数据的时候
pageIndex
要重置为1,删除数据的时候也是一样。编辑数据的时候,
pageIndex
不变,还是当前页码。总结下来,就是当数据条数会发生改变的时候,都会重置
pageIndex
为1
。当用户操作不会影响数据总条数的时候,pageSize
还维持当前不变。
小结
使用了一个库,可以监听dom元素大小的变化,resize-observer-polyfill。
在 3.x 中,如果一个元素同时定义了
v-bind="object"
和一个相同的独立 attribute。开发者可以自己选择要保留哪一个。
文档地址# v-bind 合并行为
参考文章
JavaScript API——ResizeObserver 的使用
后期功能扩展
字段之间有关联关系情况的处理,暂时还没想好。
扩展一下
slot
等等。。
迭代中....
后台实现
数据库 mysql
我这里使用的是 xampp
Muss eine bestimmte Spalte von
column
kopiert werden?
Benötigen Sie die Möglichkeit, Spaltenfelder zu bearbeiten?
Was sind die Details im Umsetzungsprozess?
feste
Positionierung). Auf diese Weise kann der Benutzer den Inhalt der Tabelle im größten Bereich sehen. 🎜🎜🎜🎜Codierungsstil🎜🎜🎜🎜Wenn die Komponente mehr als drei Attribute enthält, packen Sie sie in neue Zeilen ein. 🎜🎜🎜🎜eslint verwendet den Standard
-Stil. 🎜🎜🎜🎜css-Tipps🎜CREATE TABLE `project_config` ( `id` int NOT NULL AUTO_INCREMENT COMMENT '主键', `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '配置类型', `value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '配置的json字符串', `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 65 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = COMPACT;
npm init egg --type=simple
inline
-Element umgewandelt wird und es sich darin noch um ein Inline-Element handelt, entsteht eine Lücke, die dazu führt, dass ihre Höhe von der abweicht Höhe des übergeordneten Elements. wie folgt. 🎜🎜
vertical-align
seiner untergeordneten Elemente festlegen oder font-size: 0
festlegen. Der Hauptgrund ist, dass der mittlere Text Element besetzt auch die Position. Alternativ können Sie anstelle von inline-block
das Attribut inline-flex
verwenden. Dies ist überhaupt kein Problem, da es auch eine große Anzahl davon im element-plus
-Komponentenbibliothek ist ebenfalls sehr gut. 🎜🎜Ich kenne diese Lösungen schon seit langem, aber die Beziehung zwischen vertical-algin
und line-height
ist immer noch etwas vage und ich habe mich nie damit befasst . . 🎜🎜
baseline
in flex
, align-items-Attribut: Ein Attribut auf der Querachse ist sehr ähnlich. 🎜🎜Detaillierte Erläuterung des Flex-Layout-Syntax-Tutorials🎜🎜Tabellenoperation🎜🎜🎜🎜Nach dem Hinzufügen von Daten sollte pageIndex
beim erneuten Abrufen von Daten auf 1 zurückgesetzt werden, und das Gleiche gilt beim Löschen von Daten. 🎜🎜🎜🎜Beim Bearbeiten von Daten ändert sich pageIndex
nicht, es ist immer noch die aktuelle Seitenzahl. 🎜🎜🎜🎜Zusammenfassend lässt sich sagen, dass pageIndex
auf 1
zurückgesetzt wird, wenn sich die Anzahl der Datenelemente ändert. Wenn Benutzeroperationen keinen Einfluss auf die Gesamtzahl der Daten haben, bleibt pageSize
unverändert. 🎜🎜🎜🎜Zusammenfassung🎜🎜🎜🎜Mit einer Bibliothek, die Änderungen in der Größe von Dom-Elementen überwachen kann, resize-observer-polyfill. 🎜🎜🎜🎜In 3.x, wenn ein Element sowohl v-bind="object"
als auch ein identisches unabhängiges Attribut definiert. Entwickler können wählen, welches sie behalten möchten. 🎜🎜🎜🎜Dokumentadresse # V-Bind-Zusammenführungsverhalten🎜🎜Referenzartikel🎜🎜JavaScript-API——Verwendung von ResizeObserver🎜🎜Spätere Funktionserweiterung🎜🎜🎜🎜Wie man mit der Korrelation zwischen Feldern umgeht, darüber habe ich noch nicht nachgedacht noch . 🎜🎜🎜🎜slot
erweitern 🎜🎜🎜🎜 und so weiter. . 🎜🎜🎜🎜Iterieren....🎜🎜
npm install --save egg-sequelize mysql2
'use strict'; /** @type Egg.EggPlugin */ exports.sequelize = { enable: true, package: 'egg-sequelize', }; exports.cors = { enable: true, package: 'egg-cors', };
RESTful 风格的 URL 定义
Sequelize
npm install --save egg-sequelize mysql2
在
config/plugin.js
中引入 egg-sequelize 插件, 这里我们引入了一个库egg-cors
来帮我们实现cors
。
'use strict'; /** @type Egg.EggPlugin */ exports.sequelize = { enable: true, package: 'egg-sequelize', }; exports.cors = { enable: true, package: 'egg-cors', };
在
config/config.default.js
中编写 sequelize 配置
/* eslint valid-jsdoc: "off" */ 'use strict'; /** * @param {Egg.EggAppInfo} appInfo app info */ module.exports = appInfo => { /** * built-in config * @type {Egg.EggAppConfig} **/ const config = exports = {}; // use for cookie sign key, should change to your own and keep security config.keys = appInfo.name + '_1655529530112_7627'; // add your middleware config here config.middleware = []; config.security = { csrf: { enable: false, ignoreJSON: true, }, }; config.cors = { origin: '*', allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH', }; // add your user config here const userConfig = { // myAppName: 'egg', }; // sequelize const sequelize = { dialect: 'mysql', host: '127.0.0.1', port: 3306, username: 'root', password: '123456', database: 'test_database', timezone: '+08:00', dialectOptions: { dateStrings: true, typeCast: true, }, define: { freezeTableName: true, // 模型名强制和表明一致 underscored: true, // 字段以下划线(_)来分割(默认是驼峰命名风格) }, }; return { ...config, ...userConfig, sequelize, }; };
1、时间格式化
类型需要采用:Sequelize.DATE
初始化Sequelize的时候传入dialectOptions参数,及timezone
timezone: '+08:00', // 改为标准时区 dialectOptions: { dateStrings: true, typeCast: true, },
下面就开始编写
controller
对这块需要安装lodash
,懂的都懂。
controller/ProjectConfig.js
'use strict'; const { success } = require('../utils/res'); const { omit, pick } = require('lodash'); const Controller = require('egg').Controller; class ProjectConfigController extends Controller { async index() { const { ctx } = this; const { pageSize, pageIndex } = ctx.query; const { Op, fn, col, where, literal } = this.app.Sequelize; // 固定的查询参数 const stableQuery = pick(ctx.query, [ 'type', 'createdAt', 'updatedAt' ]); const stableQueryArgs = Object.keys(stableQuery) .filter(key => Boolean(stableQuery[key])) .map(key => { return { [key]: stableQuery[key], }; }); const whereCondition = omit(ctx.query, [ 'pageIndex', 'pageSize', 'type', 'createdAt', 'updatedAt' ]); // 需要模糊查询的参数 const whereArgs = Object.keys(whereCondition) .filter(key => Boolean(whereCondition[key])) .map(key => { return where(fn('json_extract', col('value'), literal(`\'$.${key}\'`)), { [Op.like]: `%${whereCondition[key]}%`, }); }); const query = { where: { [Op.and]: [ ...stableQueryArgs, ...whereArgs, ], }, order: [ [ 'createdAt', 'DESC' ], ], limit: Number(pageSize), // 每页显示数量 offset: (pageIndex - 1) * pageSize, // 当前页数 }; const data = await ctx.model.ProjectConfig.findAndCountAll(query); ctx.body = success(data); } async create() { const { ctx } = this; const { type, value } = ctx.request.body; const data = await ctx.model.ProjectConfig.create({ type, value }); ctx.body = success(data); } async update() { const { ctx } = this; const { type, value } = ctx.request.body; const { id } = ctx.params; const data = await ctx.model.ProjectConfig.update({ type, value }, { where: { id } }); ctx.body = success(data); } async destroy() { const { ctx } = this; const { id } = ctx.params; console.log(id); const data = await ctx.model.ProjectConfig.destroy({ where: { id } }); ctx.body = success(data); } async batchDestroy() { const { ctx } = this; const { ids } = ctx.request.body; console.log(ids); const { Op } = this.app.Sequelize; const data = await ctx.model.ProjectConfig.destroy({ where: { id: { [Op.in]: ids, }, }, }); ctx.body = success(data); } } module.exports = ProjectConfigController;
模糊查询
SELECT json_extract(字段名,'$.json结构') FROM 表名;
sequelize高级查询
Post.findAll({ where: sequelize.where(sequelize.fn('char_length', sequelize.col('content')), 7) }); // SELECT ... FROM "posts" AS "post" WHERE char_length("content") = 7
中文文档,英文看的吃力,看中文的也无妨,不寒碜。^_^
model
model/project_config.js
'use strict'; module.exports = app => { const { STRING, INTEGER, TEXT, DATE } = app.Sequelize; const ProjectConfig = app.model.define('project_config', { id: { type: INTEGER, primaryKey: true, autoIncrement: true }, type: { type: STRING }, value: { type: TEXT, get() { return this.getDataValue('value') ? JSON.parse(this.getDataValue('value')) : null; }, set(value) { this.setDataValue('value', JSON.stringify(value)); }, }, createdAt: { type: DATE }, updatedAt: { type: DATE }, }); return ProjectConfig; };
router.js
'use strict'; /** * @param {Egg.Application} app - egg application */ module.exports = app => { const { router, controller } = app; router.get('/api/projectConfig', controller.projectConfig.index); router.post('/api/projectConfig', controller.projectConfig.create); router.put('/api/projectConfig/:id', controller.projectConfig.update); router.delete('/api/projectConfig/:id', controller.projectConfig.destroy); router.post('/api/projectConfig/batchDelete', controller.projectConfig.batchDestroy); };
API 文档 Apifox
先快速测试一把,然后去对前端代码。
ts用到的一些
在类型别名(type alias)的声明中可以使用
keyof
、typeof
、in
等关键字来进行一些强大的类型操作
interface A { x: number; y: string; } // 拿到 A 类型的 key 字面量枚举类型,相当于 type B = 'x' | 'y' type B = keyof A; const json = { foo: 1, bar: 'hi' }; // 根据 ts 的类型推论生成一个类型。此时 C 的类型为 { foo: number; bar: string; } type C = typeof json; // 根据已有类型生成相关新类型,此处将 A 类型的所有成员变成了可选项,相当于 type D = { x?: number; y?: string; }; type D = { [T in keyof A]?: A[T]; };
在比如用一个联合类型来约束对象的key
,用interface
我就没实现,貌似.
export type FormItemType = 'el-input' | 'z-select' | 'el-date-picker' // 目前发现 interface 的key 只能是三种 string number symbol keyof any type IPlaceholderMapping = { [key in FormItemType]: string } export const placeholderMapping: IPlaceholderMapping = { 'el-input': '请输入', 'z-select': '请选择', 'el-date-picker': '请选择日期' }
Das obige ist der detaillierte Inhalt vonSo verwenden Sie Vue3+ts zur Entwicklung von ProTable. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Vue3+TS+Vite-Entwicklungsfähigkeiten: So führen Sie eine SEO-Optimierung durch SEO (SearchEngineOptimization) bezieht sich auf die Optimierung der Struktur, des Inhalts und der Schlüsselwörter der Website, um sie in Suchmaschinen höher zu platzieren und dadurch den Traffic und die Präsenz der Website zu erhöhen. Bei der Entwicklung moderner Frontend-Technologien wie Vue3+TS+Vite ist die Optimierung von SEO ein sehr wichtiges Thema. In diesem Artikel werden einige hilfreiche Vue3+TS+Vite-Entwicklungstechniken und -methoden vorgestellt

tinymce ist ein voll funktionsfähiges Rich-Text-Editor-Plug-in, aber die Einführung von tinymce in Vue ist nicht so reibungslos wie bei anderen Vue-Rich-Text-Plug-ins. Tinymce selbst ist nicht für Vue geeignet, und @tinymce/tinymce-vue muss eingeführt werden. und Es handelt sich um ein ausländisches Rich-Text-Plug-in, das die chinesische Version nicht bestanden hat. Sie müssen das Übersetzungspaket von der offiziellen Website herunterladen (möglicherweise müssen Sie die Firewall umgehen). 1. Installieren Sie die zugehörigen Abhängigkeiten npminstalltinymce-Snpminstall@tinymce/tinymce-vue-S2. 3. Führen Sie den Skin und das chinesische Paket ein. Erstellen Sie einen neuen Tinymce-Ordner im öffentlichen Ordner des Projekts und laden Sie ihn herunter

vue3+vite:src verwendet „require“, um Bilder dynamisch zu importieren, und vue3+vite importiert dynamisch mehrere Bilder. Wenn Sie „requireisnotdefined“ verwenden, wird eine Fehlermeldung angezeigt like vue2 like imgUrl:require(' .../assets/test.png') wird importiert, da Typescript Require nicht unterstützt, daher wird Import verwendet. So lösen Sie das Problem: Verwenden Sieawaitimport

Um eine teilweise Aktualisierung der Seite zu erreichen, müssen wir nur das erneute Rendern der lokalen Komponente (dom) implementieren. In Vue lässt sich dieser Effekt am einfachsten mit der v-if-Direktive erzielen. In Vue2 können wir zusätzlich zur Verwendung der v-if-Anweisung zum erneuten Rendern des lokalen Doms auch eine neue leere Komponente erstellen. Wenn wir die lokale Seite aktualisieren müssen, springen wir zu dieser leeren Komponentenseite und springen dann wieder hinein der beforeRouteEnter-Schutz in der leeren Komponente. Wie in der Abbildung unten gezeigt, wie man in Vue3.X auf die Schaltfläche „Aktualisieren“ klickt, um das DOM im roten Feld neu zu laden und den entsprechenden Ladestatus anzuzeigen. Da der Guard in der Komponente in der scriptsetup-Syntax in Vue3.X nur o hat

Vue3+TS+Vite-Entwicklungsfähigkeiten: So führen Sie den Front-End-Sicherheitsschutz durch. Mit der kontinuierlichen Weiterentwicklung der Front-End-Technologie beginnen immer mehr Unternehmen und Einzelpersonen, Vue3+TS+Vite für die Front-End-Entwicklung zu verwenden. Allerdings haben auch die damit verbundenen Sicherheitsrisiken die Aufmerksamkeit der Menschen auf sich gezogen. In diesem Artikel besprechen wir einige häufige Front-End-Sicherheitsprobleme und geben einige Tipps zum Schutz der Front-End-Sicherheit während des Entwicklungsprozesses von Vue3+TS+Vite. Eingabevalidierung Benutzereingaben sind oft eine der Hauptquellen für Front-End-Sicherheitslücken. existieren

Vue3+TS+Vite-Entwicklungsfähigkeiten: So optimieren Sie domänenübergreifende Anfragen und Netzwerkanfragen Einführung: In der Front-End-Entwicklung sind Netzwerkanfragen ein sehr häufiger Vorgang. Wie wir Netzwerkanfragen optimieren können, um die Seitenladegeschwindigkeit und das Benutzererlebnis zu verbessern, ist eines der Themen, über die unsere Entwickler nachdenken müssen. Gleichzeitig müssen wir in einigen Szenarien, in denen Anforderungen an verschiedene Domänennamen gesendet werden müssen, domänenübergreifende Probleme lösen. In diesem Artikel wird vorgestellt, wie Sie in der Vue3+TS+Vite-Entwicklungsumgebung domänenübergreifende Anforderungen und Techniken zur Optimierung von Netzwerkanforderungen stellen. 1. Lösung für domänenübergreifende Anfragen

Um das Blog-Frontend mit Vue zu implementieren, müssen Sie die Markdown-Analyse implementieren. Wenn Code vorhanden ist, müssen Sie die Code-Hervorhebung implementieren. Es gibt viele Markdown-Parsing-Bibliotheken für Vue, wie z. B. markdown-it, vue-markdown-loader, markiert, vue-markdown usw. Diese Bibliotheken sind alle sehr ähnlich. Hier wird Markiert verwendet, und highlights.js wird als Code-Hervorhebungsbibliothek verwendet. Die spezifischen Implementierungsschritte lauten wie folgt: 1. Installieren Sie abhängige Bibliotheken. Öffnen Sie das Befehlsfenster unter dem Vue-Projekt und geben Sie den folgenden Befehl ein: npminstallmarked-save//marked, um Markdown in htmlnpmins zu konvertieren

Vue3+TS+Vite-Entwicklungstipps: So verschlüsseln und speichern Sie Daten Mit der rasanten Entwicklung der Internettechnologie werden Datensicherheit und Datenschutz immer wichtiger. In der Vue3+TS+Vite-Entwicklungsumgebung ist die Verschlüsselung und Speicherung von Daten ein Problem, mit dem sich jeder Entwickler auseinandersetzen muss. In diesem Artikel werden einige gängige Techniken zur Datenverschlüsselung und -speicherung vorgestellt, um Entwicklern dabei zu helfen, die Anwendungssicherheit und das Benutzererlebnis zu verbessern. 1. Datenverschlüsselung Front-End-Datenverschlüsselung Die Front-End-Verschlüsselung ist ein wichtiger Bestandteil des Schutzes der Datensicherheit. Häufig verwendet
