3

作为一名开发人员,我想创建自己的 JavaScript 库和框架。在架构和功能方面,我应该考虑哪些方面?

4

1 回答 1

10

首先,你需要知道你想让你的图书馆做什么。从那里开始,您需要能够知道如何做您正在尝试构建的内容。例如,如果您正在尝试创建一个游戏库,您最好了解您的方程式,并且擅长使用 Canvas 和 WebGL 等内容。我之前为字符串、数组、对象等方法创建了一个库。我完成了它,但遗憾的是我从未完成文档。

无论如何,我基本上是从创建一个“JavaScript 类”开始的。这看起来像(做一个类似 jQuery 的库示例):

var DOM = function (selector) {
  if (typeof selector == "string") {
        selector = document.querySelectorAll(selector);
  }
  this.animate = function (prop, times, callbacks) {
      var el = selector;
      var animate = function (element, props, time, callback) {
          callback = callback || function () {};
          time = time || 1000;
          var timers = {}, // store the different interval timers so that they can be cancelled
          calls = 0, // numbers of times the call would have been called
          nprops = 0; // number of properties
          for (var prop in props) {
              (function (prop) {
                  var edit = prop == "scrollTop" ? element : element.style;
                  var stepCounter = [],
                      customStep = props[prop],
                      curr = edit[prop],
                      lastStepPercent = curr == "" ? (prop == "opacity" ? 1 : 0) : curr,
                      measure = prop == "scrollTop" || prop == "opacity" ? "" : "px",
                      stepper = function () {
                          edit[prop] = stepCounter[0] + measure;
                          stepCounter.shift();
                      };
                  if (props[prop].constructor == Number) customStep = [props[prop]];
                  for (var step = 0, len = customStep.length; step < len; step++) {
                      var from = parseInt(lastStepPercent),
                          to = parseInt(customStep[step]),
                          small = to < from,
                          numOfSteps = small ? from - to : to - from, // get current number of frames
                          multi = 30 * Math.round(parseInt(time) / 1000),
                          by = numOfSteps / (25 + multi) * len; // the stepper number

                      if (from == to) {
                          break;
                      }
                      for (var i = from; small ? i >= to : i <= to; i += small ? -by : by) {
                          stepCounter.push(i);
                      }
                      stepCounter.push(to);
                      lastStepPercent = customStep[step];
                  }
                  stepper();
                  timers[element + prop] = setInterval(function () {
                      stepper();
                      if (stepCounter.length == 0) {
                          clearInterval(timers[element + prop]);

                          calls++;
                          if (calls == nprops) {
                              callback.call(element);
                          }
                      }
                  }, time / stepCounter.length);
                  nprops++;
              })(prop);
          }
      };
      for (var i = 0; i < el.length; i++) {
          animate(el[i], prop, times, callbacks);
      };
      return new DOM(selector); // re-initiate "JavaScript class" for chaining
  }
  this.click = function (fun) {
      var el = selector;
      for (var i = 0, len = el.length; i < len; i++) {
        el[i].onclick = fun.bind(el);
      }
  }
};

为您的库设置变量:

var $ = function (selector) {
    return new DOM(selector);
};

注意我使用一个单独的函数来做“类”只是因为我认为$应该保持基本并且只是一个init函数。

您可以像这样使用此设置:

$("#click-me").click(function(){
    $(this).animate({
            "opacity": 0
        }, 1000);
    });
});

示例(JSFiddle)

这应该对 jQuery 的语法是如何工作的有一点了解。当然,库不一定要那么复杂。库只是使您作为开发人员的生活更轻松的功能的集合。一旦你拥有了完整的函数集合,即使像下面这样的设置最终也可以被认为是一个库:

$ = {};
$.animate = function (selector, prop, times, callbacks) {
   var el = document.querySelectorAll(selector);
   var animate = function (element, props, time, callback) {
       callback = callback || function () {};
       time = time || 1000;
       var timers = {}, // store the different interval timers so that they can be cancelled
       calls = 0, // numbers of times the call would have been called
       nprops = 0; // number of properties
       for (var prop in props) {
           (function (prop) {
               var edit = prop == "scrollTop" ? element : element.style;
               var stepCounter = [],
                   customStep = props[prop],
                   curr = edit[prop],
                   lastStepPercent = curr == "" ? (prop == "opacity" ? 1 : 0) : curr,
                   measure = prop == "scrollTop" || prop == "opacity" ? "" : "px",
                   stepper = function () {
                       edit[prop] = stepCounter[0] + measure;
                       stepCounter.shift();
                   };
               if (props[prop].constructor == Number) customStep = [props[prop]];
               for (var step = 0, len = customStep.length; step < len; step++) {
                   var from = parseInt(lastStepPercent),
                       to = parseInt(customStep[step]),
                       small = to < from,
                       numOfSteps = small ? from - to : to - from, // get current number of frames
                       multi = 30 * Math.round(parseInt(time) / 1000),
                       by = numOfSteps / (25 + multi) * len; // the stepper number

                   if (from == to) {
                       break;
                   }
                   for (var i = from; small ? i >= to : i <= to; i += small ? -by : by) {
                       stepCounter.push(i);
                   }
                   stepCounter.push(to);
                   lastStepPercent = customStep[step];
               }
               stepper();
               timers[element + prop] = setInterval(function () {
                   stepper();
                   if (stepCounter.length == 0) {
                       clearInterval(timers[element + prop]);

                       calls++;
                       if (calls == nprops) {
                           callback.call(element);
                       }
                   }
               }, time / stepCounter.length);
               nprops++;
           })(prop);
       }
   };
   for (var i = 0; i < el.length; i++) {
       animate(el[i], prop, times, callbacks)
   };
}
$.animate("#id", {
    width: 0
}, 1000);

我使用这个相对复杂的函数只是为了注意,如果您尝试开发一些困难的东西,一个库可能需要做很多工作。无论如何,您需要能够在 JavaScript 中进行非常高级的编程。最后,这并不难,只要你知道自己要做什么,并且对 JavaScript 有一定的逻辑经验。当然,我不是 JavaScript 专家,可能有更好的库架构,但我希望这会有所帮助。

于 2013-07-18T02:08:20.247 回答