模板引擎-vue中的模板如何被解析,指令如何處理


模板是什么
<div id='app'>
  <div>
    <input v-model="title"/>
    <button v-on:click="add">submit</button>
  </div>
  <ul>
    <li v-for="item in list">
      {{item}}
    </li>
  </ul>
</div>

這是模板,那么模板是什么呢?

1、本質是字符串,是以字符串存在的,只不過像html
2、 有邏輯,比如判斷,循環這些,如v-if,v-for等,怎么會有邏輯呢,之前寫html就沒邏輯
3、與html格式很像,但有很大區別。首先 html在語法上是不認識v-if,v-for這些的。第二個是html是靜態的,沒有邏輯, vue是動態的,有邏輯的。它們只是格式很像
4、但是最終模板還是要轉換為html來顯示的。那么他是怎么做到的呢?



首先模板最終必須轉換成js代碼,因為:
第一個模板有邏輯,有v-if,v-for。必須用js才能實現(圖靈完備的語言)
第二個模板要轉化為html渲染頁面,必須用js才能實現
因此,模板最終要轉換成一個js函數(render函數,也就是渲染函數)

 

首先了解下with
var obj = {
  name: 'zhangsan',
  age: 20,
  getAddress: function(){
    alert('beijing');
  }
}

// 不用with
function fn(){
  alert(obj.name);
  alert(obj.age);
  obj.getAddress();
}
fn();

// 使用width
function fn1(){
  with(obj){
    alert(name);
    alert(age);
    getAddress();
  }
}
fn1();

在實際開發中,盡量不要使用with。fn是我們正常的使用。fn1使用with的情況。兩是同樣的效果,用with的里面,都不寫是誰的屬性,是誰統一的用with包起來。這個可讀性可能沒那么強。

 

我們看最簡單的一段模板
<div id="app">
  <p>{{price}}</p>
</div>

這個模板最終生成的函數是下面這個

 

/**
* _c : 創建dom標簽
* _v : 創建文本節點
* _s : toString
*/
function render(){
  with(this){ // this 就是 vm
    return _c(
      '<div>',
      {
        attrs:{"id":"app"}
      },
      [
        _c('p',[_v(_s(price))])
      ]
    )
  }
}

這個this就是vm這個實例,這個_c就是vm._c,用來創建dom標簽的。第一個參數是個div。第二個參數是個對象,對象里面有屬性。第三個參數是個數組,數組里面只有一個元素,這個_c肯定也是vm._c。這個_c第一個參數是p,第二個參數是個數組,里面也是一個數組,_v(_s(price)),這里面的price肯定是vm.price,就是data.price。然后前面的_s就是vm._s,就是toString函數。_v也是vm._v,用來創建文本節點的。

 

總結:
模板中所有信息都包含在render函數中。
this即vm
price即this.price即vm.price即data.price。
_c即this._c即vm._c



render函數
從哪里可以看到render函數?
看一下todo-list demo的render函數
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <!-- 模板 -->
  <div id="app">
    <input v-model='title'/>
    <button v-on:click='add'>submit</button>
    <ul v-for='item in list'>
      {{item}}
    </ul>
  </div>
    
  <!-- 源碼 -->
  <script src="./vue-2.6.10.js"></script>
  <script>
    var data = {
      title: '',
      list: []
    }
    // 初始化 vue 實例
    var vm = new Vue({
      el: '#app',
      data: data,
      methods: {
        add: function(){
          this.list.push(this.title);
          this.title = ''
        }
      }
    })
  </script>
</body>
</html>

 

然后通過這個例子,看看vue的render函數是什么樣子的,在源碼搜索code.render,然后打印出來
with(this) {
  return _c('div', 
        {           attrs: {             
"id": "app"           }         },         [           _c('input',
            {               directives: [{
// 當title發生變化,會賦值給value,從而響應到input                 name: "model",                 rawName: "v-model",                 value: (title),                 expression: "title"               }],               domProps: {                 "value": (title)               },               on: { // input里面的數據改變,事件監聽到,會賦值給 title                 "input": function($event) {                   if ($event.target.composing) return;                   title = $event.target.value                 }               }             }),             _v(" "),             _c('button',               {                 on: {                   "click": add                 }               },               [_v("submit")]             ),             _v(" "),             _l(               (list),               function(item) {                 return _c('ul', [_v("\n " + _s(item) + "\n ")])               }             )         ], 2)       }

是這個樣子的。這就是這個demo所對應的render函數。在創建input的時候第二個參數有個directives。叫做指令,指令名字是model。value是title,也就是vm.title。后面_v(''),_v表示創建文本節點,主要是input和button有個換行,如果不換行,就不會有_v去創建一個空的文本節點。_l就是一個數組,針對list返回li的標簽。

 

 


免責聲明!

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



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