实操案例|TinyVue树表+动态行合并

TinyVue:一款轻量级且功能强大的Vue UI组件库 TinyVue是一款基于Vue的UI组件库,它同时支持Vue 2.0和Vue 3.0,为开发者提供了丰富的组件选择,旨在提升开发效率和项目质量。TinyVue由OpenTiny团队打造,秉承了Vue的核心设计理念,如组件化、虚拟DOM和响应式数据绑定等,但在代码量上进行了大幅优化,以实现更小的体积和更高的性能。TinyVue作为一款轻量级且功能强大的Vue UI组件库,以其跨版本支持、跨端支持、组件丰富、国际化与主题定制等特性赢得了众多开发者的青睐。 阅读详情

本文由孟智强同学原创。

背景

团队某个小项目切换 UI 框架,要将 Element 换成 TinyVue。期间遇到一个树表形式的业务表格,支持多级下钻,且第一列有合并行。当初用 Element 实现这个表格时费了一些周折,料想 TinyVue 上场应该也不轻松,谁曾想一上手才知道——这比 Element 实现容易多了!

先上最终效果图(表格内容已脱敏处理):

图片

显示树表

TinyVue 的表格组件支持树表(详情),我们只需将业务数据按约定格式处理好,再简单进行配置即可。用到的表格数据如下:

const rawData = [
  { area: '华北', province: '北京', city: '北京', store: '密云店', sales: 72 },
  { area: '华东', province: '山东', city: '淄博', store: '蓝翔NO.1', sales: 57 },
  { area: '华中', province: '湖北', city: '武汉', store: '北区', sales: 21 },
  { area: '华北', province: '北京', city: '北京', store: '朝阳总店', sales: 123 },
  { area: '华东', province: '山东', city: '青岛', store: '蜊叉泊分店', sales: 12 },
  { area: '华中', province: '湖北', city: '武汉', store: '南区', sales: 42 },
  { area: '华北', province: '北京', city: '北京', store: '香山店', sales: 72 },
  { area: '华南', province: '广东', city: '广州', store: '花城店', sales: 90 },
  { area: '华南', province: '广西', city: '桂林', store: '甲天下', sales: 15 },
  { area: '华中', province: '湖北', city: '武汉', store: '城中区', sales: 54 },
  { area: '华南', province: '广东', city: '东莞', store: '万象汇', sales: 35 },
  { area: '华东', province: '山东', city: '青岛', store: '金沙滩分店', sales: 39 },
  { area: '华南', province: '广东', city: '深圳', store: '天虹', sales: 85 },
  { area: '华东', province: '浙江', city: '绍兴', store: '鲁镇店', sales: 87 },
  { area: '华南', province: '广东', city: '东莞', store: '大润发', sales: 26 },
  { area: '华北', province: '内蒙古', city: '乌兰察布', store: '乌拉旗舰店', sales: 15 },
  { area: '华南', province: '广东', city: '广州', store: '越秀店', sales: 60 }
];

我们先把它处理成树表约定的格式:

const mergeKeys = ['area', 'province', 'city'];  // 需要合并的字段名

// 根据合并字段进行排序,方便后续处理
rawData.sort((a: any, b: any) => {
  for (let key of mergeKeys) {
    if (a[key] !== b[key]) {
      return a[key].localeCompare(b[key]);
    }
  }
  return 0;
});

// 生成树表所需格式的数据
const tableData = rawData.reduce((arr, item) => {
  const provinceNode = initNodeData(arr, item, 'province');
  const cityNode = initNodeData(provinceNode.children, item, 'city');

  cityNode.children.push({ 
    place: item.store,
    store: 1,
    sales: item.sales
  });

  return arr;
}, [] as any[]);

function initNodeData(arr: any[], row: any, placeKey: string) {
  const placeValue = row[placeKey];
  let matched = arr.find(v => v.place === placeValue);

  if (!matched) {
    matched = {
      area: row.area,
      place: placeValue,
      store: 0,
      sales: 0,
      children: []  // 子级
    };
    arr.push(matched);
  }

  // 统计当前行的 store 数量和 sales 
  matched.store += 1;
  matched.sales += row.sales;

  return matched;
}

