一、读取缓存中所有key以‘upload’开头的字符串,并删除
- 使用Object.keys,读取所有缓存,并生成数组
- 数组forEach循环遍历,根据startsWith,找到以XXX为开头的字符串
- removeItem删除符合条件的记录
var keys = Object.keys(localStorage);
keys.forEach(function(key){
if(key.startsWith('upload')) {
localStorage.removeItem(key)
}
})
二、为对象object设置动态属性
可以在{ }对象内设置动态属性,只需要将属性放到 [ ]中,如:{[user]:“咸虾米”}
//原来我经常用的方法是这样的
let user="admin";
let obj={};
obj[user] = "咸虾米";
console.log(obj)
//输出:{admin: '咸虾米'}
可以更加简单一些
let user="admin";
let obj={
[user]:"小鱼吃虾米"
}
console.log(obj);
//依然输出:{admin: '小鱼吃虾米'}
三、父子组件传值,上传列表是弹窗的子组件,当上传状态修改为上传成功后,将下面的取消和确定按钮,由禁用改为启用。
1.列表子组件使用computed计算属性,监听列表中上传状态是不是都修改为上传成功了,根据上传的状态返回true或者false,然后使用watch监听计算属性的状态变化,使用emit向父组件返回值。
//上传列表不能为空,并且上传状态为success
const uploadBtnState = computed(()=>{
if(uploadFileList.value.length && uploadFileList.value.every(item=>item.status == FileStatus.success)){
return false;
}else{
return true;
}
});
//监听是否全部上传完毕
watch(uploadBtnState,(nv)=>{
emit("btnState",nv);
},{immediate:true})
2.父组件接收子组件自定义事件名称btnState,根据传过来的值,使用$event修改父组件的值。
<el-dialog>
<uploadVod @btnState="vodLoding = $event"></uploadVod>
<template #footer>
<el-button
type="primary"
@click="handleConfirmVod"
:disabled="vodLoding">确认
</el-button>
</template>
</el-dialog>
3.以上代码就是子组件向父组件通过事件传值,在父组件中使用$event可以直接获取到子组件传来的值,就无需再定义方法修改vodLoding的状态了,在标签上即可完成修改。
四、element-plus的弹窗关闭后获取不到Dialog子组件数据
问题复现:
从父组件里面想要获取子组件uploadVod,使用defineExpose向外导出的方法,放到dialog弹窗中获取不到,因为 destroy-on-close属性会销毁掉内部的HTML。
//父组件index.vue,
<el-dialog v-model="vodDialogState" destroy-on-close>
<uploadVod @btnState="vodLoding = $event" ref="uploadVodRef"></uploadVod>
</el-dialog>
<script setup>
const uploadVodRef=ref(null);
uploadVodRef.value.videoInfo;
</script>
//子组件uploadVod.vue
<script>
defineExpose({
videoInfo:[11,22,33]
})
</script>
还有,弹窗展示的时候,想要在点击确认时候获取到子组件中的videoInfo值,发现也拿不到,什么原因那?一定要想获取值,再去关闭弹窗,否则顺序颠倒,将拿不到子组件中defineExpose导出的数据。
//点击确认
function handleConfirmVod(){
//要先获取子组件中导出的数据
uploadVodRef.value.videoInfo
//再将Dialog关闭销货
vodDialogState.value = false;
}
五、defineExpose向外暴露数组,并且需要对该数组map处理
//错误代码演示
defineExpose({
videoInfo:uploadFileList.value.map((item)=>{
return {customName:item.name,ossId:item.ossId}
})
})
如果按照上面代码去向外暴露,那么对数组map循环遍历没有问题,但是uploadFileList数组有可能发生改变,导致导出去的属性videoInfo数组永远不变,正确的方式应该使用计算属性computed包裹map循环。
defineExpose({
videoInfo:computed(()=>uploadFileList.value.map((item)=>{
return {customName:item.name,ossId:item.ossId}
}))
})
六、使用forEach循环遍历发送网络请求的两种需求实现
1.循环发送请求,但是不要回调结果的方式:
直接再循环体内执行网络请求即可,不用等待结果,只要执行了请求方法,自动会进行接口的删除逻辑方法。
listArr.value.forEach(item=>{
//videoDelFile这个方法就是将id传入,执行网络请求,这里是删除文件的逻辑
videoDelFile(item.videoId)
})
2.循环执行后,需要获取到每次的回调结果:
提前准备好数组,在forEach中将网络请求push到数组中,在循环体外执行Promise.all(请求数组)
//子组件中的方法
const delUploadFileList = ()=>{
let taskArr = []
uploadFileList.value.forEach(item=>{
if(item.videoId){
taskArr.push(videoDelFile(item.videoId))
}
})
return Promise.all(taskArr);
}
//向外暴露该方法
defineExpose({
delUploadFileList
})
//父组件使用该方法
const uploadVodRef=ref(null)
uploadVodRef.value.delUploadFileList(res=>{
//这里返回的res就是Promise.all的回调数组集合
console.log(res)
})