Darth_EF 发表于 2021-4-28 17:06:15

hash监听者,类似前端路由的东西

如题。
HashCaller当触发超链接或者url的hash变动时查找是否有对应的监听者,然后将触发监听者的执行函数。
将重渲染界面的代码放到监听者的执行函数即可实现类似前端路由的东西。(话说以前我和朋友都叫这种操作叫无刷新跳转而不是叫路由)
非常简单的东西,楼下放代码,有爱自取。
或者查看我的js库,里面还有其他有用的东西: https://gitee.com/darth_ef/def-web/blob/master/js/Basics.js
使用例: https://gitee.com/darth_ef/def-web/blob/master/page/index.js

Darth_EF 发表于 2021-4-28 18:22:02

caller类 和 重载超链接标签触发事件

/**
* 点击站内链接调用的函数, 另链接不跳转而是成为锚点链接
*/
function linkClick(e,tgt){
    var _event=e||event;
    var tgt=tgt||this;
    var linkTarget=tgt.getAttribute("target");
    var tempStr;
    if(tgt.host==window.location.host){
      // var hostchar=this.pathname.slice(this.pathname.indexOf('/')+1,this.pathname.slice(this.pathname.indexOf('/')+1).indexOf('/')+1);
      switch (_event.button){
            case 0:
                if((!linkTarget||linkTarget=='_self')&&(!e.ctrlKey)){
                  window.location.href='#/'+tgt.href.substr(tgt.href.indexOf(tgt.host)+(tgt.host.length)+1);
                  stopPE(e);
                  // if(tempStr=tgt.getAttribute("title")){
                        //   window.document.title=tempStr;
                        // }
                        hashcaller.touchHashListener();
                  return false;
                }
            break;
            case 1:
                // window.open(this.getAttribute('href'));
            break;
            default:
                break;
            }
      }
}
/**
* 让站内链接失效 链接不跳转而是成为锚点链接
*/
function setupLinkClick(){
    document.addEventListener("click",function(e){
      var tgt=e.target;
      while(tgt.tagName!="HTML"){
            if(tgt.tagName=="A"){
                linkClick(e,tgt);
                break;
            }
            tgt=tgt.parentElement;
      }
    });
}
/**
* Hashcaller
*/
class Hashcaller{
    constructor(onlyTouchOne=true){
      this.listeners=[];
      /**如果冲突(有多个能够匹配到的表达式)仅取下标大的监听者触发 */
      this.onlyTouchOne=onlyTouchOne;
      this.lastListenerIndex=-1;
      var that=this;
      window.addEventListener("hashchange",function(){that.touchHashListener()});
    }
    /**
   * 添加一个监听者对象 后添加的会比前面的更优先
   * @param {HashListener} listener
   */
    add(listener){
      this.listeners.push(listener);
    }
    /**
   * 添加一个监听者对象数组
   * @param {Array<HashListener>} listeners
   */
    addList(listeners){
      for(var i=listeners.length-1;i>=0;--i){
            this.add(listeners);
      }
    }
    /**
   * 触发 location.hash
   */
    touchHashListener(){
      if((typeof window.lowhash!='undefined')&&(window.lowhash!=location.hash)){
            var regex;
            for(var i=this.listeners.length-1;i>=0;--i)
            if(regex=this.listeners.exec(location.hash)){
                this.listeners.listener(regex);
                this.lastListenerIndex=i;
                if(this.onlyTouchOne)break;
            }
      }
      window.lowhash=location.hash;
    }
}
/**
* HashListener obj
*/
class HashListener{
    /**
   * @param {RegExp} regExp       hash的正则表达式
   * @param {Function} listener   监听者 调用时会引用 regExp 的 regex
   * @param {Boolean} filterFlag选择是否过滤 hash 中的 /^#\// 默认为过滤
   */
    constructor(regExp,listener,filterFlag=true){
      this.hashSelector=regExp;
      this.listener=listener;
      this.filterFlag=filterFlag;
    }
    /**
   * 测试表达式能否匹配字符串
   * @param {String} _string文本
   */
    exec(_string){
      var string;
      if((this.filterFlag)&&(_string.indexOf("#/")==0)){
            string=_string.slice(2);
      }
      else{
            string=_string;
      }
      return this.hashSelector.exec(string);
    }
}
var hashcaller=new Hashcaller();

食用方法

hashcaller.add(new HashListener(
      /.*/i, //这里放正则表达式匹配url的hash
      show404Page //这里放渲染页面的函数
    ))

wp231957 发表于 2021-4-29 07:01:32

Darth_EF 发表于 2021-4-28 18:22
caller类 和 重载超链接标签触发事件




还是不会用,我后台在跳转路由时,都是带参数渲染,这些参数都咋弄,能给个实例吗

Darth_EF 发表于 2021-4-29 14:21:07

本帖最后由 Darth_EF 于 2021-4-29 14:37 编辑

wp231957 发表于 2021-4-29 07:01
还是不会用,我后台在跳转路由时,都是带参数渲染,这些参数都咋弄,能给个实例吗

示例的话可以看看我一楼放的第二个链接。

闭包写一个渲染某页面的函数作为HashListener的构造函数的参数就好了。
页: [1]
查看完整版本: hash监听者,类似前端路由的东西