处理好的 tableData 格式如下:

[
  {
    "area": "华北",
    "place": "北京",
    "store": 3,
    "sales": 267,
    "children": [
      {
        "area": "华北",
        "place": "北京",
        "store": 3,
        "sales": 267,
        "children": [
          {
            "place": "密云店",
            "store": 1,
            "sales": 72,
            "_RID": "row_3"
          },
          ...
        ]
      }
    ]
  },
  ...
]

模板的配置非常方便,只需为需要展开的列配置 tree-node 即可。

Element 中的树表默认只能通过第一列的单元格来控制展开和折叠,如果想要在其他列中实现同样的功能,就需要使用一点黑魔法 hack。这一点要为 TinyVue 的方便好用点赞!

<template>
  <tiny-grid :data="tableData" :tree-config="{ children: 'children' }" border>
    <tiny-grid-column title="大区" field="area" width="120" />
    <tiny-grid-column title="地区" field="place" tree-node /> <!-- 这列控制树表展开/折叠 -->
    <tiny-grid-column title="店铺" field="store" />
    <tiny-grid-column title="销售额" field="sales" />
  </tiny-grid>
</template>

效果如下图:

图片

跨行合并首列单元格

TinyVue 表格组件提供了 row-span 和 span-method 两种单元格合并的方法,但前者不支持嵌套树表,所以这里选择后者。span-method 这个方法是不是很眼熟?对了,Element Table 中也有这个方法,两者在使用上几乎一模一样。

<template>
  <tiny-grid span-method="spanMethod" ... >...</tiny-grid>
</template>
function spanMethod({ columnIndex, row }: { columnIndex: number, row: any}) {
  if (columnIndex === 0) {  // 首列跨行合并
    return {
      rowspan: 1,  // 如何求跨行合并数值?
      colspan: 1
    }
  }
}

接下来的问题就是如何求出 spanMethod 方法返回值中的 rowspan 的值。

我们先来看表格,在初始状态下,表格首列需要跨行合并的单元格如下图红框处所示:

图片

不难看出每个“大区”(area)的跨行合并数就是其相邻且内容相同单元格的个数,例如“大区”一列中相邻的“华北”单元格有2个,则它的跨行合并数就是2。我们可以通过定义一个 rowspanMapping 变量来保存这些“大区”分别对应的跨行合并数:

// 跨行合并数,Map key 为 area 的值,Map value 为跨行合并数
const rowspanMapping: Map<string, number> = new Map();

// 统计不同大区的默认跨行合并数
tableData.forEach((item) => {
  const spanValue = rowspanMapping.get(item.area) ?? 0;
  rowspanMapping.set(item.area, spanValue + 1);
});

然后我们就得到了表格初始形态首列的跨行合并数信息:

Map(4) {'华北' => 2, '华东' => 2, '华南' => 2, '华中' => 1}

再应用到 spanMethod 方法中:

function spanMethod({ columnIndex, row }: { columnIndex: number, row: any}) {
  if (columnIndex === 0) {  // 首列跨行合并
    return {
      rowspan: rowspanMapping.get(row.area),  // 获取当前单元格跨行合并数
      colspan: 1
    }
  }
}

然而,实际的渲染效果与我们预期的完全不同,表格布局出现了严重的错位。如下图所示:

图片

经过分析,我们发现在进行单元格合并时,合并组中的起始单元格会占据对应的行数,而其余单元格则需要被移除,以保证表格的结构不会出现错位。在 TinyVue 表格组件的 spanMthod 方法中,我们通过将 rowspan 设为 0 来实现这一点。例如,“华北”的 rowspan 为 2,则第一个“华北”单元格的 rowspan 值就为2,而第二个“华北”单元格则应该设为0,即移除不渲染。

为此,我们需要改进我们统计大区默认跨行合并数的方法。我们可以通过定义一个私有属性来记录当前“大区”是否首次出现:

tableData.forEach((item) => {
  const spanValue = rowspanMapping.get(item.area) ?? 0;
  // 当前 area 值首次出现(用于设定 rowspan 的作用行)
  item._isAppearFirst = !rowspanMapping.has(item.area);
  rowspanMapping.set(item.area, spanValue + 1);
});

