实习随笔-1

75 阅读2分钟

此系列旨在记录实习中遇到的技术问题,方便日后再次遇到可以查阅。

最近在做实习以来的第二个需求,在一个由后端数据动态生成的表单中添加上传文件、下载文件和更新文件的按钮。

上传文件的功能本来我就没自己写过,问ai才知道应该用按钮配合点击事件来触发被隐藏的input组件的click事件,来实现按钮与文件上传组件的联动。OK听起来不难,写写看。

然后不出意外,写的依托勾石,完全跑不通...

仔细复盘了一下,发现应该是ref与v-for一起使用的问题。首先声明一点,这两者可以一起使用,但是,不能像我之前这么用...

我最开始的代码belike:

<template>
    <div v-for="(item,index) in 10" :key="index">
        <input type="file" :ref="ITEM"/>
        <button @click="func()">click</button>
    </div>
</template>
<script setup>
import { ref } from 'vue'
const ITEM = ref(null)
const func = () => {
    ITEM.value.click()
}
</script>

bro以为inputref会分身😅,第一版有点蠢的没边了,改!

第二版稍微像个正常人写的了:

<template>
    <div v-for="(item,index) in 10" :key="index">
        <input type="file" :ref="ITEMs[index]"/>
        <button @click="func(index)">click</button>
    </div>
</template>
<script setup>
import { ref } from 'vue'
const ITEMs = ref(new Array(10).fill(null))
const func = (index) => {
    ITEMs.value[index].click()
}
</script>

看起来已经无懈可击了,对吧!
对吗???

那这时候豆包就告诉我:亲,ref不支持这么写哦~要使用高阶函数哟!

于是我又查了查什么叫高阶函数...

总算可以跑了,最后一版如下:

<template>
    <div v-for="(item,index) in 10" :key="index">
        <input type="file" :ref="setRef(index)"/>
        <button @click="func(index)">click</button>
    </div>
</template>
<script setup>
import { ref } from 'vue'
const ITEMs = ref(new Array(10).fill(null))
const setRef = (index) => (el) => {
    ITEMs.value[index] = el
}
const func = (index) => {
    console.log(ITEMs.value[index])
    ITEMs.value[index].click()
}
</script>

那么长话短说呢,就是在获取input实例的时候,使用一个函数来实现,也就是setRef,它的返回值也是个函数(所谓高阶函数),返回的函数接受一个参数el,代表input实例,被赋值到用于存储实例的数组中index下标对应的位置。

源自搜索:在 Vue 中, ref 指令可以接收一个函数作为值。当组件挂载时,这个函数会被调用,并且将对应的 DOM 元素或者组件实例作为参数传入;当组件卸载时,这个函数同样会被调用,不过此时传入的参数为 null 。

不过呢,当时一直出问题,搞得我有点急,所以实际代码中没有使用ref的方案,而是使用label配合input来实现绑定文件选择框到按钮(当然也是豆包教我的🤫)总之是可以跑通的~