最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Best way to handle Svelte component props - Stack Overflow

programmeradmin6浏览0评论

I'm building an app using SvelteKit and Tailwind. I know that when using Tailwind to style it is remended to leverage ponents to reduce the amount of repeated code you have to write using Tailwinds utility classes. My issue is that when making ponents based on HTML tags, for instance an <input> tag, dealing with props in that ponent that would normally just be attributes for that tag is getting overwhelming. MDN shows that the <input> tag has 31 possible attributes. I know that I won't be using all of them but going back and forth and adding them as props to a ponent is getting tiresome.

What is the best way to solve this problem without adding up to 31 lines of export let attribute to a ponent and adding them to the real HTML tag inside of the ponent?

Example:

<script>
    export let name;
    export let id;
    export let type;
    export let disabled;
    export let required;
    export let minLength;
    export let maxLength;
    export let min;
    export let max;
    export let pattern;

    let value;
    let borderColor = '#D1D5DB';

    const inputHandler = (e) => {
        if (e.target.value === '') {
            borderColor = '#D1D5DB';
        } else {
            borderColor = '';
        }
    };
</script>

<input
    {name}
    {id}
    {type}
    {disabled}
    {required}
    {minLength}
    {maxLength}
    {min}
    {max}
    {pattern}
    on:input={inputHandler}
    style={`border-color: ${borderColor}`}
    class="
    w-full px-1 py-px mb-4 bg-transparent border-2 border-gray-300 
    rounded-xl last:mb-0 valid:border-emerald-300 invalid:border-rose-400
  "
/>

I'm building an app using SvelteKit and Tailwind. I know that when using Tailwind to style it is remended to leverage ponents to reduce the amount of repeated code you have to write using Tailwinds utility classes. My issue is that when making ponents based on HTML tags, for instance an <input> tag, dealing with props in that ponent that would normally just be attributes for that tag is getting overwhelming. MDN shows that the <input> tag has 31 possible attributes. I know that I won't be using all of them but going back and forth and adding them as props to a ponent is getting tiresome.

What is the best way to solve this problem without adding up to 31 lines of export let attribute to a ponent and adding them to the real HTML tag inside of the ponent?

Example:

<script>
    export let name;
    export let id;
    export let type;
    export let disabled;
    export let required;
    export let minLength;
    export let maxLength;
    export let min;
    export let max;
    export let pattern;

    let value;
    let borderColor = '#D1D5DB';

    const inputHandler = (e) => {
        if (e.target.value === '') {
            borderColor = '#D1D5DB';
        } else {
            borderColor = '';
        }
    };
</script>

<input
    {name}
    {id}
    {type}
    {disabled}
    {required}
    {minLength}
    {maxLength}
    {min}
    {max}
    {pattern}
    on:input={inputHandler}
    style={`border-color: ${borderColor}`}
    class="
    w-full px-1 py-px mb-4 bg-transparent border-2 border-gray-300 
    rounded-xl last:mb-0 valid:border-emerald-300 invalid:border-rose-400
  "
/>

Share Improve this question asked May 18, 2022 at 21:43 ClarenceClarence 3223 silver badges9 bronze badges 6
  • 2 you could export an object as prop and then spread it into the input – pilchard Commented May 18, 2022 at 21:55
  • 2 repl – pilchard Commented May 18, 2022 at 22:02
  • 1 @pilchard this is absolutely the way to do it, you should write it up as an answer using your REPL code as a guideline – Thomas Hennes Commented May 19, 2022 at 3:25
  • 1 @pilchard The default values which are set on the exported variable get overwritten if the prop is passed on the ponent. So if just one value should be modified, all the values must be defined again in the parent. To prevent that I would suggest to seperate the default Options into a seperate object and spread both on the input element svelte.dev/repl/52715e3c326349fca4f310060869960b?version=3.48.0 – Corrl Commented May 19, 2022 at 6:55
  • 1 Or probably even better - set the attributes which actually have a default value directly on the input element and spread the options afterwards svelte.dev/repl/062b19cdfc1a45409d66fbd1245609c6?version=3.48.0 – Corrl Commented May 19, 2022 at 7:11
 |  Show 1 more ment

2 Answers 2

Reset to default 5

If you want to be able to do

<MyInputField name="123" maxLength="5" type="text">

Without having to declare all these extra attribute, the best way to do so is to use the $$restProps, this object will contain all the props that have been passed to the ponent but have not been explicitly defined as props (exported).

<script>
  export let name = "";
</script>

<input name={name} {..$$restProps}>

(here name was defined, so it will not be included in $$restProps and I had to add it myself)

Alternatively to using the $$restProps (and based on @pilchard's ment above, thanks for that) an options object could be exported, which is holding all the modified attributes values and is spread after the default attributes defined on the input element inside the ponent
Like this all possible attributes of the element can be used/set without having to write them all out anywhere REPL

<script>
    import Input from './Input.svelte';

    const options ={
        type: 'number',
        placeholder:'input a number',
        required: true
    };
</script>

<Input {options} />
Input.svelte
<script>
    export let options = {}
    export let value = ''
</script>

<input type="text"
       placeholder="default placeholder"
       {...options}
       bind:value
       style:border-color="{options.required && value === '' ? 'tomato' : ''}"
       class="w-full px-1 py-px mb-4 bg-transparent border-2 ..."
       />
发布评论

评论列表(0)

  1. 暂无评论