合并方法也要随之调整:

function spanMethod({ columnIndex, row }: { columnIndex: number, row: any}) {
  if (columnIndex === 0) {  // 首列跨行合并
    return {
      // 当前大区若首次出现,则应用跨行合并数,否则设为0(不渲染)
      rowspan: row._isAppearFirst ? rowspanMapping.get(row.area) : 0,
      colspan: 1
    }
  }
}

完成后效果如下图所示:

图片

合并行动态适配树表展开与折叠

目前为止,我们已经实现了树表和表格初始化状态首列的行合并,接下来要将两者结合起来完成最终效果。

当展开树表中的任意一行时,当前行下方会显示新的表格行;相反,折叠任意一行时,下方对应的表格行也会隐藏。换句话说,随着树表的展开和折叠,表格的总行数会发生变化,因此需要动态调整对应首列的跨行合并数,以确保表格布局不发生错位。

举例说明:

“华东”的跨行合并数默认为2

图片

当展开“山东”时,会显示下级的“青岛”和“淄博”,此时“华东”的跨行合并数应该加上这2个新出现的表格行,变为4,才能确保表格布局恢复正常。

图片

同理,当继续展开“青岛”时,会显示2个下级行,此时“华东”的跨行合并数应该再加上这2个新出现的表格行,变为6

图片

原理搞清了,下面分享代码实现。

既然需要根据树表的展开和折叠来计算跨行合并数,那么首先就要监听树表切换事件 toggle-tree-change:

<template>
  <tiny-grid @toggle-tree-change="handleExpand" ... >
    ...
  </tiny-grid>
</template>

function handleExpand({ row }: { row: any }) {
  // ?
}

在表格组件底层,当树表展开或折叠后,会重新获取单元格合并数信息以进行布局。换句话说,我们需要在 handleExpand 方法中计算出树表行操作后的合并数,以便 spanMethod 方法能够获取到最新的单元格合并数。

为了计算操作后的合并数,我们需要知道当前操作是“展开”还是“折叠”,以便进行针对性的处理:

  • 当前为折叠操作,需要减去待折叠的行数

  • 当前为展开操作,需要加上待展开的行数

我们为每行数据添加一个私有属性 _treeExpanded 来存储展开/折叠状态。

function initNodeData(arr: any[], row: any, placeKey: string) {
  ...
  if (!matched) {
    matched = {
      ...
      _treeExpanded: false  // 自定义属性:当前树表行是否展开
    };
  }
 ...
}

这样我们就可以在 handleExpand 方法中进行展开或折叠的合并行数处理了:

function handleExpand({ row }: { row: any }) {
  const curRowspan = rowspanMapping.get(row.area) ?? 0;  // 当前 area 的跨行合并数
  const changedRowspan = row.children.length;  // 当前行的子级数量
  let spanValue;
  
  if (row._treeExpanded) {  // 当前行已展开:当前为折叠操作,需要减去待折叠的行数
    spanValue = curRowspan - changedRowspan;
  } else {  // 当前行已折叠:当前为展开操作,需要加上待展开的行数
    spanValue = curRowspan + changedRowspan;
  }
  
  row._treeExpanded = !row._treeExpanded;  // 更新状态
  rowspanMapping.set(row.area, spanValue);
}

目前的效果已经非常接近了,但通过测试我们发现:当树表按层级顺序逐步展开或折叠时,一切正常,然而,若直接跨层级操作,就会出现布局错位。正如下图所示:

图片

这是因为跨层级操作时,我们的代码中只考虑了当前行子级的变动数量,而没有考虑子级的子级,以及更深层级的展开/折叠状态。因此,我们需要将当前行的所有子级都纳入考虑。下面是最终调整后的代码:

