VUE使用element-ui的upload組件自定義文件列表

emmm我又來了๑乛◡乛๑css

餓了麼上傳組件的文件列表filelist有個刪除功能,我看源代碼它是直接刪除,並不會提示。issue上也有很多開發者提過這個問題,開發組仍是建議本身寫(想偷懶都不行……)
除了複寫文件列表外,還加了一個上傳狀態的顯示。vue

先上效果圖:
文件列表git

懸浮時的效果:
鼠標懸浮可點擊放大刪除github

上傳時的效果:
圖片描述ajax

如下測試在vue(v2.5) + vue-router(v3.0) + element-ui(v2.0)環境下進行,一些細節(如icon)會與上述圖片不相符。因此每一個步驟都加個圖片=。=vue-router

步驟一:卡片化

其實就是重寫樣式,寫個相似el-card組件的樣式element-ui

<template>
    <div class="img-list">
        <div class="img-content" v-for="(item,key) in imagelist" :key="key">
            <img :src="item.url">
            <div class="name">
                <div>{{ item.name }}</div>
                <el-button type="text" @click="handleFileName(item,key)">修更名字</el-button>
            </div>
<!-- 刪除icon -->
            <div class="del">
                <i @click="handleFileRemove(item,key)" class="el-icon-delete2"></i>
            </div>
<!-- 放大icon -->
            <div class="layer" @click="handleFileEnlarge(item.url)">
                <i class="el-icon-view"></i>
            </div>
        </div>
    </div>
</template>
<script>
export default{
    name: 'upload-list',
    data(){
        return {
            imagelist: [{
                url: 'http://img.hb.aicdn.com/723f8754f412debce188626d09cc0a1b2be6b7a6751a3-ICEp1E_fw658',
                name: 'lemon'
            },{
                url: 'http://img.hb.aicdn.com/38ab9e558bcba041be979f03bfd31bd67bf1e6f35815a-8PD8Eo_fw658',
                name: 'lemon2'
            },{
                url: 'http://img.hb.aicdn.com/0cd0dcc93f5b918e191dd84791101435136c7f9811e31-LRzYAQ_fw658',
                name: 'lemon3'
            }]
        }
    },
    methods: {
        handleFileEnlarge(_url){//放大圖片
            console.log(_url)
        },
        handleFileName(file,i){//修更名字
            console.log(file,i)
        },
        handleFileRemove(file,i){//刪除圖片
            console.log(file,i)
        }
    }
}
</script>

放大按鈕和刪除按鈕只有鼠標懸浮才顯示:json

*{
    box-sizing: border-box;
}
.img-list{
    overflow:hidden;
    width:100%;
}
.img-list .img-content{
    float:left;
    position:relative;
    display:inline-block;
    width:200px;
    height:270px;
    padding:5px;
    margin:5px 20px 20px 0;
    border:1px solid #d1dbe5;
    border-radius:4px;
    transition:all .3s;
    box-shadow:0 2px 4px 0 rgba(0,0,0,.12), 0 0 6px 0 rgba(0,0,0,.04);
}
.img-list .img-content img{
    display:block;
    width:100%;
    height:190px;
    margin:0 auto;
    border-radius:4px;
}
.img-list .img-content .name{
    margin-top:10px;
}
.img-list .img-content .name>div{
    width:90%;
    text-overflow:ellipsis;
    overflow:hidden;
    height:25px;
    line-height:25px;
}
.img-list .img-content:hover .del,
.img-list .img-content:hover .layer{
    opacity:1;
}
.img-list .img-content .del,
.img-list .img-content .layer{
    opacity:0;
    transition:all .3s;
}
.img-list .img-content .del{
    position:absolute;
    bottom:10px;
    right:10px;
    color:#8492a6;
    cursor:pointer;
    font-size:1.1em;
}
.img-list .img-content .layer{
    position:absolute;
    left:0;
    right:0;
    top:0;
    height:200px;
    color:#fff;
    text-align:center;
    z-index:5;
    background-color:rgba(0,0,0,.4);
}
.img-list .img-content .layer i{
    font-size:1.6em;
    margin-top:80px;
}

效果圖:
步驟一效果圖跨域

步驟二:放大

這個操做很簡單,用el-dialog組件app

<div class="img-list">
    ...
    <el-dialog title="" :visible.sync="isEnlargeImage" size="large" :modal-append-to-body="false" top="8%" width="60%">
        <img @click="isEnlargeImage = false" style="width:100%;" :src="enlargeImage">
    </el-dialog>
</div>
<script>
export default{
    data(){
        return {
            isEnlargeImage: false,//放大圖片
            enlargeImage: '',//放大圖片地址
        }
    },
    methods: {
        handleFileEnlarge(_url){//放大圖片
            console.log(_url)
            if(_url){
                this.enlargeImage = _url;
                this.isEnlargeImage = !this.isEnlargeImage;
            }
        }, 
    }
}
</script>

放大效果圖

