技巧型设计模式

链模式(OperateOfResponsibility)

核心
  • 定义:在对象方法中将当前对象返回,实现对一个对象多个方法的链式调用
  • 重点:简化接口调用(返回 this )
  • 应用:jQuery 方法链式调用
示例一:jQuery 获取元素功能
  • 需求:简单模拟 jQuery 获取元素的基本功能
  • js
// index.js
var A = function (selector, context) {
   
  return new A.fn.init(selector, context);
};
A.fn = A.prototype = {
   
  /**
   * // init 方法,new 该方法会报错
   * init(){
   *
   * }
   * 所有方法定义不是构造函数,如果您尝试实例化它们,将抛出TypeError。
   */
  /**
   *
   * @param {string} selector 选择器
   * @param {dom|undefined} context 上下文
   * @returns
   */
  init: function (selector, context = document) {
   
    this.length = 0;
    if (~selector.indexOf("#")) {
   
      this[0] = document.getElementById(selector.slice(1));
      this.length = 1;
    } else {
   
      var doms = context.getElementsByTagName(selector),
        i = 0,
        len = doms.length;
      for (; i < len; i++) {
   
        this[i] = doms[i];
      }
      this.length = len;
    }
    this.context = context;
    this.selector = selector;
    return this;
  },
  size() {
   
    return this.length;
  },
  splice: [].splice, // 增强数组特性
};
A.fn.init.prototype = A.fn; // 原型链继承

console.log(A("#d1"));
console.log(A("#d1").size()); // 1
console.log(A("div", A("#d1")[0]).size()); // 3

if (typeof module !== "undefined") {
   
  module.exports = A;
}
  • html
 <div id="d1">
    <div>11</div>
    <div></div>
    <div></div>
  </div>
  • 效果
    在这里插入图片描述
示例二:jQuery 方法拓展
  • 需求:实现 jQuery 的 extend 方法(内部/外部对象拓展)
  • js
// extend.js
// nodejs 环境
if (typeof require === "function") {
   
  A = require("./index");
}

/**
 * 扩展对象成员方法
 * 传2个及以上参数,类似于 Object.assign 方法(外部对象拓展)
 * 传一个参数,拓展 this(A或A.extend)(内部拓展)
 */
A.extend = A.fn.extend = function () {
   
  // 拓展对象从第二个参数算起
  let i = 1,
    len = arguments.length,
    //源对象
    target = arguments[0],
    // 遍历拓展对象的指针
    j;
  // 只有1个参数
  if (len === 1) {
   
    target = this;
    // 第一个参数为拓展对象
    i--;
  }
  // 遍历拓展对象
  for (; i < len; i++) {
   
    for (j in arguments[i]) {
   
      // 拓展源对象
      target[j] = arguments[i][j];
    }
  }
  return target;
};

// 外部拓展 (类似于 Object.assign )
var obj = {
   };
console.log(A.extend(obj, {
    a: 1, b: 2 }, {
    a: 2, c: 3 }) === obj); // true
console.log(obj); // { a: 2, b: 2, c: 3 }
A.fn.extend(obj, {
    d: 4, b: 0 });
console.log(obj); // { a: 2, b: 0, c: 3, d: 4 }

// 内部拓展(jQuery框架扩充类和原型方法)
// 浏览器环境测试
if (typeof window === "object") {
   
  // 拓展A.fn(原型拓展,实例访问)
  A.extend(A.fn, {
    version: "1.0" });
  const d1 = A("#d1");
  console.log(d1); // init [div#d1, context: document, selector: "#d1"]
  console.log(d1.version); // 1.0
  A.fn.extend({
   
    getVersion() {
   
      return this.version;
    },
  });
  console.log(d1.getVersion()); // 1.0

  // 拓展A(类/构造函数拓展)
  A.extend({
    a: 11, b: 22 });
  A.extend({
    c: 33 });
  const {
    a, b, c } = A;
  console.log(a, b, c); // 11 22 33
}
示例三:jQuery 操作 DOM 方法
  • 需求:模拟 jQuery ,实现 事件绑定,html / css / attr 查询和赋值
  • js
A.extend({
   
  // 将 - 转化为驼峰
  camelCase(str) {
   
    return str.replace(/\-(\w)/g, function (all, letter) {
   
      console.log(all, letter);
      return letter.toUpperCase();
    });
  },
});
// 添加方法(事件、属性、类、html)
A.fn.extend({
   
  // 事件,创建不同环境的函数,减少调用时的校验
  on: (function () {
   
    // 标志浏览器 DOM2级事件
    if (document.addEventListener) {
   
      return function (type, fn) {
   
        for (var i = 0; i < this.length; i++) {
   
          this[i].addEventListener(type, fn, false);
        }
        return this;
      };
    }
    // IEDOM2级事件
    else if (document.attachEvent) {
   
      return function (type, fn) {
   
        for (var i = 0; i < this.length; i++) {
   
          this[i].attachEvent(`on${
     type}`, fn);
        }
        return this;
      };
    }
    // 不支持DOM2级事件
    else {
   
      return function (type, fn) {
   
        for (var i = 0; i < this.length; i++) {
   
          this[i][`on${
     type}`] = fn;
        }
        return this;
      };
    }
  })(),
  /**
   *
   * @returns this
   */
  css() {
   
    const args = arguments,
      len = args.length;
    if (this.length < 1) return this;
    // 只有一个参数
    if (len === 1) {
   
      // 获取样式 $.css('width)
      if (typeof args[0] === "string") {
   
        return getComputedStyle(this[0])[A.camelCase(args[0])];
      }
      // 设置 $.css({width: '20px','background-color':'red'})
      else if (typeof args[0] === "object" && args[0] !== null) {
   
        for (var i in args[0]) {
   
          for (var j = 0; j < this.length; j++) {
   
            this[j].style[A.camelCase(i)] = args[0][i];
          }
        }
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值