function handleExpand({ row }: { row: any }) {
  const curRowspan = rowspanMapping.get(row.area) ?? 0;
  let changedRowspan = row.children.length;

  // 当前行已展开:当前为折叠操作,需要减去待折叠的行数(含后代)
  // 当前行已折叠:当前为展开操作,需要加上待展开的行数(含后代)
  const deepExpandedCount = (arr: any[]) => {
    if (!Array.isArray(arr)) {
      return;
    }

    arr.forEach((item: any) => {
      if (item._treeExpanded) {
        // 递归累加已经展开的子级个数
        changedRowspan += item.children.length;
        deepExpandedCount(item.children);
      }
    });
  }

  deepExpandedCount(row.children);

  const spanValue = curRowspan + changedRowspan * (row._treeExpanded ? -1 : 1);
  
  row._treeExpanded = !row._treeExpanded;  // 更新状态
  rowspanMapping.set(row.area, spanValue);
}

要点总结

1、为需要控制树表展开/折叠的列配置 tree-node 属性;

2、span-method 方法返回当前单元格的合并数,其中 rowspan 为跨行合并数,当设为0时,当前单元格不渲染;

3、定义一个变量以存储表格的跨行合并数信息;

4、对于相邻且内容相同的同组单元格,仅设置该组首个单元格的 rowspan 为对应的跨行合并数,其余单元格均设为 0;

5、监听表格的 toggle-tree-change 事件,区分树表的展开、折叠操作,动态修改对应的跨行合并数信息。

关于OpenTiny

欢迎加入 OpenTiny 开源社区。添加微信小助手:opentiny-official 一起参与交流前端技术~

OpenTiny 官网:https://opentiny.design/

OpenTiny 代码仓库:https://github.com/opentiny/

TinyVue 源码:https://github.com/opentiny/tiny-vue

TinyEngine 源码: https://github.com/opentiny/tiny-engine

欢迎进入代码仓库 Star🌟TinyEngine、TinyVue、TinyNG、TinyCLI~

如果你也想要共建,可以进入代码仓库,找到 good first issue标签,一起参与开源贡献~ 

tinyvue一个非常精简的vuejs的实现 这里有非常详细的教程,教你怎么写一个自己的tiny-vue 8 小时实现自己的迷你版vuejs 立即下载

相关推荐

stm32控制舵机_使用URT-1控制飞特舵机上手教程(SM40BL舵机为例)

使用URT-1控制飞特舵机上手教程(SM40BL舵机为例):1,参阅URT-1使用说明.pdf2, 材料清单:① URT-1驱动板② 连接驱动板与电脑的MINI USB 连接线③ 给舵机供电的电源④ 舵机与舵机连接线⑤ 杜邦线(可选)3,将URT-1驱动板与电脑连接4,安装驱动,参阅文件CH340驱动,检查设备管理器串口号。5,舵机连接URT-1驱动板,驱动板接电源,参考下图:6,打开FD软件进行...

weixin_39564510的博客 3432

TinyVue - 华为云 OpenTiny 出品的企业级前端 UI 组件库,免费开源,同时支持 Vue2 / Vue3,自带 TinyPro 中后台管理系统

华为最新发布的前端 UI 组件库,支持 PC 和移动端,自带了 admin 后台系统,完成度很高,web 项目开发又多一个选择。

那些免费的砖 3618

Rockchip硬件编码实战:5分钟搞定RK3588上的H.265视频压缩(附FFmpeg集成指南)

本文深入解析了在Rockchip RK3588平台上利用硬件编码器实现高效H.265视频压缩的完整实战流程。文章详细介绍了MPP库的基础使用、FFmpeg集成方法,并重点分享了零拷贝、多实例编码等关键性能优化技巧,帮助开发者充分发挥RK3588的硬件编码能力,实现从YUV原始数据到高质量H.265码流的高效转换。

h6i7j8的博客 1098

华为开源项目OpenTiny的TinyVue组件库适用于哪些地方?

组件库目前是有80+的组件,1500+组件API接口,同时其中Table、Tree、Select等高频组件均内置虚拟滚动,在10万大数据场景下保持丝滑体验。所以其实相对于其他组件库的话,性能还是非常高的。第三个就是可以支持大屏系统,提供多种页面模式,轻松点击即可生成页面结构,同时不断添加新的图表组件,包含A-Charts等,只需要简单拖拽,少量设置即可完成页面搭建。第四个就是可以支持工业制造系统,可支持多种页面布局,通过可视化图表集成控制工作台各个场景业务,让使用者直观了解业务数据情况,进行智能分析。

ihhhh1的博客 1517

AI人工智能与模拟退火:碰撞出的智慧火花

本文旨在为读者全面介绍模拟退火算法在人工智能领域的应用。我们将涵盖从基础理论到实际实现的完整知识体系,帮助读者理解这一受自然界启发的优化技术如何解决复杂的计算问题。文章首先介绍模拟退火的基本概念,然后深入其工作原理和数学基础,接着通过Python实现展示具体应用,最后讨论实际应用场景和未来发展方向。模拟退火(Simulated Annealing, SA):一种受物理退火过程启发的概率性优化算法能量函数(Energy Function):评估系统状态的函数,对应优化问题的目标函数。

AGI×大数据,开启智能时代的认知跃迁;解码AGI,赋能数据驱动的智能革命。 453

S905L3B机顶盒刷Armbian:从安卓Root到eMMC全攻略

在嵌入式开发与轻量级服务器搭建中,ARM架构设备因其低功耗和高性价比备受关注。晶晨S905L3B作为运营商机顶盒的主流芯片,通过刷写Armbian系统可将其改造为ARM小服务器。其原理是利用Amlogic芯片的uboot引导机制,将Linux系统写入eMMC存储,从而脱离原厂安卓限制。这一方案的技术价值在于以极低成本实现Docker容器、下载机、轻量数据库等服务的部署,应用场景涵盖家庭网络广告过滤、智能家居控制、复古游戏机等。本文以CM311-1S为例,详细拆解从安卓9 Root到Armbian写入eMMC

weixin_31476015的博客 341

探索TinyVue:跨端跨框架的企业级UI组件库

上面板</div><div class="demo-split-pane">下面板</div></div><div class="demo-split-pane">右面板</div>

qq_52752298的博客 1424

Prompt提示优化工具

在大模型使用过程中,Prompt尤为重要。一个好的Prompt可以解决很多的问题。那么如何撰写一个完美的Prompt?下面汇总了一些Prompt工具,可以辅助日常Prompt的编写。

HJ_blog 3108

探索 TinyVue 组件库系列之组件系统3:组件配置驱动开发

配置系统采用分层注入模型,配置从全局设置逐级传递到单个组件实例。ConfigProvider 组件作为核心配置中心,利用 Vue 的 provide/inject 机制在整个组件树中分发配置。

kagol的博客 1021

微信终于支持“多设备同时在线”?我用 NAS + Docker 搭了一个云端微信系统,多端共享24小时在线

通过Docker 容器,将微信运行在云端并通过浏览器访问,实现多设备共享同一微信会话 📱。本文详细介绍完整部署流程、docker-compose 配置及资源控制方案,让微信变成“可访问的云桌面应用” ✨

XiaoqiangClub的博客 872

SAP 中租赁资产的实现需区分经营租赁与融资租赁,核心围绕资产主数据配置、折旧与利息设置、科目分配及业务操作展开

摘要:SAP系统租赁资产管理需区分经营租赁与融资租赁,通过SPRO配置资产主数据、折旧范围、利息计算及科目分配。关键步骤包括:激活折旧范围利息计算(OABZ)、设置租赁资产类别(OAYZ)、维护总账科目(AO90)及创建租赁资产主数据(AS01)。业务操作涵盖资产资本化(ABZON)、折旧利息过账(AFAB)、租金支付(F-53)及终止处理(ABUMN)。核心配置要点在于准确设置租赁类型、利率参数和科目联动,确保系统自动计算折旧与利息并生成正确凭证。

金牌架构师 1076

【深度解析】TinyVue表格组件表头溢出终极解决方案:从像素级适配到跨端兼容

在企业级应用开发中,表格(Table)作为数据展示的核心组件,其可用性直接影响用户体验。当面对复杂表头、多终端适配和动态数据场景时,**表头溢出**问题常常让开发者头疼不已——过长标题被截断、固定列与滚动列错位、嵌套表头排版混乱等问题层出不穷。 本文将系统解析TinyVue表格组件(Table Component)的表头溢出处理方案,通过**6大核心技术**和**12个实战案例**,带你掌握从基...

