第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

    <samp id="9lurr"></samp>
    為了賬號安全,請及時綁定郵箱和手機立即綁定

    【九月打卡】第8天 完成上傳組件-支持拖拽上傳和代碼重構(gòu)

    標簽:
    Vue.js

    课程名称web前端架构师

    课程章节:第11周 第五章

    主讲老师:张轩

    课程内容:完成上传组件-支持拖拽上传 代码重构

    拖拽上传

    分析

    拖拽区域触发事件:

    • 拖拽元素进入区域时触发dragenter;
    • 拖拽元素进入区域后悬停触发dragover;
    • 拖拽元素离开区域时触发dragleave;
    • 拖拽元素放置时触发 drop, 此时我们可以发送 上传文件请求

    在拖拽元素进入区域悬停时,我们可以给拖拽区域元素一个 class is-draging ,当离开拖拽区域时,就移除 is-draging 这个class。

    下面编写触发拖拽事件的代码

    // 拖拽元素进入区域或离开区域时触发。
    // over为true 为进入区域悬停,false 时为离开拖拽区域
    function handleDrag (e: DragEvent, over:boolean) {
      e.preventDefault()
      e.stopPropagation()
      dragOver.value = over
    }
    
    // 拽元素放置时触发
    function handleDrop (e: DragEvent) {
      e.preventDefault()
      e.stopPropagation()
      // is
      if (e.dataTransfer) {
        // 发送请求 
        uploadFile(e.dataTransfer.files)
      }
      dragOver.value = false
    }
    

    编写代码实现

    首先我们在使用组件时,需要用户传递一个参数 drag ,是否需要拖拽上传

    interface Props{
      beforeUpload?: (file: File) => boolean | Promise<boolean>
      drap?: boolean
      name?: string
    }
    

    事件处理, 如果需要 拖拽上传,添加拖拽事件

    let events: {[key: string]:(e: any) => void} = {
      click: triggerUpload
    }
    if (props.isDrag) {
      events = {
        ...events,
        dragover: (e: DragEvent) => { handleDrag(e, true) },
        dragleave: (e: DragEvent) => { handleDrag(e, false) },
        drop: handleDrop
      }
    }
    

    给元素绑定事件和class, 事件绑定通过 v-on 绑定多个事件

    <div
      class="choose-flle"
      :class="{ 'is-draging': drag && dragOver }"
      v-on="events"
    >
    ...
    </div>
    

    编写测试代码

    it('test drag upload', async () => {
      const wrapper = mount(UploadFile, {
        props: {
          drag: true
        }
      })
      const uploadFileEl = wrapper.get('.choose-file')
      await uploadFileEl.trigger('dragover')
      expect(uploadFileEl.classes()).toContain('is-draging')
      await uploadFileEl.trigger('dragleave')
      expect(uploadFileEl.classes()).not.toContain('is-draging')
      await uploadFileEl.trigger('drop', {
        dataTransfer: {
          files: [testFile]
        }
      })
      request.mockResolvedValueOnce({ status: 'success' })
      expect(request).toHaveBeenCalled()
      await flushPromises()
      expect(wrapper.findAll('li').length).toBe(1)
    })
    

    这里需要注意过是触发 drop 事件. https://test-utils.vuejs.org/api/#trigger

    trigger 方法第一个参数是事件名称,第二个参数需要传递的参数

    查看下我们需要传递的参数格式

    function handleDrop (e: DragEvent) {
      e.preventDefault()
      e.stopPropagation()
      // is
      if (e.dataTransfer) {
        uploadFile(e.dataTransfer.files)
      }
      dragOver.value = false
    }
    

    知道需要传递的参数格式就可以触发 drop 事件了

    const testFile = new File(['foo'], 'foo.txt', {
      type: 'text/plain'
    })
    await uploadFileEl.trigger('drop', {
      dataTransfer: {
        files: [testFile]
      }
    })
    

    代码重构

    有时候我们不需要选择完图片后自动上传,这个就需要将我们之前上传文件给提出来

    之前上传文件的代码

    async function uploadFile (files: FileList) {
      const uploadFile = files[0]
      const formData = new FormData()
      formData.append(props.name, uploadFile)
      const fileObj = reactive<FileItem>({
        id: '' + Date.now(),
        name: uploadFile.name,
        size: uploadFile.size,
        status: 'loading',
        raw: uploadFile
      })
      try {
        fileObj.status = 'loading'
        loadStatus.value = 'loading'
        if (props.beforeUpload) {
          const res = await props.beforeUpload(uploadFile)
          if (!res) {
            return
          }
        }
        uploadFiles.push(fileObj)
        const res = await request<{code: number}>(formData)
        fileObj.status = 'success'
        loadStatus.value = 'success'
        if (res.code === 0) {
          console.log('上传成功')
        }
      } catch (e) {
        fileObj.status = 'fail'
        loadStatus.value = 'fail'
      } finally {
        (fileRef.value as HTMLInputElement).value = ''
      }
    }
    

    上传文件的步骤

    • 准备
      • 执行 beforeUpload 钩子,是否需要往下执行
    • 将文件添加到 fileList 中
    • 判断是否需要自动上传
      • 需要就执行文件上传
      • 不需要什么也不用做
    • 给外部暴露一个手动上传文件的方法
    <script setup lang="ts">
    import { reactive, ref, computed } from 'vue'
    import request from '@/utils/request'
    type UploadStatus = 'ready' | 'loading' | 'success' | 'fail'
    interface FileItem {
      id: string
      name: string
      size: number
      status:UploadStatus
      raw: File
      res?: any
    }
    interface Props{
      beforeUpload?: (file: File) => boolean | Promise<boolean>
      drag?: boolean
      name?: string
      autoUpload?: boolean
    }
    const fileRef = ref<HTMLInputElement | null>(null)
    const dragOver = ref(false)
    const props = withDefaults(defineProps<Props>(), {
      drag: false,
      beforeUpload: () => true,
      name: 'file',
      autoUpload: false
    })
    // const uploadStatus = ref<UploadStatus>('ready')
    const uploadFileList = reactive<FileItem[]>([])
    const isUploading = computed(() => uploadFileList.some(file => file.status === 'loading'))
    const loadStatus = ref<UploadStatus>('ready')
    
    async function handleChangeFile (e: Event) {
      const target = e.target as HTMLInputElement
      const files = target.files
      if (files) {
        uploadReady(files[0])
      }
    }
    function addFileToList (file: File) {
      if (!file) return
      const fileObj = reactive<FileItem>({
        id: '' + Date.now(),
        name: file.name,
        size: file.size,
        status: 'ready',
        raw: file
      })
      uploadFileList.push(fileObj)
      if (props.autoUpload) {
        uploadFile(file, fileObj)
      }
    }
    async function uploadReady (file: File) {
      if (props.beforeUpload) {
        const res = await props.beforeUpload(file)
        if (!res) {
          return false
        }
      }
      addFileToList(file)
    }
    // 给外部暴露一个手动上传文件的方法
    function uploadFiles () {
      uploadFileList.filter(file => file.status !== 'success').forEach(file => uploadFile(file.raw, file))
    }
    defineExpose({
      uploadFiles
    })
    async function uploadFile (file: File, fileObj: FileItem) {
      const formData = new FormData()
      formData.append(props.name, file)
      try {
        loadStatus.value = fileObj.status = 'loading'
        const res = await request<{code: number}>(formData)
        fileObj.status = loadStatus.value = 'success'
        if (res.code === 0) {
          console.log('上传成功')
        }
      } catch (e) {
        fileObj.status = loadStatus.value = 'fail'
      } finally {
        (fileRef.value as HTMLInputElement).value = ''
      }
    }
    
    function handleDrag (e: DragEvent, over:boolean) {
      e.preventDefault()
      e.stopPropagation()
      dragOver.value = over
    }
    function handleDrop (e: DragEvent) {
      e.preventDefault()
      e.stopPropagation()
      if (e.dataTransfer) {
        uploadReady(e.dataTransfer.files[0])
      }
      dragOver.value = false
    }
    let events: {[key: string]:(e: any) => void} = {
      click: triggerUpload
    }
    if (props.drag) {
      events = {
        ...events,
        dragover: (e: DragEvent) => { handleDrag(e, true) },
        dragleave: (e: DragEvent) => { handleDrag(e, false) },
        drop: handleDrop
      }
    }
    function triggerUpload () {
      fileRef.value?.click()
    }
    function delFile (index: number) {
      uploadFileList.splice(index, 1)
    }
    </script>
    
    <template>
      <div
        class="choose-file"
        :class="{ 'is-draging': drag && dragOver }"
        v-on="events"
      >
        <input
          type="file"
          name="file"
          ref="fileRef"
          :style="{display: 'none'}"
          @change="handleChangeFile"
        >
        <div>
          <slot
            v-if="isUploading"
            name="loading"
          >
            <button>正在上传</button>
          </slot>
          <slot
            v-else-if="loadStatus==='success'"
            name="uploaded"
            :uploaded-data="{status: loadStatus}"
          >
            <button>点击上传</button>
          </slot>
          <slot v-else>
            <button>点击上传</button>
          </slot>
        </div>
      </div>
      <ul>
        <li
          v-for="(file,index) in uploadFileList"
          :key="file.id"
          :class="'upload-'+ file.status"
        >
          <span class="filename">{{ file.name }}</span>
          <button
            class="delete-icon"
            @click="delFile(index)"
          >
            del
          </button>
        </li>
      </ul>
    </template>
    

    图片描述

    點擊查看更多內(nèi)容
    TA 點贊

    若覺得本文不錯,就分享一下吧!

    評論

    作者其他優(yōu)質(zhì)文章

    正在加載中
    • 推薦
    • 評論
    • 收藏
    • 共同學(xué)習(xí),寫下你的評論
    感謝您的支持,我會繼續(xù)努力的~
    掃碼打賞,你說多少就多少
    贊賞金額會直接到老師賬戶
    支付方式
    打開微信掃一掃,即可進行掃碼打賞哦
    今天注冊有機會得

    100積分直接送

    付費專欄免費學(xué)

    大額優(yōu)惠券免費領(lǐng)

    立即參與 放棄機會
    微信客服

    購課補貼
    聯(lián)系客服咨詢優(yōu)惠詳情

    幫助反饋 APP下載

    慕課網(wǎng)APP
    您的移動學(xué)習(xí)伙伴

    公眾號

    掃描二維碼
    關(guān)注慕課網(wǎng)微信公眾號

    舉報

    0/150
    提交
    取消