美文网首页
深入了解面向对象/通过面向对象封装插件

深入了解面向对象/通过面向对象封装插件

作者: Raral | 来源:发表于2021-03-02 11:30 被阅读0次

JavaScript--面向对象

理解对象

xxx语言中一切皆为对象!

  • 什么叫面向对象?
    对象(object),台湾译作物件,是面向对象(Object Oriented)中的术语,既表示客观世界问题空间(Namespace)中的某个具体的事物,又表示软件系统解空间中的基本元素。
    在软件系统中,对象具有唯一的标识符,对象包括属性(Properties)和方法(Methods),属性就是需要记忆的信息,方法就是对象能够 提供的服务。在面向对象(Object Oriented)的软件中,对象(Object)是某一个类(Class)的实例(Instance)。 —— 维基百科

特性:
封装:
把类同事物的相同的属性和方法封装到一个对象中。

继承:
继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。

多态:
多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。

es5 -- 继承

    function Person(name, age) {
        this.name = name;
        this.age = age;
        this.work = function() {
            console.log("正在工作")
        }
    }
    Person.prototype.sex = "男";
    Person.prototype.run = function() {
        console.log("正在跑步")
    }
    let p = new Person("李四", 20);

    function Sub(name, age) {
        Person.call(this, name, age);// 构造函数继承:缺点没有继承原型的属性和方法
        this.address = "beijin"// 字类的特有属性
    }
   
    // Sub.prototype = Person.prototype;// 原型链的继承: 继承了父类原型上的方法;但是这样写会导致 字类添加原型的方法时会影响父类的原型。
    Sub.prototype = Object.create(Person.prototype);// 这样写解决,子类影响父类的问题;w但是控制的台打印出字类的结构,会把字类原型方法和父类原型方法分离开,这样会多出一个层级。对查找不够友好
    Sub.prototype = Object.assign(Person.prototype);// 这样写解决, 字类的结构和父类的结构一样样。
    
    Sub.prototype.study = function() {
        console.log("正在学习");
    }
    let s = new Sub("子类", 100);

效果:

  • 使用 Object.assign 错误的


    12.jpg
  • 使用 Object.create 正确的


    22.png

es6 -- 继承

  class Person {
        constructor(name, age) {
            //表示当前类的属性和方法
            this.name = name;
            this.age = age;
            this.work = function() {
                console.log("正在工作")
            }
        }
         
        static test() { //等同于 es5 Person.test 
            console.log("类的静态方法")
        }
        // 表示原型的方法: 等同es5 Person.propetype.work
        run() {
            console.log("正在跑步")
        }
    }
    let p = new Person("lisi", 20);

    //extends:等同 es6  Sub.prototype = Object.create(Person.prototype); 原型链继承
    class Sub extends Person {
        constructor(name, age) {
            //等同 es5 Person.call(this, name, age); 构造函数继承
            super(name,age);
        }

        study() {
            console.log("正在学习")
        }
    }

    let s = new Sub("子类",100);

oop面向对象编程
在前端开发中,我们需要把一些常用的功能和效果,要封装到一个js中,这样方便我们以后的重复使用。
我们要通过 面对对象编程学会封装插件的能力。

封装插件(OOP)

  • 原生js 封装 (通过封装插件)
// Javascript

/* 创建一个构造函数 */
function FreeSlider(selector,speed) {

    /* 变量改为属性 */
    this.oContainer = document.querySelector(selector);
    this.oWrapper = this.oContainer.querySelector('ul');
    this.oSlide = this.oWrapper.querySelectorAll('li');

    /* 当不传入轮播速度时,速度默认为100 */
    this.speed = speed || 100;

    this.containerW = this.oContainer.offsetWidth;
    this.wrapperW = this.oSlide[0].offsetWidth * this.oSlide.length;
    this.x = 0;
    this.timer = null;

    this.init();

}

