封装上传文件组件(axios,onUploadProgress,取消请求)

news2024/11/27 14:38:17

目录

定时模拟进度条

方法

A.axios

B.xhr

取消请求​​​​​​​

完整代码

A.自定义上传组件

B.二次封装组件

情况

增加cancelToken不生效,刷新页面

进度条太快->设置浏览器网速

定时模拟进度条

    startUpload() {
        if (!this.file) return;

        const totalSize = this.file.size;
        let uploadedSize = 0;

        const interval = setInterval(() => {
            if (uploadedSize >= totalSize) {
                clearInterval(interval);
                // this.state_tip = STATE_TIPS.get('上传成功');
            } else {
                uploadedSize += 1024;
                this.progress = Math.round((uploadedSize / totalSize) * 100);
            }
        }, 200);
    }

方法

A.axios

 uploadQuery() {
        if (!this.file) return;
        this.state_tip = STATE_TIPS.get('上传中');
        this.progress = 0;
        // headers = {'Content-Type': 'multipart/form-data'}
        const formData = new FormData()
        formData.append('file', this.file)
        axios.post(this.uploadPath, formData, {
            headers: {
                "X-Requested-With": "XMLHttpRequest",
            },
            onUploadProgress: (progressEvent: ProgressEvent) => {
                console.log("onUploadProgress");
                if (progressEvent.lengthComputable) {
                    this.progress = Math.round(
                        (progressEvent.loaded / progressEvent.total) * 100
                    );
                    console.log(this.progress);
                }
            },
        }).then((res: any) => {
            if (res && res.code == 200) {
                this.uploadExel = res.data;
                this.state_tip = STATE_TIPS.get('上传成功');
                console.log(this.uploadExel);
                this.$emit("update:uploadExel", this.uploadExel);
            } else {
                this.state_tip = STATE_TIPS.get('其他');
                this.state_tip.tip = res.msg || '请取消上传,更换符合模板要求的文件';
            }
        }).catch((error: any) => {
            this.state_tip = STATE_TIPS.get('上传失败');
        }).finally(() => {
            this.uploaded = true;
            this.$emit("update:uploaded", this.uploaded);
        });
    }

B.xhr

   uploadQuery(file: File) {
        // headers = {'Content-Type': 'multipart/form-data'}
        const formData = new FormData()
        formData.append('file', file)
        const xhr = new XMLHttpRequest();
        xhr.open("POST", this.uploadPath, true);

        xhr.upload.onprogress = (event) => {
            if (event.lengthComputable) {
                this.uprogress = Math.round((event.loaded / event.total) * 100);
            }
        };

        xhr.onload = () => {
            console.log(xhr);
            
            if (xhr.status === 200) {
                const res = JSON.parse(xhr.responseText);
                console.log(res);
                console.log(res.code);
                if (res.code === 200) {
                    this.uploadExel = res.data;
                    this.state_tip = "上传成功";
                    this.uploaded = true;
                    console.log(this.uploadExel);
                    this.$emit("update:uploaded", this.uploaded);
                    this.$emit("update:uploadExel", this.uploadExel);
                } else {
                    // 处理上传失败情况
                    this.state_tip = "上传失败";
                }
            }
        };

        xhr.onerror = () => {
            // 处理上传出错情况
            this.state_tip = "上传出错";
        };

        xhr.send(formData);
        // request.post(this.uploadPath, formData).then((res: any) => {

        //     if (res.code == 200) {
        //         this.uploadExel = res.data;
        //         this.state_tip = STATE_TIPS.get('上传成功');
        //         this.uploaded = true;
        //         this.$emit("update:uploaded", this.uploaded);
        //         this.$emit("update:uploadExel", this.uploadExel);
        //     } else {

        //     }
        // })
    }

取消请求​​​​​​​

完整代码

<UploadComp :uploadPath="PATH" :fileLogPath="PATH.replace('uploadExcel?wpReleId=','getOtherIndexFileLog/')" :uploaded.sync="uploaded" :uploadExel.sync="uploadExel" @cancelUpload="cancelUpload" />
            <!-- <SingleUploadComp :uploadPath="PATH" :uploaded.sync="uploaded" :uploadExel.sync="uploadExel" @cancelUpload="cancelUpload" /> -->

A.自定义上传组件

