SS - DIY一個前端模板引擎.(一)


前端MVVM 模式有點很多,完全擺脫了意大利面條式的代碼。
個人認為,所有MVVM 的框架基礎就是一個高性能的JS模板引擎,它極大簡化了 DOM 操作, 使頁面渲染和業務邏輯徹底分離.
為了理解模板引擎原理(zhaungbi),所以我折騰了一個簡化版的模板引擎.可以實現數據綁定,三元表達式, for 循環和 if 判斷.
如何實現三元表達式, for 循環和 if 判斷,將在下一篇介紹.

HTML 模板

下面是我定義好的html 模板字符串。

var template = `
<div>
    <span>
    {{number}}
    </span>
</div>
`;

這是我的數據

var scope ={
    number:10
}

好了,現在怎么把數據渲染到模板上面呢?

很自然的想到 正則表達式

正則替換

第一步 ,可以使用字符串的replace 函數。
這是正則

   var regex = /\{\{([A-Za-z_\$]+[A-Za-z0-9_\$]*)\}\}/g;

好了,現在編寫一個函數,我把我的模板引擎就叫 SS。

var SS = (function() {
  var regex = /\{\{([A-Za-z_\$]+[A-Za-z0-9_\$]*)\}\}/g;
  var result = "";

  var ss = {};
  ss.Render = function(template, scope) {
    result = template.replace(regex, function(a, b) {
      b = b.trim();
      return scope[b];
    })
    return result;
  }
  return ss;
})()

測試一下

SS.Render(template,scope);

這是結果

但是,僅僅渲染一級屬性的模板引擎有什么用呢?

渲染多級屬性

在這里,渲染多級屬性還是分為兩種。

  • 變量屬性 (不知道這么稱是否准確,就是類似於 person.name)
  • 數組屬性 (數組元素,key 必須是數字類型)

這里,先解決變量屬性

變量屬性

首先,需要一個新的正則表達式

      var regex = /\{\{([A-Za-z_\$]+(\.[A-Za-z_\$]+|[A-Za-z0-9_\$])*)\}\}/g;

正則寫的很爛,如果發現錯誤希望不吝賜教

html 模板

var template = 
`
<div>
    {{title}}
    <ul>
        <li>{{item.name}}</li>
        <li>{{item.age}}</li>
    <ul/>
<div>
`

按照上面模板匹配的數據

var scope = { 
   title:"hello",
   item:{
    name:'pawn',age:15
    }
}

渲染函數

ss.Render = function(template, scope) {
    result = template.replace(regex, function($, $1) {
        $1 = $1.trim();
        var innerdata = scope;
        var items = $1.split('.');
        for (var i = 0; i < items.length; i++) {
            innerdata = innerdata[items[i]];
        }
        return innerdata;
    });

    return result;
}

在這里考慮到元素的屬性,所以將{{}} 中包含字符'.' 也匹配出來,再使用'.'分割,然后依次向下尋找

測試代碼

var res = ss.Render(template, scope);
console.log(res);

這是結果:

貌似這個模板引擎已經具有雛形了

數組屬性

在這里,要是正則能夠匹配上[] ,而且里面必須是數字

 var regex = /\{\{([A-Za-z_\$]+(\[\d+\]+|\.[A-Za-z_\$]+|[A-Za-z0-9_$])*)\}\}/g;

這個正則主要是匹配形如 items[0].name 類型.
變量名必須是字母下划線或者$ 符號打頭,后面必須是 [],.[A-Za-z_$] 或者
[A-Za-z0-9_$]

如果正則有錯,還忘各位不吝賜教.

形如,items[0].name.a.b 中,可以使用'.' 來分割字符串,然后進行迭代找到最終數據.
在每一次迭代中,可以使用 /[\d+]/.test(items[i]) 來判斷是否包含'[]',如果包含,那么使用/[\d+]/循環匹配取出其中每一項.

總體代碼就是這樣

  ss.Render = function (template, scope) {
        result = template.replace(regex, function ($, $1) {
            $1 = $1.trim();
            var innerdata = scope;
            var items = $1.split('.');

            for (var i = 0; i < items.length; i++) {
                var m;
                if (/\[\d+\]/.test(items[i])) {
                    innerdata = innerdata[items[i].split('[')[0]];
                    var reNumber = /\[(\d+)\]/g;
                    while (m = reNumber.exec(items[i])) {
                        innerdata = innerdata[m[1]];
                    }
                }
                else {
                    innerdata = innerdata[items[i]];
                }
            }
            return innerdata;
        });

html 模板

var template =
    `<div>
    {{title}}
    <ul>
        <li>
           name:{{items[0].name}}
           <br />
            age:{{items[0].age}}
           <br />
            sex:{{items[0].sex}}
        </li>
         <li>
           name:{{items[1].name}}
           <br />
            age:{{items[1].age}}
           <br />
            sex:{{items[1].sex}}
        </li>
    <ul/>
<div>
`;

模板數據

var scope = {
    title: "person list",
    items: [{
        name: 'pawn',
        age: 21,
        sex: 1
    }, {
            name: 'jk',
            age: 30,
            sex: 0
        },]

}

測試

console.log(SS.Render(template, scope));

結果

結束

SS 模板中簡單的數據綁定就已經實現.
在 SS 前端模板引擎.(二) 中會插入 三元表達式,for循環和if條件判斷


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM