This paper mainly introduces how to use native js, through the way of object-oriented implement a preview file upload component, the component to which FileReader file on the front end of parsing, preview, read the schedule, and other functions, and exposed the corresponding API to implement custom demand, such as file upload, progress monitoring, custom styles, Read successful callback and so on.

The component design architecture is as follows:

The core knowledge points involved are as follows:

  1. Closures: Reduce variable contamination and shorten the scope of variable lookup
  2. Self-executing function
  3. File API: Reads, parses, and monitors file events
  4. DocumentFragment API: Used to optimize DOM operations
  5. Minix: For object mixing
  6. Regular expression: matches the file type
  7. Class: class component

Making the address

Use native JS to implement a file upload preview component with progress monitoring

The Demo presentation

Use:

<div id="test"></div>
<script src="./js/xjFile.js"></script>
<script>
    new xjFile({
        el: '#test'.// If not, the body will be hung directly by default
        accept: 'image/png'./ / is optional
        clsName: 'xj-wrap'./ / is optional
        beforeUpload: function(e) { console.log(e) }, / / is optional
        onProgress: function(e) { console.log(e) }, / / is optional
        onLoad: function(e) { console.log(e) }, / / is optional
        onError: function(e) { console.error('File read error', e) } / / is optional
    });
</script>
Copy the code

The CSS code:

.xj-wrap {
            position: relative;
            display: inline-block;
            border: 1px dashed # 888;
            width: 200px;
            height: 200px;
            border-radius: 6px;
            overflow: hidden;
        }
        .xj-wrap::before {
            content: '+';
            font-size: 36px;
            position: absolute;
            transform: translate(50%, 50%);left: 50%;
            top: 50%;
            color: #ccc;
        }
        .xj-wrap .xj-pre-img {
            width: 100%;
            height: 100%;
            background-repeat: no-repeat;
            background-position: center center;
            background-size: 100%;
        }
        .xj-file {
            position: absolute;
            left: 0;
            right: 0;
            bottom: 0;
            top: 0;
            opacity: 0;
            cursor: pointer;
        }
Copy the code

Js code:

(function(win, doc){
    function xjFile(opt) {
        var defaultOption = {
            el: doc.body,
            accept: The '*', // The format is as follows'image/jpg,image/gif'The clsName:'xj-wrap',
            beforeUpload: function(e) { console.log(e) },
            onProgress: function(e) { console.log(e) },
            onLoad: function(e) { console.log(e) },
            onError: function(e) { console.error('File read error', e) } }; / / get the domif(opt.el) {
            opt.el = typeof opt.el === 'object' ? opt.el : document.querySelector(opt.el);
        }

        this.opt = minix(defaultOption, opt);
        this.value = ' ';
        this.init();
    }

    xjFile.prototype.init = function() {
        this.render();
        this.watch();
    }

    xjFile.prototype.render = function() {
        var fragment = document.createDocumentFragment(),
            file = document.createElement('input'),
            imgBox = document.createElement('div');
        file.type = 'file';
        file.accept = this.opt.accept || The '*';
        file.className = 'xj-file';
        imgBox.className = 'xj-pre-img'; // Insert fragment fragment. AppendChild (file); fragment.appendChild(imgBox); // Set class this.opt.el.className = this.opt.clsname; this.opt.el.appendChild(fragment); } xjFile.prototype.watch =function() {
        var ipt = this.opt.el.querySelector('.xj-file');
        var _this = this;
        ipt.addEventListener('change', (e) => { var file = ipt.files[0]; // Assign a value to the component _this.value = file; var fileReader = new FileReader(); // Filereader.onloadStart = is triggered when a file is readfunction(e) {
                if(_this.opt.accept ! = =The '*' && _this.opt.accept.indexOf(file.type.toLowerCase()) === -1) {
                    fileReader.abort();
                    _this.opt.beforeUpload(file, e);
                    console.error('Wrong file format', file.type.toLowerCase()); }} / / read complete trigger event. FileReader onload = (e) = > {var imgBox = this. Opt. El. QuerySelector ('.xj-pre-img');
                if(isImage(file.type)) {
                    imgBox.innerHTML = ' ';
                    imgBox.style.backgroundImage = 'url(' + fileReader.result + ') ';
                } else{ imgBox.innerHTML = fileReader.result; } imgBox.title = file.name; this.opt.onLoad(e); } filereader.onError = (e) => {this.opt.onError(e); } filereader.onprogress = (e) => {this.opt.onprogress (e); } isImage(file.type) ? fileReader.readAsDataURL(file) : fileReader.readAsText(file); },false); } / / clean up ipt and component values, support chain calls xjFile. Prototype. ClearFile =function() {
        this.opt.el.querySelector('.xj-file').value = ' ';
        this.value = ' ';
        returnThis} // Simple object mixfunction minix(source, target) {
        for(var key in target) {
            source[key] = target[key];
        }
        return source} // Check the image typefunction isImage(type) {
        var reg = /(image\/jpeg|image\/jpg|image\/gif|image\/png)/gi;
        return reg.test(type)} // Mount the method to the window win.xjfile = xjFile; })(window, document);Copy the code

Class Edition (Post-planning)

Class version is also very simple, the general framework is as follows, interested friends can achieve yo ~

class XjFile {
    constructor(opt) {

    }

    init() {

    }

    watch() {

    }

    render() {

    }

    clearFile() {

    }

    minix(source, target) {
        
    }

    isImage(type) {
        
    }
}
Copy the code

conclusion

This component still needs to be improved, and will be updated and optimized slowly in the later use. Your valuable suggestions are welcome.

More recommended

  • How to use gulP4 development project scaffolding

  • Developing travel List with Angular8 and Baidu Maps API

  • Js basic search algorithm implementation and 1.7 million data under the performance test

  • How to make front-end code 60 times faster

  • Front End Algorithm series array deweighting

  • How to control CSS sense of direction

  • Vue Advanced Advanced series – Play with Vue and vuex in typescript

  • In the first three years, talk about the top five books worth reading

Finally, more technical quality articles and technical data are welcome to pay attention to the “Interesting Talk Front Public Account” :