<template>
    <div class="upload-list-dragger" :uploadPath="uploadPath" :fileLogPath="fileLogPath">
        <div v-if="!file" @click="openFileInput" @dragenter="onDragEnter" @dragover="onDragOver" @drop="onDrop"
            :class="{ 'drag-over': isDragOver }">
            <input type="file" ref="fileInput" style="display: none;" @change="onFileChange" :accept="format" />
            <div class="custom-drag-style">
                <img src="@/assets/img/upload.png" class="upload-icon" />
                <div class="upload-click-drag">点击或拖拽上传文件</div>
                <!-- 使用正则表达式替换所有点号 -->
                <div class="upload-tip">请上传{{ format.replace(/\./g, "") }}格式文件,上传多份文件时以最后一次为准</div>
            </div>
        </div>
        <div v-else class="custom-upload-card">
            <img class="upload-card-icon" src="@/assets/img/excel.png" />
            <div class="upload-card-state">
                <div>
                    <span class="file-name">{{ file.name }}</span>
                    <span class="cancel-upload" @click="cancelUpload"><mds-icon type="line-close" /></span>
                </div>
                <div class="progress-bar" :style="{ width: progress + '%', backgroundColor: state_tip.color }"></div>
                <div class="span-container">
                    <span :style="{ color: state_tip.state === '上传中' ? '#A8ACB3' : state_tip.color }">{{
                        state_tip.tip
                    }}</span>
                    <span v-if="state_tip.state === '上传中'">{{ progress + '%' }}</span>
                    <span v-if="state_tip.state === '上传失败'" class="span-operate" underline
                        @click="restartUpload">重新上传</span>
                    <span v-if="state_tip.state === '上传成功'" class="span-operate" underline
                        @click="downloadQuery">下载结果明细</span>
                </div>
            </div>
        </div>
    </div>
</template>
  
<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator';
import request from '@/utils/request'
import axios, { Canceler } from 'axios';
const STATE_TIPS = new Map([['其他', { state: '其他', color: 'orange', tip: '' }], ['上传中', { state: '上传中', color: '#1564FF', tip: '文件上传解析中…' }], ['上传失败', { state: '上传失败', color: '#DD2100', tip: '上传失败,请重新上传' }], ['上传成功', { state: '上传成功', color: '#00AF5B', tip: '上传成功!' }]])
@Component({
    components: {}
})
export default class UploadComp extends Vue {
    @Prop({ required: true }) private uploadPath!: string
    @Prop({ required: true }) private fileLogPath!: string
    @Prop({ default: '.xls' }) private format!: string //形如".xls,.csv,.xlsx"

    uploadExel: any = {
        succList: []
    }
    uploaded: boolean = false;

    file: File | null = null;
    source = axios.CancelToken.source();

    progress = 0;
    isDragOver = false;
    data() {
        return {
            state_tip: {},
            
        }
    }
    created() {
        console.log(this.fileLogPath);
    }
    onFileChange(event: Event) {
        const target = event.target as HTMLInputElement;
        this.fileValidator(target.files);//可能为null
    }
    fileValidator(files: FileList | undefined | null) {
        if (files && files.length > 0) {
            // 上传多份文件时以最后一次为准
            const file = files[0];
            if (this.isValidFormat(file)) {
                this.file = file;
                console.log(this.file);
                this.uploadQuery();
            } else {
                alert(`请上传${this.format.replace(/\./g, "")}格式文件。`);
            }
        } else {
            alert(`请上传文件!`);
        }
    }
    uploadQuery() {
        if (!this.file) return;
        this.state_tip = STATE_TIPS.get('上传中');
        this.progress = 0;
        // headers = {'Content-Type': 'multipart/form-data'}
        const formData = new FormData()
        formData.append('file', this.file)
        // 在合适的地方定义取消令牌和取消函数
        const CancelToken = axios.CancelToken;

         // 判断上一次的请求是否还在继续,如果还在继续,则取消上一次的请求
       if(this.source.token._listeners!=undefined )
        {
            this.source.cancel("取消请求")
            this.source = axios.CancelToken.source()
        }

        request.post(this.uploadPath, formData, {
            onUploadProgress: (progressEvent: ProgressEvent) => {
                console.log("Upload progress:", progressEvent);
                this.progress = Math.round((progressEvent.loaded / progressEvent.total) * 100);
                console.log("进度:", this.progress);
            },
            cancelToken:this.source.token,
        }).then((res: any) => {
            if (res && res.code == 200) {
                this.uploadExel = res.data;
                this.state_tip = STATE_TIPS.get('上传成功');
                console.log(this.uploadExel);
                this.$emit("update:uploadExel", this.uploadExel);
                this.uploaded = true;
                this.$emit("update:uploaded", this.uploaded);
            } else {
                this.state_tip = STATE_TIPS.get('其他');
                this.state_tip.tip = res.msg || '请取消上传,更换符合模板要求的文件';
            }
        }).catch((error: any) => {
            this.state_tip = STATE_TIPS.get('上传失败');
        })
    }
    downloadQuery() {
        request.get(this.fileLogPath).then((res: any) => {
            var aLink = document.createElement("a");
            aLink.style.display = "none";
            aLink.href = res.data[0].fileUrl
            document.body.appendChild(aLink);
            aLink.click();
            document.body.removeChild(aLink);
        })
    }
    cancelUpload() {
        console.log("取消上传")
        this.state_tip = STATE_TIPS.get('其他');
        this.progress = 0;
        this.file = null;
        if (this.uploaded) {
            this.$emit('cancelUpload', this.uploadExel.fileLogId)
        }else{
            this.source.cancel("请求已被取消")
            this.source = axios.CancelToken.source()
        }
    }

