Cara menggunakan Vue3+ts untuk membangunkan ProTable
Pelaksanaan bahagian hadapan
Kesan pencapaian
Timbunan teknologi
vue3 + skrip taip + elemen-tambah
Cara menggunakan
<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>
Idea reka bentuk ProTable
Halaman dibahagikan kepada 5 kawasan,
Borang carian kawasan
Kawasan butang fungsi jadual
Kawasan operasi di sudut kanan atas meja
Jadual kawasan tema
Kawasan kelui meja
Isu untuk dipertimbangkan?
Kawasan mana yang patut menyokong slot masuk?
Adakah slot asal borang diserahkan kepada pengguna untuk penghantaran, atau adakah ia perlu dikapsulkan secara dalaman? Contohnya, apabila
colum
ialah status, ia perlu dipetakan kepadatag
, apabila ia adalah jenis数组
, ia dipetakan ke jadual, dan apabila iajson
, ia perlu diklik untuk melihat butiran? Ia akan menjadi terlalu menyusahkan untuk memproses setiap jadual Kami berharap untuk mengawalnya melalui medan.Adakah lajur dengan
column
perlu disalin?Medan lajur perlu diedit?
Apakah butiran dalam proses pelaksanaan?
Ketinggian meja, biarkan pengguna mengawal saiz kawasan yang boleh dilihat boleh jadual dan letakkan butang operasi kelompok di bahagian bawah (
fixed
kedudukan). Dengan cara ini pengguna boleh melihat kandungan jadual di kawasan terbesar.
Gaya pengekodan
Jika terdapat lebih daripada tiga atribut pada komponen, bungkusnya dalam baris baharu
Gunakan eslint ialah gaya
standard
.
petua 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; }
Jika kotak ditukar menjadi elemen 行内
, jika ia masih elemen sebaris, akan ada jurang, yang akan menyebabkan Ketinggiannya berbeza daripada ketinggian elemen induk. seperti berikut.
Penyelesaiannya juga sangat mudah Anda perlu menetapkan atribut vertical-align
elemen anaknya, atau tetapkan font-size: 0
Sebab asasnya ialah teks tengah elemen juga menduduki Lokasi. Atau jika anda tidak menggunakan inline-block
dan menggunakan atribut inline-flex
, tiada masalah sama sekali, kerana atribut ini juga digunakan secara meluas dalam pustaka komponen element-plus
, dan keserasian juga sangat bagus. Penyelesaian untuk
telah diketahui sejak sekian lama, tetapi hubungan antara vertical-algin
dan line-height
masih agak kabur, dan saya tidak pernah mendalaminya.
Letakkan dua artikel
Atribut penjajaran menegak CSS
Saya juga memikirkan baseline
perkara ini dalamflex
, selaraskan -item atribut: Atribut pada paksi silang adalah serupa.
Penjelasan terperinci tentang tutorial sintaks reka letak fleksibel
Operasi jadual
Selepas menambah data, apabila mendapatkan semula data,
pageIndex
hendaklah ditetapkan semula kepada 1 dan dipadam Begitu juga dengan data.Apabila mengedit data,
pageIndex
kekal tidak berubah dan kekal sebagai nombor halaman semasa.Ringkasnya, apabila bilangan item data berubah,
pageIndex
akan ditetapkan semula kepada1
. Apabila operasi pengguna tidak menjejaskan jumlah data,pageSize
kekal tidak berubah.
Ringkasan
menggunakan pustaka yang boleh memantau perubahan dalam saiz elemen dom, ubah saiz-pemerhati-polyfill.
Dalam 3.x, jika elemen mentakrifkan kedua-dua
v-bind="object"
dan atribut bebas yang serupa. Pembangun boleh memilih yang mana satu untuk disimpan.
Alamat dokumen # tingkah laku gabungan v-bind
Artikel rujukan
JavaScript API——ResizeObserver penggunaan
Fungsi kemudian pemprosesan perhubungan antara medan
lanjutan belum difikirkan lagi.
Kembangkan
slot
dan seterusnya. .
Lelaran....
Pelaksanaan latar belakang
Pangkalan data mysql
I The yang digunakan di sini dipasang oleh xampp
, mari semak versi. Apakah versi ini? Ia palsu, adakah ia benar-benar 10? Jangan risau tentangnya buat masa ini, selagi ia berkesan.
Buat jadual
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;
Projek baharu
npm init egg --type=simple
Direktori projek secara kasarnya seperti berikut,
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': '请选择日期' }
Atas ialah kandungan terperinci Cara menggunakan Vue3+ts untuk membangunkan ProTable. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Kemahiran pembangunan Vue3+TS+Vite: Cara melakukan pengoptimuman SEO SEO (SearchEngineOptimization) merujuk kepada mengoptimumkan struktur, kandungan dan kata kunci tapak web untuk meletakkannya lebih tinggi dalam enjin carian, dengan itu meningkatkan trafik dan pendedahan tapak web . Dalam pembangunan teknologi hadapan moden seperti Vue3+TS+Vite, cara mengoptimumkan SEO adalah isu yang sangat penting. Artikel ini akan memperkenalkan beberapa teknik dan kaedah pembangunan Vue3+TS+Vite untuk membantu