gitblog_01414的博客 586

华为OD机考2025C卷 - 精准核酸检测(Java & Python& JS & C++ & C语言)

华为OD机考2025C卷 - 精准核酸检测,提供在线OJ Java & Python& JS & C++ & C

算法大师! 2882

探索 TinyVue 组件库系列之低代码平台集成

低代码平台通常需要使用自定义组件扩展标准组件库。组合方法:组合现有组件创建新的复合组件。可以重用无渲染层以保持与标准组件的一致性。继承方法:扩展标准组件模板并覆盖特定部分,同时继承无渲染逻辑。插件方法:使用设计配置系统向标准组件注入自定义行为,而无需修改其代码。

kagol的博客 788

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

TinyVue主题系统架构解析:从设计Token到运行时换肤的完整链路

主题定制是前端组件库落地中的关键能力,直接关系到品牌换肤、暗黑模式与多租户视觉一致性等复杂场景。在实际工程中,单纯的样式变量替换难以应对动态切换与局部覆盖需求,需要从设计Token体系、编译映射到运行时注入进行统一治理。TinyVue主题系统通过基础Token与组件Token的双层结构,结合CSS Variables原生能力,实现了构建期静态产物与运行期动态切换的完整闭环。其设计思路在组件库架构与设计系统落地中具有普遍参考价值。无论是开发企业级中后台项目,还是自研组件库的主题方案,理解这套Token治理与运

weixin_34377919的博客 320

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

叮!OpenTiny社区运营阶段总结报告已送达

PC 端游80+组件,移动端游30+组件,包含高频组件 Table、Tree、Select 等,内置虚拟滚动,保证大数据场景下的流畅体验,除了业界常见组件之外,我们还提供了一些独有的特色组件,如:Split 面板分割器、IpAddress IP地址输入框、Calendar 日历、Crop 图片裁切等。OpenTiny从今年2月开源之后也已经陪伴了大家好几个月的时光,在这些时间里,OpenTiny也从各个方面不断的突破自己,不断的通过各种形式近距离的与开发者进行交流。与开发者一起共同成长~

OpenTiny的博客 349

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Vue组件库测试体系构建:Vitest + Vue Test Utils + Playwright实战

单元测试作为前端工程化质量保障的基石,核心原理在于通过模拟运行环境验证代码逻辑的确定性,确保组件的输入输出符合预期。然而在组件库场景中,测试还承担着契约稳定、边界条件覆盖、跨端一致性等更严苛的职责。基于此,Vitest以其与Vite生态无缝集成、极速启动与原生TS支持的特性,成为Vue单测的优选;搭配Vue Test Utils提供的mount/trigger等API,可精细控制组件交互;而Playwright则在真实浏览器层面兜底回归验证。本文完整呈现了从测试分层、工具选型、配置落盘到具体用例编写与排障的

weixin_34208185的博客 370

Vue 2与Vue 3兼容层:一套代码双版本组件库的工程实践

前端组件库开发中,多版本框架兼容一直是工程化领域的高频痛点。Vue 2 与 Vue 3 在响应式系统、渲染函数、生命周期和插槽机制上存在系统性差异,仅靠运行时判断无法在复杂组件库场景下保持代码可维护性与性能。通过引入兼容层设计,可以将版本差异隔离为独立模块,借助构建时插件、别名替换和运行时最小适配,实现“一份源码,双版本产物”的交付模式。这种架构不仅让组件库作者、企业级内部组件系统维护者能更平滑地应对 Vue 版本升级,也为多端适配、平台隔离提供了通用方法论。本文从组件库双版本兼容的现实挑战出发,拆解兼容层

weixin_34236869的博客 240

新手适合用什么Vue组件库?TinyVue组件库好用吗?

最近 TinyVue组件库的热度也是持续上升,怀揣着这个疑问,作为新手的我便尝试了一下使用这个组件库。Ant Design 的 Vue 实现,组件的风格与 Ant Design 保持同步,风格俏皮简约,更适合用过 ant design 的 react 框架组件库的童鞋。整体感受下来还是很流畅的,在官网给出的多个组件示例中,API 的设计看起来也都友好合理。常规支持:多语言、自定义主题、按需引入、内置过渡动画 ,文档详细,组件齐全。开箱即用的多语言组件库,支持单独配置和升级,Vue2 和 Vue3 都适配。

