使用 SAP UI5 Web Components 与 Vue 3 构建Fiori风格的 Web 应用 - 详解

引言

SAP UI5 Web Components 是一套基于原生 Web Components 标准构建的企业级 UI 组件库,它不依赖于特定框架,可以直接在 Vue、React、Angular 甚至原生 HTML 中使用。

结合 Vue 3 的响应式系统和组合式 API(Composition API),我们可以快速构建出语义清晰、风格统一的企业级应用。本文将带你使用 纯 JavaScript 从零开始,用 SAP UI5 Web Components 和 Vue 3 搭建一个简单的“员工查询”应用。

一、技术栈

  • Vue 3(Composition API)
  • SAP UI5 Web Components
  • Vite(构建工具)
  • JavaScript

二、初始化项目

  1. 使用 Vite 创建 Vue 项目(选择 JavaScript + Vue 模板):
npm create vite@latest es-ui5-app -- --template vue
cd es-ui5-app
npm install
  1. 安装 SAP UI5 Web Components:
npm install @ui5/webcomponents @ui5/webcomponents-fiori @ui5/webcomponents-icons

三、 构建员工查询页面

创建 src/components/EmployeeSearch.vue

员工信息管理系统
姓名
部门
全部部门
技术部
销售部
人事部
财务部
入职时间
查询
重置
工号
姓名
部门
职位
入职时间
操作
{{ emp.id }}
{{ emp.name }}
{{ emp.department }}
{{ emp.position }}
{{ emp.joinDate }}
import { ref, computed, watch } from "vue";
import "@ui5/webcomponents-icons/dist/AllIcons.js";
import "@ui5/webcomponents/dist/Button.js";
import "@ui5/webcomponents/dist/Input.js";
import "@ui5/webcomponents/dist/Label.js";
import "@ui5/webcomponents/dist/Select.js";
import "@ui5/webcomponents/dist/Option.js";
import "@ui5/webcomponents/dist/DatePicker.js";
import "@ui5/webcomponents/dist/Table.js";
import "@ui5/webcomponents/dist/TableRow.js";
import "@ui5/webcomponents/dist/TableCell.js";
import "@ui5/webcomponents/dist/TableHeaderRow.js";
import "@ui5/webcomponents/dist/TableHeaderCell.js";
import "@ui5/webcomponents/dist/TableGrowing.js";
import "@ui5/webcomponents-fiori/dist/ShellBar.js";
import "@ui5/webcomponents-fiori/dist/ShellBarBranding.js";
export default {
setup() {
const logo =
"https://images.sj33.cn/uploads/allimg/201401/7-140131225442O6.png";
// 模拟员工数据
const employees = ref([
{
id: "E001",
name: "张伟",
department: "技术部",
position: "前端工程师",
joinDate: "2022-03-15",
},
{
id: "E002",
name: "李娜",
department: "销售部",
position: "客户经理",
joinDate: "2021-07-22",
},
{
id: "E003",
name: "王强",
department: "技术部",
position: "后端工程师",
joinDate: "2023-01-10",
},
{
id: "E004",
name: "陈芳",
department: "人事部",
position: "HR专员",
joinDate: "2020-11-05",
},
{
id: "E005",
name: "刘洋",
department: "财务部",
position: "会计",
joinDate: "2022-08-18",
},
{
id: "E006",
name: "赵敏",
department: "技术部",
position: "UI设计师",
joinDate: "2023-05-12",
},
{
id: "E007",
name: "孙磊",
department: "销售部",
position: "销售代表",
joinDate: "2021-09-30",
},
{
id: "E008",
name: "周婷",
department: "财务部",
position: "出纳",
joinDate: "2022-12-03",
},
]);
// 筛选条件
const filters = ref({
name: "",
department: "",
joinDate: "",
});
// 表格增长(代替分页)
const growingStep = 5;
const visibleCount = ref(growingStep);
// 计算筛选后的数据
const filteredData = computed(() => {
return employees.value.filter((emp) => {
const matchName =
!filters.value.name || emp.name.includes(filters.value.name);
const matchDept =
!filters.value.department ||
emp.department === filters.value.department;
const matchDate =
!filters.value.joinDate || emp.joinDate === filters.value.joinDate;
return matchName && matchDept && matchDate;
});
});
const onChangeDate = (e) => {
filters.value.joinDate = e.target.value;
};
// 可见数据(用于表格growing展示)
const visibleData = computed(() => {
return filteredData.value.slice(0, visibleCount.value);
});
// 是否还有更多数据
const hasMore = computed(
() => visibleCount.value  {
const next = Math.min(
visibleCount.value + growingStep,
filteredData.value.length
);
visibleCount.value = next;
};
// 查询
const search = () => {
visibleCount.value = growingStep; // 重置可见数量
};
// 重置
const reset = () => {
filters.value = {
name: "",
department: "",
joinDate: "",
};
visibleCount.value = growingStep;
};
// 监听筛选条件变化,自动重置可见数量
// 监听筛选条件变化,自动重置到第一页
watch(
filters,
() => {
visibleCount.value = growingStep;
},
{ deep: true }
);
return {
logo,
filters,
filteredData,
visibleData,
hasMore,
search,
reset,
onLoadMore,
onChangeDate,
};
},
};
.page-container {
font-family: "Segoe UI", system-ui, sans-serif;
max-width: 1200px;
margin: 0 auto;
background: #f9f9f9;
}
/* 表单样式 */
.search-form {
display: grid;
grid-template-columns: auto 1fr auto 1fr auto 1fr auto auto;
gap: 12px;
padding: 16px;
background: white;
border-bottom: 1px solid #e5e5e5;
align-items: center;
}
.search-form ui5-label {
text-align: right;
font-weight: 500;
}
/* 表格容器 */
.table-container {
padding: 16px;
background: white;
margin: 0 16px;
border-radius: 8px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}
/* 分页 */
.pagination {
display: flex;
justify-content: flex-end;
padding: 16px;
}

四、在 App.vue 中引入

<template>
  <EmployeeSearch />
    <
    /template>
    <script>
      import EmployeeSearch from "./components/EmployeeSearch.vue";
      export default {
      components: {
      EmployeeSearch,
      },
      };
      <
      /script>

五、检查vite.config.js

import { defineConfig
} from "vite";
import vue from "@vitejs/plugin-vue";
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
// treat all tags with a ui5- as custom elements
isCustomElement: (tag) => tag.includes("ui5-"),
},
},
}),
],
});

六、运行项目

npm run dev

打开 http://localhost:5173,你将看到:

在这里插入图片描述

posted @ 2025-08-22 16:50  yfceshi  阅读(14)  评论(0)    收藏  举报