美文网首页
解释器模式

解释器模式

作者: 小宇cool | 来源:发表于2020-11-08 11:51 被阅读0次

    1. 解释器模式

    1.1 定义:

    解释器模式(Interpreter) : 定义一种文法的表示,并定义一种解释器, 通过这个解释器类解析对应的文法内容.

    1.2 作用

    1. 利用解释器类解析文法中表示的想要的意图,解决并实现对应的需求.
    2. 将一些特定类型的问题, 提供一种更简单的文法表示, 来解决对应的问题.
    3. 将一些重复出现的问题,用一种简单的语言来进行表达.

    1.3应用场景

    • 场景一 Jq提供了选择器

    我们都知道原生js获取DOM元素的方式是有限的,而Jq给我们提供了更为复杂的复杂方式, 比如:$("#box>p:odd"),这个参数规则就是Jq定义的一套选择元素的文法, 而最终解析这个字符串, 使得我们可以获取对应的DOM元素的代码实现就是通过解释器模式来完成的.

    假设我们想实现上面的$("#box>p:odd"), 我们可以简单的模拟一下

     function $(selector){
         if(selector.includes(':odd')){
             const [select] = selector.split(':');
             let eleList = document.querySelectorAll(select);
             return  [...eleList].filter((ele, index) => (index + 1) % 2 === 1)
         }else{
             return document.querySelectorAll(selector)
         }
     }
    

    还有我们经常会使用到的emmet语法, 我们可以通过在编辑器输入div>p*4{12}这种类型的字符串快速生成对应的HTML结构代码. 其实用的就是解释器模式,我们也可以简单的模拟实现一下.

     function createDom(ruleStr) {
         let fragment = document.createDocumentFragment();
         let reg = /([a-z]+)>([a-z]+)\*(\d)\{(.+?)\}/i,
             res = ruleStr.match(reg);
         let rootEle = document.createElement(res[1]);
         /*
            利用字符串的repeat将字符串扩展为指定长度并通过split切割为数组
            方便遍历对应的子元素
         */
         "*".repeat(res[3]).split('').forEach(item =>{
             let p = document.createElement(res[2])
             p.textContent = res[4]
             rootEle.append(p)
         })
         fragment.append(rootEle)
         return fragment
     }
    let dom =  createDom('div>p*4{这是一个p标签}');
    //渲染到页面上
    document.body.appendChild(dom)
    
    • 场景二 获取某个标签的DOM父级结构
      let getPath = (function(){
          // 获取与DOM元素标签名相同的同级DOM元素个数
          function getSiblingsCount(dom){
              let count = 0;// 记录个数
              // 记录当前兄弟节点的标签名, toLowerCase将小写转为大写
              let nodeName = dom.nodeName.toLowerCase();
              while(dom){
                  // 如果相等则count++
                  if(dom.nodeName.toLowerCase() === nodeName){
                      count++
                  }
                  // 查找上一个兄弟节点
                  dom = dom.previousElementSibling;
              }
              // 返回对应个数的字符串, 通过拼接字符串将数字转为正常
              return count === 1 ? "" : count+"";
          }
          return function(dom){
              // 限制措参数的类型
              if (!(dom instanceof HTMLElement)) throw new Error("参数不是DOM节点");
              // 最终返回的DOM路径结果
              let path = [];
              // 如果上一个节点不为document则一直查找父节点
              while(dom !== document){
                  //从数组的前面追加对应的结果
                  path.unshift(dom.nodeName.toLowerCase()+getSiblingsCount(dom));
                  dom = dom.parentNode;
              }
             return path
          }
      })()
    

    假设我们在HTML文档body内有如下结构的HTML代码

     <div id="box">
            <p>1</p>
            <p>2</p>
            <div></div>
            <p class="age"></p>
    </div>
    

    我们可以简单测试一下

    console.log(getPath(document.querySelector('.age')))
    //["html", "body", "div", "p3"]
    

    总结: 解释器模式是一种非常灵活的行为型设计模式, 这种模式使得我们可以在语言的基础上定义新的文法并进行解释.使得我们可以通过简单的文法实现某些特定类型的问题和需求,它的可扩展性比较好,缺点就是使用场景比较少,对于复杂的文法比较难以维护.通常只会在特定的应用场景才会使用到.

    相关文章

      网友评论

          本文标题:解释器模式

          本文链接:https://www.haomeiwen.com/subject/vnxhbktx.html