LLI025的博客 862

从自研走向开源的 TinyVue 组件库

本文介绍了TinyVue开源征程的三个阶段

OpenTiny的博客 729

优化永不止步:TinyVue v3.20.0 正式发布,更美观的官网UI,更友好的文档搜索,更强大的主题配置能力~

ThemeData是自定义主题数据格式,用户可以通过data属性,传入覆盖的全局CSS 变量, 通过css属性,传入有效的 CSS 规则块。/** 主题的ID */ id?: string /** 主题的名称 */ name?: string /** 主题的中文名称 */ cnName?* 需要追加的全局css变量的对象* 比如:{ 'tv-base-color-brand' : '#1476ff' } 会追加到 :root { --tv-base....... }* */ data?

OpenTiny的博客 1450

给大家讲讲TinyVue组件库项目介绍

TinyVue 是一套跨端、跨框架的企业级 UI 组件库,支持 Vue 2 和 Vue 3,支持 PC 端和移动端。📦 包含 80 多个简洁、易用、功能强大的组件🖖 一套代码同时支持 Vue 2 和 Vue 3🖥️ 一套代码同时支持 PC 端和移动端🌍 支持国际化🎨 支持主题定制📊 组件内部支持配置式开发,可支持低代码平台可视化组件配置💡 采用模板、样式、逻辑分离的跨端、跨框架架构,保障灵活性和可移植性。

happyleyouyou的专栏 1040

原来 TinyVue 组件库跨框架(Vue2、Vue3、React、Solid)是这样实现的?

前端组件库跨框架是指在不同的前端框架(如 React、Vue、Solid 等)之间共享和复用组件的能力。这种能力可以让开发者在不同的项目中使用同一套组件库,从而提高开发效率和代码复用性。

OpenTiny的博客 1134

直播回顾|6个实例带你解读TinyVue 组件库跨框架技术

作为致力于实现跨框架的TinyVue组件库,旨在实现跨不同版本的Vue框架兼容性,其独特之处在于采用单份源代码策略,通过智能编译技术,能够同时生成适用于Vue 2.6、2.7版本以及Vue3版本的组件包。在本期《手把手教你实现mini版TinyVue组件库》的主题直播中,华为云前端开发DTSE技术布道师阿健老师给开发者们展开了组件库跨框架的讨论,同时针对TinyVue组件库的关键技术进行了剖析,并通过项目实战演示了一份源码编译出2个不同Vue 框架的组件。随后,这些状态值被返回给适配层。

OpenTiny的博客 1109

使用 TinyVue 组件库搭建前端项目的实操体验

在这个示例中,我们创建了一个包含用户名和密码输入框的表单,并添加了表单验证功能。总的来说,TinyVue 组件库为前端开发提供了强大的支持和便利。通过这次活动,我不仅提升了自己的开发技能,还对 OpenTiny 的产品有了更深入的了解。在这个示例中,我们引入了 TinyButton 组件,并在按钮点击时触发一个成功消息。TinyVue 组件库提供了丰富的 UI 组件,可以满足各种业务需求。在项目中,我使用了 TinyVue 提供的多个组件来构建页面。首先,我按照官方文档的指引,完成了开发环境的准备工作。

Echo_Wish 1334

推荐一款适用于Vue项目的UI组件库——TinyVue

今天给大家推荐了TinyVue这款组件库,教了一下TinyVue怎么使用,总的来说,它的文档全面,组件丰富,容易上手,非常适合用来开发一些管理系统的中后台页面,如果你有幸看到这篇文章不妨去尝试尝试吧。

qq_34147402的博客 884
上一篇: 重磅更新!Fluent Editor 开源富文本支持 LaTeX 可编辑公式啦~
下一篇: 活动邀请|2024华为云首届开源开发者论坛即将正式开幕
OpenTiny社区
博客等级 码龄4年 1540粉丝 266原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值