Как сделать предпросмотр изображения перед загрузкой на VueJS

Например, вы создаете приложение, в котором ваши пользователи могут загружать изображения в свои профили. Вероятно, вы хотите просмотреть эти изображения перед загрузкой - как правило, это хороший способ взаимодействия с вашим интерфейсом.

В этом небольшом уроке мы научимся писать униаерсальный переиспользуменный компонет на Vue JS для подобных целей.

Шаблон компонента

Для начала давайте создадим Vue шаблон нашего будущего компанента:

<template id="image-input-template">
    <div class="Image-input">
        <div class="Image-input__image-wrapper">
            <i v-show="! imageSrc" class="icon fa fa-picture-o"></i>
            <img v-show="imageSrc" class="Image-input__image" :src="imageSrc">
        </div>

        <div class="Image-input__input-wrapper">
            Choose
            <input @change="previewThumbnail" class="Image-input__input" name="thumbnail" type="file">
        </div>
    </div>
</template>

Здесь нам важны только два пунтка, это свойствр imageSrc загружаемого изображения и событие @change="previewThumbnail" которое мы повесили на поле file input, которое будет срабатывать каждый раз когда мы будем загружать изображение.

Компонент

Давайте теперь напишем сам компонент:

Vue.component('image-input', {
    template: '#image-input-template',

    props: [ 'imageSrc' ],

    methods: {
        previewThumbnail: function(event) {
            var input = event.target;

            if (input.files && input.files[0]) {
                var reader = new FileReader();
                var vm = this;

                reader.onload = function(e) {
                    vm.imageSrc = e.target.result;
                }

                reader.readAsDataURL(input.files[0]);
            }
        }
    }
});

Сначала мы указываем компоненту на ранее созданный шаблон и свойство которое он будет принимать — imageSrc. Затем выполняем обработчик событий, который использует объект FileReader для доступа к данным изображения хранящегося в DOM элементе поля, что бы достать от туда данные для предпросмотра.

Если вам кажется странным, почему мы определили imageSrc как свойство, а не как набор данных, это потому, что в некоторых случаях нам может понадобиться отображать уже загруженные  ранее изображения (например, когда пользователь редактирует свой профиль).

Стили CSS

Наш компонент готов к использованию, однако для полного счастья нам необходимо стилизовать его при помощи CSS подогнав под общий дизайн вашего приложения. Ниже я приожу мой пример кода, который вы можете извенить на ваше усмотрение.

.Image-input {
    display: flex;
}

.Image-input__image-wrapper {
    flex-basis: 80%;
    height: 150px;
    flex: 2.5;
    border-radius: 1px;
    margin-right: 10px;
    overflow-y: hidden;
    border-radius: 1px;
    background: #eee;
    justify-content: center;
    align-items: center;
    display: flex;
}

.Image-input__image-wrapper > .icon {
    color: #ccc;
    font-size: 50px;
    cursor: default;
}

.Image-input__image {
    max-width: 100%;
    border-radius: 1px;
}

.Image-input__input-wrapper {
    overflow: hidden;
    position: relative;
    background: #eee;
    border-radius: 1px;
    float: left;
    flex: 1;
    display: flex;
    justify-content: center;
    align-items: center;
    color: rgba(0,0,0,0.2);
    transition: 0.4s background;
}

.Image-input__input-wrapper:hover {
    background: #e0e0e0;
}


.Image-input__input {
    cursor: inherit;
    display: block;
    font-size: 999px;
    min-height: 100%;
    opacity: 0;
    position: absolute;
    right: 0;
    text-align: right;
    top: 0;
    cursor: pointer;
}

Осталось лишь разместить данный компонент в шаблоне вашего приложения:

<image-input image-src=""></image-input>

И вызвать экземпляр root Vue

new Vue({
    el: 'body'
});

Ну вот и всё, теперь у вас есть переиспользуемый компонент для загрузки изображений на Vue js.