avatar

目录
JavaScript之组件封装

jQuery组件封装

  1. 思想:
    • 利用立即执行函数(闭包)封装组件方法,避免污染全局作用域;
    • 将方法挂到$.fn对象上,即可在jQuery实例对象上调用封装得方法;
  2. 实现:
    javascript
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    // html
    <select name="select" class="select"></select>

    // plugin
    (function($) {
    /**
    * @desc 一个异步获取下拉框数据的组件
    * @param options { object } 配置参数对象
    * @param options.url { string } 获取数据路径
    * @param options.textField { string } option的显示文本对应返回数据中的字段名
    * @param options.valueField { string } option的value对应返回数据中的字段名
    * @return target { jquery object } 返回jquery对象本身,提供链式调用
    */
    $.fn.initSelect = function(options) {
    const defaultOptions = {
    textField: 'text',
    valueField: 'value',
    } // 用户可调配置
    const target = this
    let optionCode = ''

    $.extend(options, defaultOptions)
    $.ajax({
    url: options.url,
    method: 'GET',
    success: function(res) {
    const { data } = res
    optionCode = data
    .map(elem => (`<option value="${elem[options.valueField]}">${elem[options.textField]}</option>`))
    .join('')
    target.empty().html(optionCode)
    },
    })

    return target
    }
    }(jQuery))

    // logic
    $(document).ready(function() {
    $('.select').initSelect({ url: '/select' })
    })

JavaScript原生面向对象封装

  1. 思路:
    • 利用闭包封装,将需要挂载方法的对象当参数传入;
    • 实现一些兼容;
    • 利用构造函数和原型的写法(构造函数prototype上的属性(方法)能在实例上访问);
  2. 实现一个拖拽组件:
    javascript
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    (function () {
    // 私有方法,仅仅用来获取transform的兼容写法
    function getTransform() {
    var transform = '',
    divStyle = document.createElement('div').style,
    transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'],

    i = 0,
    len = transformArr.length;

    for (; i < len; i++) {
    if (transformArr[i] in divStyle) {
    return transform = transformArr[i];
    }
    }

    return transform;
    }
    // 这是一个私有属性,不需要被实例访问
    var transform = getTransform();

    function Drag(selector) {
    // 放在构造函数中的属性,都是属于每一个实例单独拥有
    this.elem = typeof selector == 'Object' ? selector : document.getElementById(selector);
    this.startX = 0;
    this.startY = 0;
    this.sourceX = 0;
    this.sourceY = 0;

    this.init();
    }

    // 原型
    Drag.prototype = {
    constructor: Drag,

    init: function () {
    // 初始时需要做些什么事情
    this.setDrag();
    },

    // 该方法用来绑定事件
    setDrag: function () {
    var self = this;
    this.elem.addEventListener('mousedown', start, false);
    function start(event) {
    self.startX = event.pageX;
    self.startY = event.pageY;

    var pos = self.getPosition();

    self.sourceX = pos.x;
    self.sourceY = pos.y;

    document.addEventListener('mousemove', move, false);
    document.addEventListener('mouseup', end, false);
    }

    function move(event) {
    var currentX = event.pageX;
    var currentY = event.pageY;

    var distanceX = currentX - self.startX;
    var distanceY = currentY - self.startY;

    self.setPostion({
    x: (self.sourceX + distanceX).toFixed(),
    y: (self.sourceY + distanceY).toFixed()
    })
    }

    function end(event) {
    document.removeEventListener('mousemove', move);
    document.removeEventListener('mouseup', end);
    // do other things
    }
    },

    // 稍作改造,仅用于获取当前元素的属性,类似于getName
    getStyle: function (property) {
    return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(this.elem, false)[property] : this.elem.currentStyle[property];
    },

    // 用来获取当前元素的位置信息,注意与之前的不同之处
    getPosition: function () {
    var pos = { x: 0, y: 0 };
    if (transform) {
    var transformValue = this.getStyle(transform);
    if (transformValue == 'none') {
    this.elem.style[transform] = 'translate(0, 0)';
    } else {
    var temp = transformValue.match(/-?\d+/g);
    pos = {
    x: parseInt(temp[4].trim()),
    y: parseInt(temp[5].trim())
    }
    }
    } else {
    if (this.getStyle('position') == 'static') {
    this.elem.style.position = 'relative';
    } else {
    pos = {
    x: parseInt(this.getStyle('left') ? this.getStyle('left') : 0),
    y: parseInt(this.getStyle('top') ? this.getStyle('top') : 0)
    }
    }
    }

    return pos;
    },

    // 用来设置当前元素的位置
    setPostion: function (pos) {
    if (transform) {
    this.elem.style[transform] = 'translate(' + pos.x + 'px, ' + pos.y + 'px)';
    } else {
    this.elem.style.left = pos.x + 'px';
    this.elem.style.top = pos.y + 'px';
    }
    },

    }

    // 一种对外暴露的方式
    window.Drag = Drag;
    })();

    // 使用:声明2个拖拽实例
    new Drag('target');
    new Drag('target2');
文章作者: 盛顺炎
文章链接: https://www.shengshunyan.xyz/2018/10/27/JavaScript%E4%B9%8B%E7%BB%84%E4%BB%B6%E5%B0%81%E8%A3%85/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 果实的技术分享
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论