【问题标题】:File input in svelte does not update datasvelte 中的文件输入不更新数据
【发布时间】:2021-12-09 16:19:34
【问题描述】:

我正在尝试创建一个带有客户端文件输入的站点,其中一些数据完全在客户端处理,没有任何内容发送到服务器。

我有以下 Svelte 组件 (App.svelte):

<script>
let data;
function handleFileSelect(evt) {
    var files = evt.target.files;
    if (! (files && files[0])) {
        return;
    }
    let binfile = files[0];
    let reader = new FileReader();
    reader.onload = function(evt) {
        data = new Uint8Array(evt.target.result);
    }
    reader.readAsArrayBuffer(binfile);
}
</script>

<main>
    <label for="fileinput">Your data</label>
    <input type="file" id="fileinput" on:click={handleFileSelect}/>
    <div>
        <textarea id="datafield" rows="10" cols="50">{data}</textarea>
    </div>
</main>

当我单击按钮时,文本区域中的数据不会更新,但是当我第二次单击按钮时,一旦单击,数据就会加载到文本区域中。我在正确的轨道上加载文件吗?我错过了什么?谢谢!

【问题讨论】:

    标签: svelte


    【解决方案1】:

    在文件输入上,您要绑定值而不是点击事件。

    像这样:

    <script>
    let files = [];
    <input 
       bind:files
       type="file"
       accept="image/*">
    
    or bind:value={files}
    
    {files}
    

    编辑:回答chovy的问题

    let template = null;
    let files = null;
    
    $: if (files) {
       const fileText = files[0].text();
       fileText.then((text) => {
           template = text;
       });
       files = null;
    }
    

    请注意,我只打算在我的代码中使用第一个文件,如果您使用多文件上传,则必须从文件调用中删除 [0],遍历数组并写入就像处理任何其他数组数据一样,将每个单独的文件放入指定的变量中。在上述情况下,模板将包含实际文件数据作为文本。

    希望这会有所帮助。

    【讨论】:

    • 这让我成功了一半,谢谢!我还必须按照我的答案来获取文件内容。
    • 是的,选择文件时如何调用方法?这就是问题所在。
    • @chovy 我更新了我的答案,希望这能回答你的问题。
    【解决方案2】:

    我也必须这样做才能获取文件的内容:

    <script>
    let data;
    let files;
    $: {
        if (files && files[0]) {
            let binfile = files[0];
            let reader = new FileReader();
            reader.onload = function(evt) {
                data = new Uint8Array(evt.target.result);
            }
            reader.readAsArrayBuffer(binfile);
        }
    }
    </script>
    
    <main>
        <label for="fileinput">Your data</label>
        <input type="file" id="fileinput" bind:files />
        <div>
            <textarea id="datafield" rows="10" cols="50">{data}</textarea>
        </div>
    </main>
    

    【讨论】:

    • 我不知道这是否是惯用的 svelte(这是我第一次涉足 svelte - 以及一般的 web 开发),但这是我让它工作的方式。看起来有点慢,但确实有效。
    • 它应该按照 web api 工作。也许这里的其他人有更好/更合适的方法来做到这一点。
    【解决方案3】:

    如果你想要一个自定义按钮而不是丑陋的默认按钮: 代码很苗条 + Framework7

    <script>
    let browseInput;
    let data;
    let files;
    
    $: {
        if ... see answer 2 
       }
    </script>
    
    <input bind:this={browseInput} type="file" id="fileinput" class="hidden" bind:files={files}>
    <Button onClick={() => browseInput.click()} fill raised">Open Keystore File</Button>
    
    <style>
    .hidden {
       display: none !important;
     }
    </style>
    

    【讨论】:

      猜你喜欢
      • 2021-07-31
      • 2019-09-21
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      • 2020-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多