Как я в 15 лет написал свой первый jQuery плагин и как их создавать

Здравствуйте! Я живу в Узбекистане и самостоятельно изучаю веб разработку вот уже третий год. За это время я научился изобретать велосипед самостоятельно решать проблемы, с которыми я сталкивался. Одна из таких проблем и ее решение будет описана здесь. Надеюсь вам будет интересно.



Почему мне пришлось писать плагин?


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


Поэтому поискал плагины для вставки слайдера, но я так и не нашел подходящий плагин, который бы устраивал меня по всем критериям: mobile-friendly, с remote-controllers, чтобы весь код умещался в одном файле, компактный код и чтобы были все опции по умолчанию для слайдеров.


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


А второй причиной написания плагина является самообучение и развитие. Создав плагин, я набрался бы опыта в создании плагинов и модулей. А эти знания могли бы мне помочь в будущем.


Почему я использовал jQuery?


Хотя я могу написать код в ванильном JavaScript-е, мне иногда все же удобнее работать с jQuery )


Как же создавать плагины для jQuery?


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


После того, как вы определитесь с выбором проблем, вы можете приступать к разработке.


Шаблон


Первым делом, подключите jQuery к своей странице:


<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>

Потом, создайте новый файл, и добавьте этот код:


(function($) {
    $.fn.plugtest = function(options) {

    }
})(jQuery)

Это самовызывающаяся функция для глобализации plugtest. Да, мы назовем наш плагин plugtest. $.fn нужен чтобы мы могли вызвать эту функцию на какой-либо элемент:


<div></div>

и снизу в script элементе:


$('div').plugtest({})

Здесь, в качестве параметра options будет пустой объект.


Действие с this


Если сейчас я добавлю console.log(this) в эту функцию, то на консоль выйдет именно этот элемент:


(function($) {
    $.fn.plugtest = function(options) {
        console.log(this)
    }
})(jQuery)

выводится this

Настройки


Теперь, мы можем поработать над настройками плагина:


(function($) {
        $.fn.plugtest = function(options) {
            let o = $.extend({
                greeting: 'Привет!'
            }, options)
            console.log(this[0].tagName + ' говорит ' + o.greeting)
        }
    })(jQuery)

Функция extend «скрещивает» два объекта в один. Теперь поменяем greeting в нашей инициализации:


$('div').plugtest({
        greeting: "Здравствуй!"
})

Открываем консоль и видим это:


DIV говорит здравствуй!

Можно ещё добавить функцию возврата, чтобы возвращать в переменную все элементы:


let test = $('div').plugtest({
        greeting: "Здравствуй!"
})

(function($) {
    $.fn.plugtest = function(options) {
        let o = $.extend({
            greeting: 'Привет!'
        }, options)
        return this.each(function() {
            console.log(this[0].tagName + ' говорит ' + o.greeting)
        })
    }
})(jQuery)

Вот, мы написали самый простой плагин, который говорит что-то от имени элемента. Вы можете добавить еще несколько опций и немного поиграться. Если вы думали о создании своего плагина, не ждите начинайте разработку!


Slibox в github-e:


Здесь живет Slibox


Дополнительно


У меня есть опыт по созданию API и приложений на PHP, на фреймворках Laravel и Vue, имею опыт работы с node.js, express.js. Также мне интересно создавать кросс-платформенные десктопные приложения и люблю писать ванильный JavaScript для лучшего контроля приложений. Мне одинаково интересно задачи фронтэнда так и бекэнда.


