后端与接口
在开发或调试 NetSuite UIF SPA 组件时…
构建、修改或调试 NetSuite UIF SPA(JSX)组件时,用于查询 UIF 类/组件/枚举的准确 API 并避免已知运行时错误。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
在开发或调试 NetSuite UIF 特定
解决思路
- 在本地 `references/` 目录中按类名搜索,例如搜索 `class Date`。
- 按方法名搜索,例如在 `references/core.d.ts` 中搜索 `lastOfMonth`、`firstOfMonth` 或 `addDay`。
- 按枚举搜索,例如在 `references/component.d.ts` 中搜索 `enum GapSize`、`enum Hierarchy` 或 `enum Type`。
- 找到行号后打开该文件对应区段查看完整定义。
- 使用 UIF Date 时注意:`Date.now()` 返回 UIF Date 对象而非数字;使用 `.year`/`.month`/`.day` 属性(非 `getFullYear()` 等);`.month` 从 0 开始;只有 `import { Date } from '@uif-js/core'` 才是 UIF Date,`new Date()` 仍是原生 Date。
- StackPanel 中禁止 null 子元素和空数组:用命令式数组构建 `var items = []; if (x) items.push(<Item>...</Item>);`,或用 for 循环 push;`StackPanel.Item` 必须恰好一个子元素。
- Modal 必须放在根组件层级:把 modal 的 `<StackPanel.Item>` push 进根级 items 数组(用 for 循环追加),避免嵌套容器导致层叠上下文问题。
- Badge 的 `classList` 只能传单个类名(内部用 `DOMTokenList.add()`,空格分隔会抛 `InvalidCharacterError`);紧凑徽章用 `size={Badge.Size.SMALL}`。
- DataGrid 全宽:为每列保留显式 `width`(作为 `columnStretch` 的比例权重),在 DataGrid 上加 `rootStyle={{ width: '100%' }}`,宽列给更大 width 值;不要用 `stretchStrategy={{}}`(构造器专用,重渲染会报错)。
- TEMPLATED 列的 `content` 回调中 `args` 含 `{cell, context}`,用 `args.cell.value` 或 `args.cell.row.dataItem`;回调必须包 try/catch,未捕获异常会让后续列空白。
- DataGrid 行高用 `dataRowHeight`(`rowHeight` 被静默忽略)。
- `CHECK_BOX` 列需要网格级 `editable={true}`;`CHECK_BOX` + `CELL_UPDATE` 不可靠,推荐用 TEMPLATED 列 + 切换 Button(如 `label={checked ? '☑' : '☐'}`),用 `useRef({})` 按行 ID 管理状态并用 setState 计数器触发重渲染。
- 区分 DataGrid.Options 构造器专用与可写属性:构造器专用有 `stretchStrategy`、`autoSize`、`bindingController`、`editingMode`、`preload`、`defaultColumnOptions`、`lockedLevels`、`beforeEditCell`、`stripedRows`、`multiColumnSort`、`allowUnsort`;可写有 `columnStretch`、`editable`、`paging`、`pageSize`、`pageNumber`、`sortable`、`placeholder`、`showHeader`、`highlightRowsOnHover`。
- 用 `maxViewportWidth` 限制横向视口防止溢出;`stripedRows={true}` 开启斑马纹;`editingMode` 可选 `DataGrid.EditingMode.CELL` 或 `ROW`;`multiColumnSort={true}` 开启多列排序;`allowUnsort={true}` 允许取消排序;行选择优先用内置 `SelectionColumn` 与 `DataGrid.SingleSelection`/`DataGrid.MultiSelection`。
- 可用命令式方法:`autoSize()`、`stretchColumns()`、`reload()`、`rowForDataItem(dataItem)`、`scrollTo({cell/row/column})`、`pinRow(row, section)`。
- `Select` 在 `@uif-js/component` 中不存在(导入为 undefined);DataGrid 内下拉用 `DataGrid.ColumnType.DROPDOWN` 配 `inputMode: DataGrid.InputMode.EDIT_ONLY`、`valueMember: 'value'`、`displayMember: 'label'`、`bindToValue: true`、`dataSource`(用 `useRef` 缓存 `ArrayDataSource`)、`dataSourceConfigurator: function(row) {...}`、`widgetOptions: { allowEmpty: true, placeholder: 'Unassigned' }`,通过网格 `on` 上的 `DataGrid.Event.CELL_UPDATE` 处理变更,网格需 `editable={true}`;独立下拉用 `Dropdown`。
- Modal 的 `Modal.Size` 只有 `DEFAULT`/`SMALL`/`MEDIUM`/`LARGE`(无 `EXTRA_LARGE`);`Modal.Size.LARGE` 有内部 max-width 且 `rootStyle` 无法覆盖,要更宽就移除 `size` 只用 `rootStyle`(如 `rootStyle={{ width: '80vw', maxWidth: '1200px' }}`);Modal 内 DataGrid 加 `rootStyle={{ width: '100%' }}`;`onClose` 不是有效 prop,需用 `closeButton={false}` 加自定义关闭 Button,或 `on={{ [Window.Event.CLOSED]: handler }}`。
- MenuButton 继承 Button 全部 props 并加 `menu`;菜单项是 `ActionItemDefinition` 对象 `{ label: 'Text', action: function() {...} }`;不要设 `icon: null`;标准三点图标用 `SystemIcon.OVERFLOW` 配 `type={Button.Type.GHOST}`;用 `tooltip={null}` 抑制提示;TEMPLATED 列中用 ref 处理器避免闭包过期。
- 通用:所有 UIF 组件都支持 `rootStyle`(`Record<string, string>` 内联 CSS);不要用空 `<Text />` 作条件回退(用 `null`,但不要在 StackPanel 内);大数据集把 ArrayDataSource 限制在约 500 行。
- Store:`Store.Provider` 必须包在调用 `useDispatch()`/`useSelector()` 的组件之上;`Reducer.create()` 接收 action 类型到处理函数的映射,处理函数 `(state, action)` 必须返回新对象;用 `ImmutableObject.set(state, 'key', value)`;`Store.create()` 构造器专用,在模块级创建一次;深层组件用 `useContext(ContextType.STORE)` 访问 store。
- useEffect 异步清理:在 useEffect 顶部创建 `CancellationTokenSource`,取 `var token = source.token` 传给异步操作,在清理函数中调用 `source.cancel()`,并在任何 setState 前检查 `token.cancelled`。
- TreeDataSource:用 `new TreeDataSource({ data: items, childAccessor: (item) => item.children })` 作 `dataSource`,第一列必须是 `DataGrid.ColumnType.TREE` 才能渲染展开/折叠。
- 表单:控件包在 `Field` 中;只读用 `Field.Mode.VIEW`;长表单用 `FieldGroup` 分组;用 `RadioButtonGroup` 管理单选;`Field.Size` 枚举为 `AUTO`/`SMALL`/`MEDIUM`/`LARGE`/`XLARGE`/`XXLARGE`/`STRETCH`。
- 用户反馈:`GrowlPanel` 需加入组件树(根 shell 一次),获取 ref 后调用 `.add(msg)`(非 `.addMessage()`)推送 `GrowlMessage`;瞬时反馈用 GrowlMessage,持久内联提示用 Banner;`Banner.Color` 为 `BLUE`/`BLUE_DARK`/`GREEN`/`ORANGE`。
- FilterPanel:`filters` 和 `filtersVisibilityToggle` 已废弃,改用 `activeFilters` + `showClearAll`;`FilterChip` 需要 `picker` prop(如 `FilterChip.textBox`、`FilterChip.date`)才能打开选择 UI。
- 不可变状态:不要直接改 state(`state.items.push(x)` 不触发重渲染),用 `ImmutableArray.push(state.items, x)` 等;reducer 内用 `ImmutableObject.set(state, 'loading', true)` 返回新对象,不要用 `Object.assign(state, ...)`。
适用边界 · 注意事项
- 不适用于非 NetSuite UIF SPA 项目(如普通 React、其他框架或非 UIF 的 NetSuite 脚本)。
- 需要先安装并可用 `@uif-js/core` 与 `@uif-js/component` 包及本地 `references/` 类型定义文件,否则无法按类名/方法名/枚举搜索。
- 不适用于查询 NetSuite SuiteScript、RESTlet 或其他非 UIF 前端 API。