跳转到内容

Svelte 包 API 参考(@piying/view-svelte)

本文介绍 Svelte 包 @piying/view-svelte 的公开 API。Svelte 使用 runes($state / $effect)作为响应式基础,字段通过 getContext 获取。

<script>
  import { PiyingView } from '@piying/view-svelte';
</script>

<PiyingView {schema} {options} {model} modelChange={(v) => (model = v)} />
Props 类型 说明
schema v.BaseSchema Valibot Schema
model any 模型值(单向传入,变化后重新写入表单)
modelChange (value: any) => void 模型变更回调(仅在无验证错误时触发)
options FieldConvertViewOptions 转换选项

model 不是 $bindable() prop,不能写 bind:model;需要自己在 modelChange 里回写本地状态。

🧭 手动模式:属于 两种使用模式 中的模式二。只手动渲染位置,字段内部仍全自动渲染。

把「包装器链 + 组件 + 递归子字段」整棵树渲染到指定位置:

<script>
  import { PiyingFieldTemplate } from '@piying/view-svelte';
</script>

<PiyingFieldTemplate {field} {path} />
Props 类型 说明
field PiResolvedViewFieldConfig(必填) 要渲染的字段配置
path KeyPath(可选) 定位子字段;不传则渲染整个根字段

完整渲染管线、懒加载与常见坑见 PiyingFieldTemplate(字段渲染)

🧭 手动模式:同 PiyingFieldTemplate,属于模式二(手动绑定)。

字段绑定:把字段的 FieldControl 接到你手写的控件上,通过 children snippet 暴露 cvaa / field

<script lang="ts">
  import { PiyingField } from '@piying/view-svelte';
  let { field } = $props();
</script>

<PiyingField {field} path={['text1']}>
  {#snippet children(cvaa, f)}
    <input
      type="text"
      value={cvaa.value ?? ''}
      disabled={cvaa.disabled}
      oninput={(e) => cvaa.valueChange(e.currentTarget.value)}
      onblur={cvaa.touchedChange}
    />
  {/snippet}
</PiyingField>
Props 类型 说明
field PiResolvedViewFieldConfig(必填) 字段配置
path KeyPath(可选) 定位叶子子字段再绑定
children (cvaa, field) => any snippet 参数,类型跟着 path 推导

完整说明(含 cvaa 成员、错误码、与 PiyingFieldTemplate 对比)见 PiyingField(字段绑定)

字段组容器,用于渲染 object / array / record 等容器类型。

<script lang="ts">
  import { PiyingViewGroup } from '@piying/view-svelte';

  const options = {
    fieldGlobalConfig: {
      types: {
        object: { type: PiyingViewGroup },
        array: { type: PiyingViewGroup },
      },
    },
  };
</script>
<PiyingViewGroup {field} />

Svelte 通过 getContext 获取字段,而非依赖注入:

<script>
  import { getContext } from 'svelte';
  import { PI_VIEW_FIELD_TOKEN, InjectorToken } from '@piying/view-svelte';

  const field = getContext(PI_VIEW_FIELD_TOKEN);       // () => PiResolvedViewFieldConfig
  const injector = getContext(InjectorToken);          // () => Injector
</script>
  • PI_VIEW_FIELD_TOKEN — 当前字段配置(() => PiResolvedViewFieldConfig
  • InjectorToken — 静态注入器
<script>
  import { useControlValueAccessor } from '@piying/view-svelte';
  const { cva, cvaa } = useControlValueAccessor();
  export { cva }; // 导出 CVA 供库内部注册
</script>

cvaa 提供:

成员 类型 说明
value $state getter 当前值
disabled $state getter 禁用状态
valueChange(v) (v) => void 更新值并触发变更
touchedChange() () => void 触发 touched 回调
<script>
  import { signalToState } from '@piying/view-svelte';
  const inputs = signalToState(() => field().inputs());
  const outputs = signalToState(() => field().outputs());
</script>

返回一个函数,调用时返回当前状态值(() => dataRef)。

typedFieldComponentPipe — 路径 + 组件双强类型

Section titled “typedFieldComponentPipe — 路径 + 组件双强类型”

按「路径 + 组件」写配置,inputs 收非函数 prop,outputs 收函数 prop(名字原样)。特别注意:Snippet 不算 output。详见 typedFieldComponentPipe(Svelte)

import { typedFieldComponentPipe } from '@piying/view-svelte';

const merged = typedFieldComponentPipe(schema, define, (d) => [
  d(['price'], 'amount', [d.inputs.patch({ placeholder: '请输入金额' })]),
  d(['tags'], 'tags', [d.outputs.merge({ onChange: (value) => {} })]),
]);

Svelte 版没有 d.modelsbind:prop 在类型上只是普通 prop,运行时也不消费 field.models

<script>
  import { SvelteSchemaHandle, SvelteFormBuilder } from '@piying/view-svelte';
</script>
<script>
  import { convertToField } from '@piying/view-svelte';
  // 第二个参数为可选的父 Injector,第三个参数为取值函数形式的 options
  const field = convertToField(() => schema, injector /* 可选 */, () => options);
</script>

Svelte 的字段配置类型:

import type { PiResolvedViewFieldConfig } from '@piying/view-svelte';
<script lang="ts">
  import { useControlValueAccessor } from '@piying/view-svelte';
  const { cva, cvaa } = useControlValueAccessor();
  export { cva };
</script>

<input
  value={cvaa.value}
  disabled={cvaa.disabled}
  oninput={(e) => cvaa.valueChange(e.currentTarget.value)}
  onblur={() => cvaa.touchedChange()}
/>

@piying/view-svelte 导出:PiyingViewPiyingFieldTemplatePiyingFieldPiyingViewGroupPI_VIEW_FIELD_TOKENInjectorTokensignalToStateuseControlValueAccessortypedFieldComponentPipeconvertToFieldSvelteSchemaHandleSvelteFormBuilderPiResolvedViewFieldConfig