    restartUpload() {
        this.uploadQuery();
    }
    openFileInput() {
        const fileInput = this.$refs.fileInput as HTMLInputElement;
        fileInput.click();
    }
    // 拖动文件进入上传区域
    onDragEnter(event: DragEvent) {
        // 防止浏览器默认的拖放行为
        event.preventDefault();
        this.isDragOver = true;
    }
    // 拖动文件在上传区域中移动
    onDragOver(event: DragEvent) {
        //防止浏览器默认的拖放行为
        event.preventDefault();
    }
    // 放置拖动的文件
    onDrop(event: DragEvent) {
        event.preventDefault();
        this.isDragOver = false;
        this.fileValidator(event.dataTransfer?.files)//可能为undefined
    }
    isValidFormat(file: File) {
        const supportedFormats: string[] = this.format.split(','); // 将 format 字符串拆分成数组
        const fileExtension = '.' + file.name.split('.').pop(); // 获取文件名的扩展名
        return supportedFormats.some((supportedFormat: string) => {
            return fileExtension === supportedFormat;
        });
    }
}
</script>
  
<style>
.upload-list-dragger {
    width: 800px;
    height: 160px;
    border: 1px dashed rgba(206, 212, 224, 1);
    border-radius: 4px;
    display: flex;
    align-items: center;
}

.upload-list-dragger:hover {
    background-color: #eef8ff;

}

.custom-drag-style {
    height: 140px;
    width: 780px;
    background-color: #fff;
    flex-wrap: wrap;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    cursor: pointer;

    .upload-icon {
        width: 24px;
        height: 24px;
    }

    .upload-click-drag {
        width: 144px;
        height: 24px;
        font-family: PingFangSC-Regular;
        font-size: 16px;
        font-weight: 400;
        line-height: 24px;
        color: rgba(69, 71, 77, 1);
        text-align: left;
        display: block;
    }

    .upload-tip {
        height: 24px;
        font-family: PingFangSC-Regular;
        font-size: 14px;
        font-weight: 400;
        line-height: 24px;
        color: rgba(168, 172, 179, 1);
        text-align: left;
        display: block;
    }
}

.custom-upload-card {
    display: flex;
    align-items: center;
    height: 71px;

    .upload-card-icon {
        width: 71px;

    }

    .upload-card-state {
        height: 100%;
        display: flex;
        flex-direction: column;
        justify-content: space-around;

        .file-name {
            font-family: PingFangSC-Regular;
            font-size: 16px;
            font-weight: 400;
            line-height: 16px;
            color: rgba(69, 71, 77, 1);
            text-align: left;
            margin-right: 12px;
        }

        .cancel-upload {
            cursor: pointer;
        }

        .progress-bar {
            height: 8px;
            border-radius: 8px;
        }

        /* 进度条看作是由两个嵌套的<div>元素构成,外部的.progress-bar元素和内部的<div> */
        .progress-bar div {
            width: 638px;
            height: 8px;
            background-color: rgba(228, 231, 237, 1);
            border-radius: 8px;
        }

        .span-container {
            width: 690px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-family: PingFangSC-Regular;
            font-size: 14px;
            font-weight: 400;
            line-height: 24px;

            .span-operate {
                color: #1564FF;
                cursor: pointer;
            }
        }
    }

}
</style>
  

B.二次封装组件