Penggunaan vue3+vite:src memerlukan pengimportan imej secara dinamik dan laporan ralat dan penyelesaian vue3+vite secara dinamik Jika vue3 dibangunkan menggunakan skrip taip, akan terdapat mesej ralat untuk keperluan untuk memperkenalkan imej tidak boleh digunakan :require(' .../assets/test.png') diimport kerana typescript tidak menyokong require, jadi import digunakan Berikut ialah cara menyelesaikannya: gunakan awaitimport

tinymce ialah pemalam editor teks kaya yang berfungsi sepenuhnya, tetapi memperkenalkan tinymce ke dalam vue tidak selancar seperti pemalam teks kaya Vue yang lain tidak sesuai untuk Vue dan @tinymce/tinymce-vue perlu diperkenalkan. dan Ia adalah pemalam teks kaya asing dan belum melepasi versi Cina Anda perlu memuat turun pakej terjemahan dari tapak web rasminya (anda mungkin perlu memintas tembok api). 1. Pasang kebergantungan yang berkaitan npminstalltinymce-Snpminstall@tinymce/tinymce-vue-S2 Muat turun pakej Cina 3. Perkenalkan pakej kulit dan Cina Buat folder tinymce baharu dalam folder awam projek dan muat turun

Vue melaksanakan bahagian hadapan blog dan perlu melaksanakan penghuraian markdown Jika terdapat kod, ia perlu melaksanakan penyerlahan kod. Terdapat banyak pustaka parsing markdown untuk Vue, seperti markdown-it, vue-markdown-loader, marked, vue-markdown, dsb. Perpustakaan ini semuanya sangat serupa. Ditanda digunakan di sini, dan highlight.js digunakan sebagai pustaka penonjolan kod. Langkah-langkah pelaksanaan khusus adalah seperti berikut: 1. Pasang perpustakaan bergantung Buka tetingkap arahan di bawah projek vue dan masukkan arahan berikut npminstallmarked-save//marked untuk menukar markdown ke htmlnpmins.

Untuk mencapai muat semula separa halaman, kami hanya perlu melaksanakan pemaparan semula komponen setempat (dom). Dalam Vue, cara paling mudah untuk mencapai kesan ini ialah menggunakan arahan v-if. Dalam Vue2, selain menggunakan arahan v-if untuk memaparkan semula dom setempat, kami juga boleh mencipta komponen kosong baharu Apabila kami perlu memuat semula halaman setempat, lompat ke halaman komponen kosong ini dan kemudian masuk semula pengawal beforeRouteEnter dalam komponen kosong. Seperti yang ditunjukkan dalam rajah di bawah, cara mengklik butang muat semula dalam Vue3.X untuk memuatkan semula DOM dalam kotak merah dan memaparkan status pemuatan yang sepadan. Memandangkan pengawal dalam komponen dalam sintaks persediaan skrip dalam Vue3.X hanya mempunyai o

Kemahiran pembangunan Vue3+TS+Vite: Cara mengoptimumkan permintaan merentas domain dan permintaan rangkaian Pengenalan: Dalam pembangunan bahagian hadapan, permintaan rangkaian adalah operasi yang sangat biasa. Cara mengoptimumkan permintaan rangkaian untuk meningkatkan kelajuan pemuatan halaman dan pengalaman pengguna ialah salah satu isu yang perlu difikirkan oleh pembangun kami. Pada masa yang sama, untuk beberapa senario yang memerlukan penghantaran permintaan kepada nama domain yang berbeza, kami perlu menyelesaikan isu merentas domain. Artikel ini akan memperkenalkan cara membuat permintaan merentas domain dan teknik pengoptimuman permintaan rangkaian dalam persekitaran pembangunan Vue3+TS+Vite. 1. Penyelesaian permintaan merentas domain

Kemahiran pembangunan Vue3+TS+Vite: Cara melaksanakan perlindungan keselamatan bahagian hadapan Dengan pembangunan berterusan teknologi bahagian hadapan, semakin banyak syarikat dan individu mula menggunakan Vue3+TS+Vite untuk pembangunan bahagian hadapan. Walau bagaimanapun, risiko keselamatan yang datang dengannya juga telah menarik perhatian orang ramai. Dalam artikel ini, kami akan membincangkan beberapa isu keselamatan bahagian hadapan biasa dan berkongsi beberapa petua tentang cara melindungi keselamatan bahagian hadapan semasa proses pembangunan Vue3+TS+Vite. Pengesahan input Input pengguna selalunya merupakan salah satu sumber utama kelemahan keselamatan bahagian hadapan. wujud

Petua pembangunan Vue3+TS+Vite: Cara menyulitkan dan menyimpan data Dengan perkembangan pesat teknologi Internet, keselamatan data dan perlindungan privasi menjadi semakin penting. Dalam persekitaran pembangunan Vue3+TS+Vite, cara menyulitkan dan menyimpan data adalah masalah yang perlu dihadapi oleh setiap pembangun. Artikel ini akan memperkenalkan beberapa teknik penyulitan dan storan data biasa untuk membantu pembangun meningkatkan keselamatan aplikasi dan pengalaman pengguna. 1. Penyulitan Data Penyulitan Data Bahagian Hadapan Penyulitan Bahagian Hadapan ialah bahagian penting dalam melindungi keselamatan data. Biasa digunakan
