当前位置: 首页 > 工具软件 > Riot.js > 使用案例 >

Riot.js源码阅读

孙清野
2023-12-01

    Riot.js的版本是1.0.4。官网地址:https://muut.com/riotjs

    整个Riot.js只有3个可以在外面调用的函数接口,分别是observable、render、route。

    1、observable函数

    observable函数只有一个参数el,指向Model,该接口的作用是预处理Model,使得Model具有事件定义和发布功能,返回值是处理后的Model。我们来看源码:

riot.observable = function(el) {
  var callbacks = {}, slice = [].slice;

  el.on = function(events, fn) {
    if (typeof fn === "function") {
      events.replace(/\S+/g, function(name, pos) {
        (callbacks[name] = callbacks[name] || []).push(fn);
        fn.typed = pos > 0;
      });
    }
    return el;
  };

  el.off = function(events, fn) {
    if (events === "*") callbacks = {};
    else if (fn) {
      var arr = callbacks[events];
      for (var i = 0, cb; (cb = arr && arr[i]); ++i) {
        if (cb === fn) { arr.splice(i, 1); i--; }
      }
    } else {
      events.replace(/\S+/g, function(name) {
        callbacks[name] = [];
      });
    }
    return el;
  };

  // only single event supported
  el.one = function(name, fn) {
    if (fn) fn.one = true;
    return el.on(name, fn);
  };

  el.trigger = function(name) {
    var args = slice.call(arguments, 1),
      fns = callbacks[name] || [];

    for (var i = 0, fn; (fn = fns[i]); ++i) {
      if (!fn.busy) {
        fn.busy = true;
        fn.apply(el, fn.typed ? [name].concat(args) : args);
        if (fn.one) { fns.splice(i, 1); i--; }
        fn.busy = false;
      }
    }

    return el;
  };

  return el;

};

    2、render函数    

    render函数顾名思义就是用来呈现html模板的。直接上代码:

var FN = {}, // Precompiled templates (JavaScript functions)
  template_escape = {"\\": "\\\\", "\n": "\\n", "\r": "\\r", "'": "\\'"},
  render_escape = {'&': '&amp;', '"': '&quot;', '<': '&lt;', '>': '&gt;'};

function default_escape_fn(str, key) {
  return str == null ? '' : (str+'').replace(/[&\"<>]/g, function(char) {
    return render_escape[char];
  });
}

riot.render = function(tmpl, data, escape_fn) {
  if (escape_fn === true) escape_fn = default_escape_fn;
  tmpl = tmpl || '';

  return (FN[tmpl] = FN[tmpl] || new Function("_", "e", "return '" +
    tmpl.replace(/[\\\n\r']/g, function(char) {
      return template_escape[char];
    }).replace(/{\s*([\w\.]+)\s*}/g, "' + (e?e(_.$1,'$1'):_.$1||(_.$1==null?'':_.$1)) + '") + "'")
  )(data, escape_fn);
};

    3、route函数 

    route函数的参数是一个回调函数,用来在”页面加载“时触发。

    这段代码比较有意思。

pops = riot.observable({})

    先通过observable函数定义一个”临时model“,用来可以订阅和发布事件(这里主要是页面加载事件)。

// listen
    if (typeof to === "function") return pops.on("pop", to);

    通过route函数,传入回调函数to,定义pops上得”pop“事件,回调函数为to。

  function pop(hash) {
    hash = hash.type ? location.hash : hash;
    if (hash !== currentHash) pops.trigger("pop", hash);
    currentHash = hash;
  }

  /* Always fire pop event upon page load (normalize behaviour across browsers) */

  // standard browsers
  if (listen) {
    listen("popstate", pop, false);
    doc.addEventListener("DOMContentLoaded", pop, false);

  // IE
  } else {
    doc.attachEvent("onreadystatechange", function() {
      if (doc.readyState === "complete") pop("");
    });
  }

    监听页面的加载事件,然后触发”pop“事件。

    下面是整个route函数的相关代码:

/* Cross browser popstate */
(function () {
  // for browsers only
  if (typeof window === "undefined") return;

  var currentHash,
    pops = riot.observable({}),
    listen = window.addEventListener,
    doc = document;

  function pop(hash) {
    hash = hash.type ? location.hash : hash;
    if (hash !== currentHash) pops.trigger("pop", hash);
    currentHash = hash;
  }

  /* Always fire pop event upon page load (normalize behaviour across browsers) */

  // standard browsers
  if (listen) {
    listen("popstate", pop, false);
    doc.addEventListener("DOMContentLoaded", pop, false);

  // IE
  } else {
    doc.attachEvent("onreadystatechange", function() {
      if (doc.readyState === "complete") pop("");
    });
  }

  /* Change the browser URL or listen to changes on the URL */
  riot.route = function(to) {
    // listen
    if (typeof to === "function") return pops.on("pop", to);

    // fire
    if (history.pushState) history.pushState(0, 0, to);
    pop(to);

  };
})();

 

转载于:https://my.oschina.net/yck108/blog/348315

 类似资料: