npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zhouyuejin1995/vue-dynamic-table

v0.1.7

Published

Schema-driven dynamic table for Vue 3 + Element Plus: search form, columns, toolbar, pagination, row selection, fullscreen — all configurable via JSON.

Readme

@zhouyuejin1995/vue-dynamic-table

Schema-driven dynamic table for Vue 3 + Element Plus: search form, columns, toolbar, pagination, row selection, fullscreen — all configurable via JSON.

npm license

🚧 0.1.x 早期版本:API 仍在小幅调整,升级前请看 CHANGELOG


✨ 特性

  • 🧾 声明式 schema:搜索表单 / 列 / 操作列 / 工具栏,全部用 TS 对象描述,告别重复模板
  • 🔍 搜索:支持 input / select / date;select 支持静态选项、函数式联动、远程查询缓存
  • 🏷️ 列渲染:内置 tag / image / dictMap / formatter / 自定义 render / customRender / 插槽 6 种渲染模式
  • 🛠️ 工具栏:支持 schema(推荐)或 JSX 渲染函数或具名插槽;按钮按选中行 / 权限过滤
  • 🔐 权限注入perms 字段由 app.use(DynamicTable, { hasPermission }) 注入判断,未注入则向后兼容
  • 📑 分页 / 多选 / 序号 / 全屏 / 空数据,开箱即用
  • 🎨 嵌入模式plain 属性去掉装饰背景,适配弹窗、StepSection 等容器

📦 安装

npm install @zhouyuejin1995/vue-dynamic-table element-plus @element-plus/icons-vue
# 或
pnpm add @zhouyuejin1995/vue-dynamic-table element-plus @element-plus/icons-vue

这两个是 peer dep,请确保宿主项目已安装(element-plus ≥ 2.7、@element-plus/icons-vue ≥ 2.3、Vue 3.5+)。


🚀 快速开始

全局注册(推荐)

// main.ts
import { createApp } from 'vue';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
import DynamicTable from '@zhouyuejin1995/vue-dynamic-table';
import '@zhouyuejin1995/vue-dynamic-table/style.css';
import App from './App.vue';

createApp(App)
  .use(ElementPlus)
  .use(DynamicTable, {
    hasPermission: (code) => myUserStore.perms.has(code)
  })
  .mount('#app');

局部注册

<script setup lang="ts">
import { DynamicTable } from '@zhouyuejin1995/vue-dynamic-table';
import '@zhouyuejin1995/vue-dynamic-table/style.css';
import type { DynamicTableColumn, SearchField } from '@zhouyuejin1995/vue-dynamic-table';

const searchFields: SearchField[] = [
  { prop: 'keyword', label: '关键字', type: 'input', placeholder: '姓名/账号' },
  { prop: 'status', label: '状态', type: 'select', clearable: true,
    options: [{ label: '正常', value: 1 }, { label: '禁用', value: 0 }] }
];

const columns: DynamicTableColumn[] = [
  { prop: 'userName', label: '用户名', width: 120 },
  { prop: 'phone', label: '账号', width: 140 },
  { prop: 'role', label: '角色', tag: true,
    tagMap: { admin: { type: 'danger', text: '管理员' }, user: { type: 'info', text: '用户' } } },
  { prop: 'avatar', label: '头像', image: true },
  { label: '操作', width: 200,
    actions: () => [
      { label: '编辑', type: 'primary', link: true, perms: 'btn_user_edit',
        onClick: ({ row }) => console.log('edit', row) },
      { label: '删除', type: 'danger', link: true, perms: 'btn_user_delete',
        confirm: '确认删除?',
        onClick: ({ row }) => console.log('delete', row) }
    ]
  }
];

const fetchData = (params: Record<string, any>) => myApi.listUsers(params);
</script>

<template>
  <DynamicTable
    :columns="columns"
    :search-fields="searchFields"
    :data-request="fetchData"
    show-selection
    show-index
  />
</template>

纯前端静态数据

const data = [
  { id: 1, name: '张三', status: 1 },
  { id: 2, name: '李四', status: 0 }
];
// 不传 dataRequest,传 data 即可(开启分页会自动前端分页)
<DynamicTable :columns="columns" :data="data" />

📚 Props

完整 API 见 src/types.ts,下面列出常用项:

主体

| Prop | 类型 | 默认 | 说明 | |---|---|---|---| | columns | DynamicTableColumn[] | 必填 | 列配置 | | data | any[] | [] | 静态数据;不传 dataRequest 时使用 | | dataRequest | (params) => Promise<{ data, total } \| any[]> | - | 数据请求函数;返回 { data, total } 或纯数组 | | searchFields | SearchField[] | - | 搜索表单字段 | | toolbar | ToolbarAction[] | - | 工具栏按钮 schema(优先于 toolbarRender / slot) | | toolbarRender | () => VNode \| VNode[] | - | 工具栏 JSX 渲染函数(回退) |

显隐

| Prop | 类型 | 默认 | 说明 | |---|---|---|---| | showSearch | boolean | true | 显示搜索区 | | showToolbar | boolean | true | 显示工具栏 | | showRefresh | boolean | true | 显示刷新按钮 | | showFullscreen | boolean | true | 显示全屏按钮 | | showIndex | boolean | false | 显示序号列 | | showSelection | boolean | false | 显示多选列 | | showPagination | boolean | true | 显示分页 | | plain | boolean | false | 嵌入模式:去背景/内边距 | | emptyText | string | '暂无数据' | 空数据文案 |

数据 / 分页

| Prop | 类型 | 默认 | 说明 | |---|---|---|---| | immediate | boolean | true | 挂载后立即加载 | | refreshOnActivated | boolean | 跟随 immediate | keepAlive 重新激活时自动刷新 | | extraParams | object | {} | 额外请求参数(与搜索条件合并) | | pageField | string | 'page' | 分页页码字段名 | | pageSizeField | string | 'rows' | 分页大小字段名 | | paginationAlign | 'left' \| 'center' \| 'right' | 'right' | 分页对齐 |

其他(透传给 el-table)

通过 v-bind="$attrs" 透传:borderheightstripesize 等。


📡 Events

| Event | 参数 | 说明 | |---|---|---| | selection-change | (selection: any[]) | 多选变化 | | search | (form: Record<string, any>) | 点击「查询」后 | | reset | () | 点击「重置」后 | | reload | () | 内部触发,可监听 |


🎯 Exposed Methods(通过 ref 调用)

const tableRef = ref();
tableRef.value?.reload();         // 重载数据(保持当前页)
tableRef.value?.search();         // 触发搜索(回到第 1 页)
tableRef.value?.reset();          // 重置搜索表单
tableRef.value?.getSelectionRows(); // 当前选中行
tableRef.value?.clearSelection();   // 清空选中

🔐 权限注入

组件库本身不耦合任何权限方案。调用方在 app.use() 时注入:

app.use(DynamicTable, {
  hasPermission: (code: string) => myUserStore.perms.has(code)
});

之后 actions[].permstoolbar[].perms 字段会自动过滤:

{ label: '删除', perms: 'btn_user_delete', onClick: ... }  // 无权限 → 不渲染

未注入时:perms 字段失效(按钮始终显示),向后兼容老代码。


🧪 本地开发

# 装依赖
npm install

# 启动 playground(http://localhost:5173)
npm run dev

# 类型检查
npm run typecheck

# 单测
npm test

# 库构建(产出 dist/)
npm run build

# 跑完整 prepublish 链路
npm run prepublishOnly

📤 发布

参见 PUBLISH.md。日常用:

npm run release:patch   # 0.1.0 → 0.1.1
npm run release:minor   # 0.1.0 → 0.2.0
npm run release:dry     # 只跑测试+构建,不改版本不 push

脚本会自动 commit + 打 tag + 触发 GitHub Actions 发布到 npm。


🤝 贡献

  • Bug / 需求:开 issue
  • PR:开 PR
  • CI:main 分支触发测试矩阵(Node 18/20/22),tag 触发 npm 发布

📄 License

MIT © yuejin