<template>
  <mds-upload ref="uploadRef" :path="uploadPath" name="file" :beforeUpload="onBeforeUpload"
    :getUploadParams="getUploadParams" :disabled="false" :multiple="false" :accept="format" :onComplete="onUploadComplete"
    :onError="onUploadError" :onChange="onListChange" listType="imgCard" :limit="1" :dragable="true">
    <template v-slot:dragStyle>
      <div class="custom-drag-style">
        <img src="@/assets/img/upload.png" class="upload-icon" />
        <div class="upload-click-drag">点击或拖拽上传文件</div>
        <!-- 使用正则表达式替换所有点号 -->
        <div class="upload-tip" slot="tip">请上传{{ format.replace(/\./g, "") }}格式文件,上传多份文件时以最后一次为准</div>
      </div>
    </template>
  </mds-upload>
</template>
<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator'
@Component({
  components: {}
})
export default class SingleUploadComp extends Vue {
  @Prop({ required: true })  private uploadPath!: boolean
  @Prop({ default: '.xls' }) private format!: string //形如".xls,.csv,.xlsx"
  uploadExel: any = {
    succList: []
  }
  uploaded:boolean= false
   onBeforeUpload(files: File[], callback: (files: File[]) => void) {
    callback(files)
  }
  
   getUploadParams(file: File, callback: (data: any) => void) {
    const formData = new FormData()
    formData.append('file', file)
    const cbData = {
      data: formData,
      withCredentials: true
    }
    callback(cbData)
    this.$refs.uploadRef.$el.querySelector('.upload-list-dragger').style.display = "none";
  }
  /**
   * @param res 响应结果
   * @param oriFile 原始文件
   */
   onUploadComplete(res: any, oriFile: File) {
    const errEle = this.$refs.uploadRef.$el.querySelector('.mds-upload-card-data-error')
    if (res.data.code == 200) {
      this.uploadExel = res.data.data;
      this.$emit("update:uploadExel", this.uploadExel); 
      errEle.innerHTML = "上传成功!";
      this.uploaded = true;
      this.$emit("update:uploaded", this.uploaded); 
    } else {
      errEle.innerHTML = res.data.msg;
      errEle.style.color = "orange";
    }
  }
   onUploadError(err: any, oriFile: File) {
    const errEle = this.$refs.uploadRef.$el.querySelector('.mds-upload-card-data-erro')
    errEle.innerHTML = "上传失败,请重新上传";
  }
   onListChange(uploadList: any[]) {
    console.log('on list change')
    if (uploadList.length == 0) {
      if (this.uploaded) {
        console.log("取消上传")
        this.$emit('cancelUpload', this.uploadExel.fileLogId)
      }
      this.$refs.uploadRef.$el.querySelector('.upload-list-dragger').style.display = "block";
    }
  }
}  
</script>
<style lang="scss" scoped>
::v-deep .upload-list-dragger {
  // position: relative;
  width: 800px;
  height: 160px;
  border: 1px dashed rgba(206, 212, 224, 1);
  border-radius: 4px;

  .custom-drag-style:hover {
    background-color: #eef8ff;
  }

  .custom-drag-style {
    height: 140px;
    background-color: #fff;
    flex-wrap: wrap;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    cursor: pointer;

    .upload-icon {
      width: 24px;
      height: 24px;
    }

    .upload-click-drag {
      width: 144px;
      height: 24px;
      font-family: PingFangSC-Regular;
      font-size: 16px;
      font-weight: 400;
      line-height: 24px;
      color: rgba(69, 71, 77, 1);
      text-align: left;
      display: block;
    }

    .upload-tip {
      width: 326px;
      height: 24px;
      font-family: PingFangSC-Regular;
      font-size: 14px;
      font-weight: 400;
      line-height: 24px;
      color: rgba(168, 172, 179, 1);
      text-align: left;
      display: block;
    }
  }
}

::v-deep .mds-upload-card {
  position: relative;
  width: 800px;
  height: 160px;
  border: 1px dashed rgba(206, 212, 224, 1) !important;
  border-radius: 4px;
}

::v-deep .mds-upload-card:hover .mds-upload-card-eyes {
  display: none;
}

::v-deep .mds-upload-card-icon {
  width: 71px;
  height: 71px;
  display: block;

  &::before {
    content: '';
    display: block;
    width: 71px;
    height: 71px;
    background: url('../../../assets/img/excel.png');
    background-size: 71px 71px;
    z-index: 9999;
  }
}