步驟三:刪除和修更名字

emmm仍是個簡單的操做

handleFileRemove(file,i){//刪除圖片
    console.log(file,i)
    if(!file.url){
        return false;
    }
    let that = this;
    this.$confirm('是否刪除此附件?','提示',{
        confirmButtonText: '肯定',
        cancelButtonText: '取消',
        type: 'warning'
    }).then(() => {
        //可添加ajax
        this.$message.success("刪除成功")
        this.$message({
            type: 'success',
            message: '刪除成功',
            onClose: () => {
                that.imagelist.splice(i,1)
            }
        })
    }).catch((meg) => console.log(meg))
},
handleFileName(file,i){//修更名字
    console.log(file,i)
    let that = this;
    this.$prompt("請輸入新文件名:","提示:",{
        confirmButtonText: '肯定',
        cancelButtonText: '取消'
    }).then(({ value }) => {
        console.log(value)
        if(!value){
            return false;
        }
        //可添加ajax
        this.$message.success("操做成功")
        that.imagelist[i].name = value
    }).catch(() => {})
},

效果圖:
從新命名效果圖

步驟四:上傳進程

emmm其實這篇文章的重點在這兒。

css:

<style>
...
.img-list .img-upload{
    float:left;
    width:200px;
    height:270px;
    display:table;
    text-align:center;
}
.img-list .uploader{
    width:100%;
    display:table-cell;
    vertical-align:middle;
}
</style>
<template>
...
    <div class="img-upload">
        <el-upload class="uploader" accept="image/*"
          ref="upload"
          list-type="picture-card"
          :show-file-list="false"
          :action="params.action"
          :data="params.data"
          :on-change="uploadOnChange"
          :on-success="uploadOnSuccess"
          :on-error="uploadOnError"
          :on-progress="uploadOnProgress">
              <el-button type="primary">點擊上傳</el-button>
        </el-upload>
    </div>
</template>
<script>
...
data(){
    return {
        params: {
            action: 'http://jsonplaceholder.typicode.com/posts/',
            data: {}
        }
    }
},
...
methods: {
    uploadOnProgress(e,file){//開始上傳
        console.log(e.percent,file)
    },
    uploadOnChange(file){
        console.log("——————————change——————————")
        // console.log(file)
        if(file.status == 'ready'){
            console.log("ready")
        }else if(file.status == 'fail'){
            this.$message.error("圖片上傳出錯,請刷新重試!")
        }
    },
    uploadOnSuccess(e,file){//上傳附件
        console.log("——————————success——————————")
        this.$message.success("上傳成功")
    },
    uploadOnError(e,file){
        console.log("——————————error——————————")
        console.log(e)
    },
}
</script>

插播一則tips:在項目中文件是直接上傳到阿里雲,上傳參數data會動態變化。可是因爲自動上傳一直出錯(上傳參數data有些關鍵字不存在),後來用手動上傳倒是可行。因此測試了半天才採用如下方式:

<el-upload :auto-upload="false"></el-upload>

methods:

uploadOnChange(file){
    if(file.status == 'ready'){
        this.params.data = {
            //change
        }
        this.$nextTick(() => {
            this.$refs.upload.submit();
        })
    }
}

加個上傳加載的過程,el-progress組件剛好適用
css:

.img-list .img-progress{
    text-align:center;
    padding-top:50px;
}
<div v-if="!pass && progress !== 0" class="img-content img-progress">
    <el-progress type="circle" :percentage="progress" :status="proStatus"></el-progress>
</div>

data:

data(){
    return {
        progress: 0,//上傳進度
        pass: null,//是否上傳成功
    }
},
computed: {
    proStatus(){//上傳狀態
        if(this.pass){
            return 'success'
        }else if(this.pass == false){
            return 'exception'
        }else{
            return ''
        }
    }
},

methods:

uploadOnProgress(e,file){//開始上傳
    console.log(e.percent,file)
    this.progress = Math.floor(e.percent)
},
uploadOnChange(file){
    console.log("——————————change——————————")
    // console.log(file)
    if(file.status == 'ready'){
        console.log("ready")
        //重置progress組件
        this.pass = null;
        this.progress = 0;
    }else if(file.status == 'fail'){
        this.$message.error("圖片上傳出錯,請刷新重試!")
    }
},
uploadOnSuccess(e,file){//上傳附件
    console.log("——————————success——————————")
    this.pass = true;
    this.$message.success("上傳成功")
    this.imagelist.push({
        url: file.url,
        name: '新增圖片'
    })
},
uploadOnError(e,file){
    console.log("——————————error——————————")
    console.log(e)
    this.pass = false;
},

本來是用this.progress控制status,可是後來發現及時上傳進度100%也不必定上傳成功,因此改用this.pass。用餓了麼的上傳地址偶爾會跨域報錯,上傳多幾回又成了=。=

圖片描述

圖片描述

Github地址:點我點我點我(component/uploadlist.vue)

相關文章
相關標籤/搜索