/* 构造函数的原型对象 */
FreeSlider.prototype = {

    constructor: FreeSlider,

    /* 功能抽离,此处实现初始化 */
    init: function(){
        this.oWrapper.style.width = this.wrapperW * 2 + 'px';
        this.oWrapper.innerHTML += this.oWrapper.innerHTML;

        if(this.wrapperW < this.containerW){
            this.oContainer.style.width = this.wrapperW + 'px';
        }

        this.slideMove();
    },

     /* 图片自动无限轮播 */
    slideMove: function(){
        /* 此处需要注意this的指向,
           在setInterval回调函数中的this指向为window */
        var that = this;  
        this.timer = setInterval(function () {
            that.x++;
            if(that.x > that.wrapperW){
                that.x = 0;
            }
            that.oWrapper.style.transform = 'translate('+ (-that.x) +'px)';
        },this.containerW / this.speed);   // 将速度转化成定时器时间
    },

    /* 图片停止轮播 */
    stopSlideMove: function () {
        clearInterval(this.timer);
    }
};

window.onload = function(){

    var oContainer = document.querySelector('.container');

    // 新建图片轮播对象
    var mySlider = new FreeSlider('.container',300);

    // 鼠标移入时清除定时器,图片停止轮播
    oContainer.addEventListener('mouseover',function () {
        mySlider.stopSlideMove();
    });

    // 鼠标移出时图片继续轮播
    oContainer.addEventListener('mouseout',function () {
        mySlider.slideMove();
    });

}
  • 基于jquery封装
(function($,window) {
    //common方法封装到jQuery类对象里
    $.extend({
        debounce:function (fn,wait) {
            let timer = null;
            return function () {
                if(timer) {
                    window.clearTimeout(timer);
                }
                let _this = this;
                let args = arguments;
                timer = setTimeout(() => {
                    fn.apply(_this, args)
                }, wait);
            }
        }
    })
    //轮播切换封装到jQuery对象方法
    $.fn.indexBannerScroll = function(options) {
        var opts = $.extend({},$.fn.indexBannerScroll.defaults,options);
        return this.each(function(){
            var $this = $(this),
                listContent = $this.find(".list"),// 如果是滚动切换时,这个是  子容器k 800 px 
                carouselItem = $this.find(".item"),//所有的轮播盒子
                points = $this.find(".point"),//所有的点
                carouselLength = carouselItem.length,//轮播的个数
                currentIndex = 0,//当前对应索引
                imgWidth = carouselItem.eq(0).width(),
                prevBtn = $this.find(".prevBtn"),//上一个按钮
                nextBtn = $this.find(".nextBtn"),//下一个按钮
                speed = opts.speed,//延时时间
                type = opts.type,// 切换的类型  如果是0 表示 显示隐藏 ; 如果是1表示 图片滚动
                timer = null;//定时器 自动轮播用的
            //先默认给第一个盒子添加激活 类
            $this.find(".item:first-child").addClass("active");
            // 图片切换 
            function bannerScroll() {
                //圆点变化
                points.eq(currentIndex).addClass("active2").siblings().removeClass("active2");
                //图片变化
                carouselItem.eq(currentIndex).addClass("active").siblings().removeClass("active");
            }
            
            //图片切换效果2
            function bannerSilde() {
                //圆点变化
                points.eq(currentIndex%points.length).addClass("active2").siblings().removeClass("active2");
                //图片的变化
                listContent.stop().animate({
                    left: `-${(currentIndex + 1) * imgWidth} `
                },1000,function () {
                    if(currentIndex == points.length) {
                        currentIndex = 0;
                        listContent.css("left", `-${(currentIndex + 1) * imgWidth}px`)
                    }else if(currentIndex == -1 ) {
                        currentIndex = points.length - 1;
                        listContent.css("left", `-${(currentIndex + 1) * imgWidth}px`)
                    }
                })
            }
            //上一个按钮
            prevBtn.click($.debounce(prevMethod,400))
            //下一个按钮
            nextBtn.click($.debounce(nextMethod,400))
            //下一个的方法
            function nextMethod() {
                currentIndex ++;
                currentIndex = currentIndex > carouselLength - 1? 0 : currentIndex;
                if(type=="0") {
                    bannerScroll()
                }else if(type == "1") {
                    bannerSilde()
                }
            }
            //上一个方法
            function prevMethod() {
                currentIndex --;
                currentIndex = currentIndex < 0? carouselLength - 1 : currentIndex;
                console.log(currentIndex)
                if(type=="0") {
                    bannerScroll()
                }else if(type == "1") {
                    bannerSilde()
                }
            }
            //指示点按钮
            points.click(function(e) {
                currentIndex = $(this).attr("data-index");
                if(type=="0") {
                    bannerScroll()
                }else if(type == "1") {
                    bannerSilde()
                }
            })

            var timer = setInterval(function() {
                // nextBtn.click();
            },speed)
        })
    }
    $.fn.indexBannerScroll.defaults = {
        speed: 1900
    }

    // 异步效果显示(针对多个元素的效果)
    $.fn.asyncAnimation =  function(options) {
        var opts = $.extend({},$.fn.asyncAnimation.defaults, options );
        return this.each(function() {
            var $this = $(this),
                list = $this.find("li"),
                delay = opts.delay,
                cssAttr = opts.cssAttr.toString(),
                cssValue = opts.cssValue;
        
            function setAnimation($el) {
                return new Promise((resolve, reject) => {
                    setTimeout(() => {
                        let obj = Object.create(null);
                        obj[cssAttr] = cssValue;
                        $el.css(obj)
                        resolve()
                    }, delay)
                })
            }
            async function excutor() {
                for(let i = 0; i < list.length; i ++) {
                    await setAnimation(list.eq(i), 300)
                }
            }
            excutor();
        })

    }
    $.fn.asyncAnimation.defaults = {
        delay: 300,
        cssAttr: "animation",
        cssValue:"img-show .5s 0.3s linear forwards"
    }
    

    //图片和文字悬浮效果(针对单个元素内嵌多个元素 效果)
    $.fn.pictureTextAnimation = function(options) {
        var opts = $.extend({},$.fn.pictureTextAnimation.defaults, options);
        return this.each(function() {
            var $this = $(this),
                pircure = $this.find("img"),
                text = $this.find(".text-wrap"),
                overCss = opts.overCss,
                outCss = opts.outCss;

            $this.hover(
                function() {
                    text.css({
                        "animation": overCss
                    })  
                },
                function() {
                    text.css({
                        "animation": outCss
                    })  
                },
            )

        })

    }
    $.fn.pictureTextAnimation.defaults = {
        overCss:"",
        outCss:""
    }


})(jQuery,window);