::v-deep .mds-upload-card-data-name {
  width: 114px;
  height: 24px;
  font-family: PingFangSC-Regular;
  font-size: 16px;
  font-weight: 400;
  line-height: 24px;
  color: rgba(69, 71, 77, 1);
  text-align: left;
}

::v-deep .mds-upload-card-data {
  .mds-upload-card-data-error {
    color: #00AF5B;
    height: 24px;
    font-family: PingFangSC-Regular;
    font-size: 14px;
    font-weight: 400;
    line-height: 24px;
    text-align: left;
  }

  .mds-upload-card-data-size {

    height: 24px;
    font-family: PingFangSC-Regular;
    font-size: 14px;
    font-weight: 400;
    line-height: 24px;
    text-align: left;
  }
}
</style>

情况

增加cancelToken不生效,刷新页面

进度条太快->设置浏览器网速

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/844191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AWS 中文入门开发教学 49- S3 - 区域间复制

知识点 S3 存储桶内容在全球区域间进行复制官网 https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/replication.html 实战演习 在东京区建立存储桶 Name: woyaofuzhi启用版本控制(完成区域间复制必须开启版本控制) 在新加坡区建立存储桶 Name: woyaofuzhibac…

科技感响应式管理系统后台登录页ui设计html模板

做了一个科技感的后台管理系统登录页设计&#xff0c;并且尝试用响应式布局把前端html写了出来&#xff0c;发现并没有现象中的那么容易&#xff0c;chrome等标准浏览器都显示的挺好&#xff0c;但IE11下面却出现了很多错位&#xff0c;兼容起来还是挺费劲的&#xff0c;真心不…

【Python从入门到进阶】31、使用JSONPath解析淘票票网站地区接口数据

接上篇《30、JSONPath的介绍和使用》 上一篇我们介绍了JSONPath的基础和具体使用&#xff0c;本篇我们来具体使用JSONPath&#xff0c;来解析淘票票网站的地区接口数据。 一、引言 1、JsonPath的作用和用途&#xff1f; JsonPath是一种用于在JSON数据中进行查询和提取的表达…

Python测试框架pytest:测试用例、查找子集、参数化、跳过

Pytest是一个基于python的测试框架&#xff0c;用于编写和执行测试代码。pytest主要用于API测试&#xff0c;可以编写代码来测试API、数据库、UI等。 pytest是一个非常成熟的全功能的Python测试框架&#xff0c;主要有以下几个优点&#xff1a; 简单灵活&#xff0c;容易上手。…

3D数字孪生技术在工业制造中的应用

工业生产是现代工业生产和城市化建设的重要组成部分&#xff0c;工业生产逐渐批量化和自动化&#xff0c;利用数字孪生3D可视化技术对工厂生产的环境、设备、管道和仪表等元素在虚拟世界中模拟和重建&#xff0c;实现工业生产的管理、规划、设计和运营数字化可视化管理。 提高生…

利用openTCS实现车辆调度系统(五)openTCS WEB接口及扩展

上一篇介绍了RMI接口的使用&#xff0c;但是RMI接口只有java可以使用&#xff0c;不能前端直接调用。openTCS最新版本中新增了很多WEB接口&#xff0c;openTCS启动后即可调用。web接口文档地址 默认地址前缀为&#xff1a;localhost:55200/v1 例如&#xff0c;获取车辆列表。 …

JVM系统优化实践(24):ZGC(一)

您好&#xff0c;这里是「码农镖局」CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 截止到目前&#xff0c;算上ZGC&#xff0c;Java一共有九种类型的GC&#xff0c;它们分别是&#xff1a; 1、Serial GC 串行/作用于新生代/复制算法/响应速度优先/适用于单…

分享一个霓虹灯拨动开关

先看效果&#xff1a; 再看代码&#xff08;查看更多&#xff09;&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title> 霓虹灯拨动开关</title><style>* {border: 0;box-sizin…

【linux】安装pytorch3d

写在开头 不要看网上的博客安装&#xff0c;直接参考官方安装文档去安装。 坑 坑1&#xff1a;安装pytorch3d后torch.cuda用不了 使用下面的命令安装后 conda install pytorch3d会提示安装下面的包&#xff0c;注意pytorch和torchvision都是cpu版本的&#xff0c;这样就会…

以太网帧格式与吞吐量计算