Хотелось бы удаленно стажироваться в сплоченной команде под наблюдением ментора, где бы пригодились мои навыки (владения световым мечом). Спасибо за советы и мнения.

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 21

    +6
    Это точно не перевод статьи этак 10-летней давности?
      +7
      Это вы так решили пропиариться и найти стажировку?

      1. Вы опоздали с такой статьёй лет на 10 точно. На 10!!! Карл!!!
      2. Это плагин? Я уж ожидал тут увидеть супер плагин, ну в 2020 году то. А тут hello world на jquery
      3. Чего такого умеет jQuery в 2020, что вы предпочитаете его, а не ванильный JavaScript?
      4. Сравните вашу статью и вот эту, от 2012 года. habr.com/ru/post/158235
        +3
        А где, собственно, разбор кода как написать слайдер, на который дана ссылка? Зачем читателям простейшая информация из документации?

        «Slibox — it's a very fast, powerful, tiny slider. Mobile-friendly, easy to use», код — github.com/GitCodeDestroyer/Slibox/blob/master/src/slibox.js. Красивое описание и трешовая реализация — бич опенсорс разработки, которая по моему опыту на 98% состоит из подобного. А статья — бесполезный самопиар, минус.
          0
          Вы невнимательно прочли заголовок:
          Как я в 15 лет написал свой первый jQuery-плагин и как их создавать.

          В статье я показал как написать jQuery-плагин, а не слайдер. Все честно?

          По коду, можете показать что не так, как можно улучшить мой код и стиль?
            0

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


            Написал несколько комментариев по общим темам, ведь данное сообщество — не только чтобы хейтить и пиариться, но и помогать друг другу) Небольшую часть отрефакторил, но полноценная переработка — уже ваша зона ответственности. Кроме этого можно написать еще про множество моментов, но по более чистой версии:


            Скрытый текст
            !function ($) {
                /**
                 * Все эти функции получаются в глобальной области видимости jQuery - это ненужно и может вступить в конфликт
                 * с другими плагинами. Нужно оформить просто в функциях, кроме $.fn.slibox
                 * Также лучше по-максимуму избегать анонимных функций, чтобы была возможность делать рекурсию и видеть
                 * семантичный стек вызовов
                 *
                 */
            
                $.fn.slideTo = function (slideTo, fromTimer = false) {
                    this.each(function () {
                        let sliderId = '#' + this.id,
                            slidesCount = $(sliderId).data("sb-slides-count");
            
                        if ($(sliderId).data("sb-carousel") || fromTimer) {
                            if (slideTo > slidesCount) {
                                slideTo = 1;
                            } else if (slideTo < 1) {
                                slideTo = slidesCount
                            }
                        }
            
                        if (fromTimer) {
                            if ($(sliderId).data('sb-timer')) {
                                $(sliderId + ' .sb-timer').removeClass('sb-timer-animate');
            
                                setTimeout(function () {
                                    $(sliderId + ' .sb-timer').addClass('sb-timer-animate');
                                }, 100);
            
                                clearInterval(this.slidingInterval);
            
                                this.slidingInterval = setInterval(function () {
                                    if (!$(sliderId)[0].paused) {
                                        // console.log($(sliderId).data('sb-timer-time') / 100, $(sliderId)[0].time);
                                        if ($(sliderId).data('sb-timer-time') / 100 != $(sliderId)[0].time - 1) {
                                            $(sliderId)[0].time++;
                                        } else {
                                            if (($(sliderId).data('sb-timer-carousel') || $(sliderId).data('sb-active-slide') < $(sliderId).data('sb-slides-count'))) {
                                                $(sliderId).slideToNext();
                                            } else {
                                                $(sliderId + ' .sb-timer').css('animation-play-state', 'paused');
                                            }
                                            $(sliderId)[0].time = 0;
                                        }
                                    }
                                }, 100);
                            }
                        }
            
                        if (slideTo) {
                            $(sliderId).toggleClass('sb-last-slide', slideTo == $(sliderId).data('sb-slides-count'));
                            $(sliderId).data("sb-active-slide", slideTo);
                            $(sliderId + " .sb-slide").removeClass("active");
                            $(sliderId + " .sb-slide:nth-of-type(" + slideTo + ")").addClass("active");
                            $(sliderId + " .sb-controller").removeClass("active"), $(sliderId + " .sb-controller:nth-of-type(" + slideTo + ")").addClass("active");
                        }
            
                    })
                }
            
                let sbCanDrag = true;
            
                $.fn.slideToNext = function () {
                    this.each(function () {
                        if (this.className.match('slibox')) {
                            $(this).slideTo($(this).data('sb-active-slide') + 1, $(this).data('sb-timed-carousel'));
                        }
                    })
                    return $(this).data('sb-active-slide');
                }
            
                $.fn.slideToPrev = function () {
                    this.each(function () {
                        if (this.className.match('slibox')) {
                            $(this).slideTo($(this).data('sb-active-slide') - 1, $(this).data('sb-timed-carousel'));
                        }
                    })
                    return $(this).data('sb-active-slide');
                }
            
                $.fn.setTimeTo = function (time) {
                    this.each(function () {
                        $(this).data('sb-timer-time', time);
                        this.time = Math.ceil(this.time / time);
                        $('#' + this.id + ' .sb-timer').css('animation-duration', time + 'ms');
                        $('#' + this.id + ' .sb-timer').css('animation-play-state', 'running');
                    });
                    return $(this);
                }
            
                $.fn.slibox = function slibox(options) {
                    /**
                     * Не стоит сокращать названия переменных до несемантичных значений типа o, это ухудшает читаемость
                     * Также не стоит использовать хелперы ($.assign) в качестве замены стандарных возможностей языка
                     *
                     */
                    const extendedOptions = Object.assign({
                        /**
                         * Не стоит использовать !0 или !1, код должен быть явным и с понятными типами,
                         * не заставляя разработчика лишний раз интерпретировать его.
                         * Также это упор на особенности языка, желательно избегать подобных конструкций
                         *
                         */
                        height: false,
                        width: false,
                        activeSlide: 1,
                        renderArrows: true,
                        renderControllers: true,
                        imagesLinks: [],
                        loadErrorMessage: "Image is not loaded",
                        noImagesMessage: "There are no images links you added<br><small>Slibox</small>",
                        imageSize: "contain",
                        loaderLink: false,
                        imagePosition: "center",
                        animateCSS: false,
                        carousel: false,
                        timer: false,
                        timerTime: 5000,
                        timerCarousel: true,
                    }, options);
            
                    /**
                     * Перебор this.each излишен и не несет никакой смысловой нагрузки.
                     * Для chaining можно просто сделать return this
                     *
                     */
            
                    /**
                     * Название el не подходит для строки, к тому же не стоит сокращать.
                     * Селектор также можно взять из уже обернутого this вместо "#" + this.id
                     * 
                     * Также неизменяемые примитивы нужно объявлять через const
                     *
                     */
                    const wrapperId = this.selector;
            
                    /**
                     * ВАЖНО: оборачивать элементы каждый раз - значит обращаться к DOM, это может быть нужно
                     * только тогда, когда элементы динамические. Статичные необходимо кешировать в переменных.
                     * Враппер можно взять из this, а не искать через $(wrapperId).
                     * 
                     * Названия jQuery-переменных рекомендую начинать с $, чтобы избежать путаницы с другими типами
                     * сущностей
                     * 
                     */
            
                    const $wrapper = this;
            
                    $wrapper.addClass("slibox");
            
                    /**
                     * Двойное равенство не рекомендую использовать никогда, исключение - if (variable != null),
                     * так как это более лаконичная форма для if (variable !== null && variable !== undefined).
                     * 
                     * imagesLinks - массив, если нужно на него проверить, то "object" != typeof extendedOptions.imagesLinks
                     * не подойдет.
                     *
                     */
            
                    if (!Array.isArray(extendedOptions.imagesLinks) || extendedOptions.imagesLinks.length === 0) {
                        /**
                         * Не стоит писать конструкции вида return 1, 2, false. Инструкции должны быть описаны отдельно,
                         * а возвращаемое значение - соответствовать глобально возвращаемому, то есть this в данном случае
                         *
                         */
            
                        extendedOptions.imagesLinks = [];
            
                        $wrapper.html('<h1 class="sb-error">' + extendedOptions.noImagesMessage + "</h1>")
            
                        return this;
                    }
            
                    if (!$wrapper.children('.sb-slides')) {
                        $('<div/>', {
                            class: 'sb-slides'
                        }).appendTo(wrapperId);
                    }
            
                    /**
                     * Хранить данные в объекте элемента конечно можно, но смысла в этом нет. Лучше переделать на
                     * отдельный объект. Это позволит IDE выдавать подсказки, что не получится в паттерне $(this).data("sb-slide")
                     *
                     */
            
                    /**
                     * ВАЖНО: все строки нужно перевести в именованные константы для избежания опечаток и дубляжей
                     *
                     */
            
                    $wrapper.data("sb-slides-count", extendedOptions.imagesLinks.length);
                    $wrapper.data("sb-carousel", extendedOptions.carousel);
                    $wrapper.data("sb-timer-time", extendedOptions.timerTime);
                    $wrapper.data("sb-timer-carousel", extendedOptions.timerCarousel);
                    $wrapper.data("sb-timer", extendedOptions.timer);
            
                    /*
                     * Setting a link of the loader
                     */
                    if ("string" === typeof extendedOptions.loaderLink) {
                        $wrapper.css({
                            background: "url(" + extendedOptions.loaderLink + ") no-repeat center"
                        })
                    }
            
                    /*
                     * Create Arrows
                     */
                    if (extendedOptions.renderArrows) {
                        $('<div/>', {
                            class: 'sb-arrow sb-arrow-left',
                            html: '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve"><g><path fill="#da5858" stroke="#da5858" d="M45.539,63.41c0.394,0.394,0.908,0.59,1.424,0.59s1.031-0.197,1.424-0.59c0.787-0.787,0.787-2.061,0-2.848 L20.059,32.233L48.407,3.886c0.786-0.787,0.786-2.062,0-2.848c-0.787-0.787-2.062-0.787-2.849,0L15.822,30.773 c-0.205,0.206-0.384,0.506-0.484,0.778c-0.273,0.738-0.092,1.567,0.465,2.124L45.539,63.41z" /></g></svg>',
                            data: {
                                'sb-slider': wrapperId,
                                'sb-arrow-direction': 'left'
                            }
                        }).appendTo(wrapperId);
                        $('<div/>', {
                            class: 'sb-arrow sb-arrow-right',
                            html: '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve"><g><path fill="#da5858" stroke="#da5858" d="M44.152,32.024L15.824,60.353c-0.787,0.787-0.787,2.062,0,2.849c0.394,0.394,0.909,0.59,1.424,0.59 c0.515,0,1.031-0.196,1.424-0.59l29.736-29.736c0.557-0.557,0.718-1.439,0.445-2.177c-0.101-0.272-0.26-0.519-0.464-0.725 L18.652,0.828c-0.787-0.787-2.062-0.787-2.848,0c-0.787,0.787-0.787,2.061,0,2.848L44.152,32.024z" /></g></svg>',
                            data: {
                                'sb-slider': wrapperId,
                                'sb-arrow-direction': 'right'
                            }
                        }).appendTo(wrapperId);
                    }
            
                    /**
                     * Проще переборы делать через extendedOptions.imagesLinks.forEach
                     *
                     */
                    for (let i = 1; i <= extendedOptions.imagesLinks.length; i++) {
                        let slide = $(wrapperId + ' .sb-slides .sb-slide:nth-of-type(' + i + ')');
                        if (slide.length != 0) {
                            slide = slide
                                .data('sb-slide', i)
                                .attr('draggable', true)
                                .css({
                                    'background-image': 'url("' + extendedOptions.imagesLinks[i - 1] + '")',
                                    'background-repeat': 'no-repeat'
                                })
                                .addClass('sb-slide-' + i)
                                .html('<div class="sb-slider-content">' + slide.html() + '</div>');
                        } else {
                            slide = $('<div/>', {
                                class: 'sb-slide sb-slide-' + i,
                                data: {
                                    'sb-slide': i
                                },
                                draggable: true,
                                css: {
                                    'background-image': 'url("' + extendedOptions.imagesLinks[i - 1] + '")',
                                    'background-repeat': 'no-repeat'
                                }
                            }).appendTo(wrapperId + ' .sb-slides').html('<div class="sb-slider-content"></div>');
                        }
            
                        /*
                         * Create Controllers
                         */
                        if (extendedOptions.renderControllers) {
                            if (0 == i - 1) {
                                $('<div/>', {
                                    class: 'sb-controllers',
                                    data: {'sb-slider': wrapperId}
                                }).appendTo(wrapperId);
                            }
                            $('<div/>', {
                                class: 'sb-controller',
                                data: {
                                    'sb-slider': wrapperId,
                                    'sb-controller': i
                                }
                            }).appendTo(wrapperId + ' .sb-controllers');
                        }
            
                        /*
                         * Animate.css functionality
                         */
                        if (extendedOptions.animateCSS) {
                            if ("object" == typeof extendedOptions.animateCSS) {
                                if (extendedOptions.animateCSS.length < i) {
                                    $(slide).addClass(extendedOptions.animateCSS[extendedOptions.animateCSS.length - 1])
                                } else {
                                    $(slide).addClass(extendedOptions.animateCSS[i - 1]);
                                }
                            } else if ("string" == typeof extendedOptions.animateCSS) {
                                $(slide).addClass(extendedOptions.animateCSS);
                            }
                            $(slide).addClass("animated");
                        }
            
                        /*
                         * Image Size
                         */
                        if (extendedOptions.imageSize) {
                            if ("object" == typeof extendedOptions.imageSize) {
                                if (extendedOptions.imageSize.length < i) {
                                    $(slide).css({
                                        "background-size": extendedOptions.imageSize[extendedOptions.imageSize.length - 1]
                                    })
                                } else {
                                    $(slide).css({
                                        "background-size": extendedOptions.imageSize[i - 1]
                                    })
                                }
                            } else if ("string" == typeof extendedOptions.imageSize) {
                                $(slide).css({
                                    "background-size": extendedOptions.imageSize
                                })
                            }
                        }
            
                        /*
                         * Image Position
                         */
                        if (extendedOptions.imagePosition) {
                            if ("object" == typeof extendedOptions.imagePosition) {
                                if (extendedOptions.imagePosition.length < i) {
                                    $(slide).css({
                                        "background-position": extendedOptions.imagePosition[extendedOptions.imagePosition.length - 1]
                                    })
                                } else {
                                    $(slide).css({
                                        "background-position": extendedOptions.imagePosition[i - 1]
                                    })
                                }
                            } else {
                                $(slide).css({
                                    "background-position": extendedOptions.imagePosition
                                })
                            }
                        }
                    } // End for
            
                    $wrapper.width(extendedOptions.width);
            
                    if (!extendedOptions.height) {
                        $wrapper.height(0.5625 * $wrapper.width())
                    } else {
                        $wrapper.height(extendedOptions.height)
                    }
            
                    if ("number" == typeof extendedOptions.activeSlide) {
                        if (extendedOptions.activeSlide > extendedOptions.imagesLinks.length) {
                            $wrapper.data("sb-active-slide", extendedOptions.imagesLinks.length)
                        } else if (extendedOptions.activeSlide < 1) {
                            $wrapper.data("sb-active-slide", 1)
                        }
                        $wrapper.data("sb-active-slide", extendedOptions.activeSlide)
                    } else {
                        $wrapper.data("sb-active-slide", 1)
                    }
            
                    if (extendedOptions.timer) {
                        $wrapper.data('sb-timed-carousel', extendedOptions.timerCarousel);
                        $('<div/>', {
                            class: 'sb-timer-container',
                        }).append($('<div/>', {
                            class: 'sb-timer sb-timer-animate',
                            style: 'animation-duration: ' + extendedOptions.timerTime + 'ms'
                        })).appendTo(wrapperId);
                        this.time = 2;
                    }
            
                    $(".sb-controller").unbind('click');
                    $(".sb-controller").click(function () {
                        $($(this).data("sb-slider")).slideTo($(this).data("sb-controller"))
                    })
            
                    $(".sb-arrow").unbind('click');
                    $(".sb-arrow").click(function () {
                        let sliderId = $(this).data("sb-slider"),
                            activeSlide = $wrapper.data("sb-active-slide");
                        if ("left" == $(this).data("sb-arrow-direction")) {
                            $(sliderId).slideTo(activeSlide - 1)
                        } else if ("right" == $(this).data("sb-arrow-direction")) {
                            $(sliderId).slideTo(activeSlide + 1)
                        }
                    })
            
                    $wrapper.hover(function () {
                        let sliderId = '#' + this.id;
                        $(sliderId + ' .sb-timer').css('animation-play-state', 'paused');
                        $(sliderId)[0].paused = true;
                    }, function () {
                        let sliderId = '#' + this.id;
                        $(sliderId + ' .sb-timer').css('animation-play-state', 'running');
                        $(sliderId)[0].paused = false;
                    });
            
                    $wrapper.slideTo($wrapper.data("sb-active-slide"), true);
            
                    $(wrapperId + ' .sb-slide').each(function () {
                        let box = $(this),
                            container = $wrapper[0];
                        this.boxOffset, this.myDragFlag = false
                        box.on('selectstart', function () {
                            sbCanDrag = false;
                        });
            
                        box[0].ondragstart = function (e) {
                            if (sbCanDrag) {
                                this.startX = e.pageX - box[0].offsetLeft - container.offsetLeft
                                this.myDragFlag = true
                            }
                        }
                        box[0].ondragend = function (e) {
                            if (sbCanDrag) {
                                this.boxOffset = e.pageX - this.startX;
                                if (this.boxOffset - container.offsetLeft <= -20) {
                                    /**
                                     * Вычисляемые переменные нужно оформлять в отдельных константах для лучшей читаемости
                                     *
                                     */
                                    $wrapper.slideTo($(this).data("sb-slide") + 1)
                                }
                                if (this.boxOffset - container.offsetLeft >= 20) {
                                    $wrapper.slideTo($(this).data("sb-slide") - 1)
                                    this.myDragFlag = false
                                }
                            } else {
                                sbCanDrag = true;
                            }
                        }
                    })
            
                    return this;
                }
            }(jQuery);
              +1
              Здравствуйте, спасибо большое за помощь, я переписал свой код следуя вашим советам. Еще раз спасибо! Если вдруг захотите посмотреть на новый код, ссылка на исходник
                0

                Все еще вижу подобные конструкции:


                this.each(function() {
                  const $wrapper = $(this)
                  $wrapper.slibox('slideTo', $wrapper.data('activeSlide') - 1)
                })
                return this

                this.each не нужен, а само слово this в большинстве случаев лучше не использовать, т.к. непонятно, что в нем находится — контекст штука динамическая. В данном случае можно так


                const $wrapper = this;
                const prevSlideIndex = $wrapper.data('activeSlide') - 1;
                
                $wrapper.slibox('slideTo', prevSlideIndex);
                
                return $wrapper;

                Также вижу анонимные функции, конструкции !1, перебор for вместо forEach, двойное равенство, проверку 'object' != typeof extOptions.imagesLinks вместо Array.isArray, хранение данных в $wrapper.data вместо обычного объекта. В общем, меньше половины рекомендаций реализовано, так что дальше анализировать пока не буду

          +1

          Три года назад JQuery был мёртв уже несколько лет. Вы три года потратили на изучение библиотеки, от которой уже на тот момент успели отказаться даже самые неповоротливые любители легаси, всё это время упорно игнорируя всё, что происходило в мире фронтенда? Зачем?

            0
            Мне показалось, что в статичных страничках использовать jQuery не плохо. А что вы можете посоветовать использовать вместо него?
              0

              Как уже написали выше, ванильный js умеет всё то же, что и JQuery.

                0
                можно посоветовать не использовать jQuery
              +1

              Через пару лет ждём статью про backbone, а ещё лет через пять — про стрелочные функции :-)

                0
                  +1
                  Тоже писал велосипед слайдер собственного сочинения, но на VanillaJS с поддержкой ES5. Прекрасный опыт. Целая гора новых знаний. И чувство удовлетворения от завершения процесса.

                  Однако, это должно оправдываться. Если вы делаете слайдер для себя — отлично. Если вы работаете над чужим проектом, то удорожаете разработку личным велосипедом. Так как на его создание уходит время, а еще его нужно будет поддерживать.

                  И все-таки не совсем понятно, зачем для этой цели выбирать jQuery. Если речь не стоит о поддержке старых браузеров, то чем плох современный JS? Если ради опыта и интереса, тогда понятно. А если нет, то нет.
                    0
                    Да, ради опыта и интереса, не для клиента.

                    Мне очень нравится ES6, его синтаксический сахар и всё такое, но я хотел написать свой слайдер, который будет работать на старых браузерах, по пути научиться писать плагины на jQuery.
                    +4
                    Ребята, вы что-то как-то уж резко человека осуждаете. Он же сам написал, что только учится. Да, jQuery устарел, я с этим тоже согласен, но на него уж слишком набросились. Так можно и отбить желание учиться программированию.

                    А автору статьи я бы рекомендовал начать изучить что-нибудь из этих фреймворков: React, vue или Angular. Коммерческой пользы от потраченного времени больше будет.
                      +2
                      Осуждение вполне обосновано. Хочет чувак учиться, пускай идёт и учится. Курсов полно. Написание статьи и обучение, различные вещи. Какой опыт вы сможете перенять у человека с сомнительным опытом?
                        0
                        Я не против осуждения, значит мне есть куда расти. Опыт написания статьи тоже ведь опыт? )
                        0
                        Спасибо за поддержку и понимание! Так как я еще не занимаюсь коммерческой разработкой, больше делаю упор на обучение. Правда, хотелось бы посмотреть как обстоят дела в современной команде, чтобы понять какими стеками и инструментами пользуются профессионалы. Короче, нужен ментор, пока я совсем не пропал )
                        Сейчас я изучаю Vue, отдельно и в связке с Laravel.
                        +3
                        Надо было назвать статью. «Как мне превратить хабр в хламовник своей тривиальной пиар-статьёй»
                          –2

                          Разве хабр не хламовник? Лучше читать технические статьи, чем про эффективных менеджеров.

                        Only users with full accounts can post comments. Log in, please.