总结

只是让你知道,任何一门语言思维模式很重要,其次,掌握最底层的原生js的API。

  1. JS插件其实没有你想象的那么难,基本原理就是面向对象
  2. 将需要可灵活配置的部分作为构造函数的参数传入,插件中的各个功能可作为原型方法提供给外部调用。

当你可以把常用的效果通过面向对象编程封装后,你就可以通封装自己的UI库,不管通过vue中的UI框架,还是react中的UI框架,最底层还是自己会原生js操作api和处理业务逻辑能力

相关文章

  • 深入了解面向对象/通过面向对象封装插件

    JavaScript--面向对象 理解对象 xxx语言中一切皆为对象! 什么叫面向对象?对象(object),台湾...

  • js 实现类的继承的5种方式

    什么是面向对象 面向对象是一种思想,是基于面向过程而言的,就是说面向对象是将功能等通过对象来实现,将功能封装进对象...

  • 面向对象概述

    面向过程和面向对象的区别通过对比,来更深入的了解下面向对象 -面向过程主要是把问题分解成多个不同的步骤,然后把各个...

  • 面向对象和面向过程

    1.面向对象:面向对象是一种思想,是基于面向过程而言的,就是说面向对象是将功能等通过对象来实现,将功能封装进对象之...

  • JS面向对象

    JS面向对象入门 1、面向对象语言概念面向对象语言主要包括 类、对象、封装、多肽。2、面向对象的编程思想面向过程思...

  • Python中面向对象概述

    1.什么是面向对象? 面向对象是一种思想,是基于面向过程而言的,就是说面向对象是将功能等通过对象来实现,将功能封装...

  • Java学习day-07:面向对象

    一、面向过程和面向对象 1.面向对象与面向过程的区别: 面向对象具有三大特征;封装,继承,多态;面向对象与面向过程...

  • python 面向对象封装案例

    面向对象封装案例 目标 封装 小明爱跑步 存放家具 01. 封装 封装 是面向对象编程的一大特点 面向对象编程的 ...

  • 14.Python对象封装

    面向对象封装案例 目标 封装 小明爱跑步 存放家具 01. 封装 封装 是面向对象编程的一大特点 面向对象编程的 ...

  • 面试 | java基础

    面向对象 1、面向对象特征? 封装封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成...

网友评论

      本文标题:深入了解面向对象/通过面向对象封装插件

      本文链接:https://www.haomeiwen.com/subject/wlmtqltx.html