以太网帧结构 帧大小的定义 以太网单个最大帧 6&#xff08;目的MAC地址&#xff09; 6&#xff08;源MAC地址&#xff09; 2&#xff08;帧类型&#xff09; 1500{IP数据包[IP头&#xff08;20&#xff09;DATA&#xff08;1480&#xff09;]} 4&#xff08;CRC校验&#xff…

【福建事业单位-资料分析】01 数学推理-基础-特征-非特征数列

【福建事业单位-资料分析】01 数学推理-基础-特征-非特征数列 一、基础数列总结 二、特征数列2.1 多重数列项数多&#xff0c;多于7项总结 2.2机械划分①小数;ab②大数字多&#xff08;三位数、四位数&#xff09;&#xff0c;达到一半或者以上总结 2.3分数数列大通分总结 2.4幂…

【MySQL】事务的多版本并发控制(MVCC)

目录 一、数据库并发的三种场景二、MVCC2.1 三个记录隐藏字段2.2 undo log&#xff08;撤销日志&#xff09;2.3 模拟MVCC2.3.1 模拟更新&#xff08;update&#xff09;2.3.1 模拟删除&#xff08;delete&#xff09;2.3.1 模拟插入&#xff08;insert&#xff09;2.3.1 模拟查…

bilibili的评论ip属地显示未知

现象 出于某些原因&#xff0c;我们在日常使用中的大部分平台都开启了IP地址显示&#xff0c;一般会显示当事人所在的地址&#xff0c;这其中就有一些奇怪的地址&#xff0c;&#xff08;在此不谈魔法&#xff09;就比如我最近在刷B站的时候&#xff0c;就在评论区发现了一些显…

C高级【day4】

思维导图&#xff1a; 写一个函数&#xff0c;获取用户的uid和gid并使用变量接收&#xff1a; #!/bin/bashfunction get_uid {my_uidid -umy_gidid -g }get_uid echo "当前用户的UID&#xff1a;$my_uid" echo "当前用户的GID&#xff1a;$my_gid"整理冒泡…

布隆过滤器,Guava实现布隆过滤器(本地内存),Redis实现布隆过滤器(分布式)

一、前言 利用布隆过滤器可以快速地解决项目中一些比较棘手的问题。如网页 URL 去重、垃圾邮件识别、大集合中重复元素的判断和缓存穿透等问题。不知道从什么时候开始&#xff0c;本来默默无闻的布隆过滤器一下子名声大噪&#xff0c;在面试中面试官问到怎么避免缓存穿透&#…

高级web前端开发工程师岗位的具体内容概述(合集)

高级web前端开发工程师岗位的具体内容概述1 职责&#xff1a; 1、负责前端页面开发和维护&#xff0c;并根据需求优化产品性能、用户体验、交互效果及各种主流浏览器以及各类型移动客户端的兼容适配工作; 2、配合产品经理和UI设计师&#xff0c;通过各种前端技术手段&#xf…

前端学习---vue2--指令修饰符详解

写在前面&#xff1a; 前端感觉系统学起来还行&#xff0c;我也不晓得我是咋快速入门1个月就开始看实习公司代码的。然后现在开始系统复习&#xff0c;然后感觉有的封装的还可以&#xff0c;不过就是我不晓得&#xff0c;像这个指令修饰符&#xff0c;其实说逻辑难写&#xff…

阿里、字节等大厂面试经历,过于真实了...

我一直想写点什么&#xff0c;但当时我觉得在得到几家大厂的offer之后再谈会更有说服力。但从目前的结果来看&#xff0c;结果并不十分令人满意。去年年底&#xff0c;我陆续面试了一些公司&#xff0c;比如迅雷、OPPO、阿里巴巴。当时&#xff0c;我并没有做任何准备&#xff…

ADS版图画封装学习笔记

ADS版图画封装 因为晶体管ATF54143在ADS中是没有封装的&#xff0c;所以要在ADS中画ATF54143的封装&#xff0c;操作步骤如下&#xff1a; 在ADS中新建layout&#xff0c;命名为ATF54143_layout&#xff0c; 根据datasheet知道封装的大小&#xff0c;进行绘制 在layout的con…

内网横向移动—资源约束委派

内网横向移动—资源约束委派 1. 资源约束委派1.1. 基于资源的约束委派的优势1.2. 约束性委派和基于资源的约束性委派配置的差别1.3. 利用条件1.3.1. 什么用户能够修改msDS-AllowedToActOnBehalfOfOtherIdentity属性1.3.2. 将机器加入域的域用户 2. 案例操作2.1. 获取目标信息2.…