vue實例的常用選項(一)-methods、computed、filters、watch、props

我們先來總結一下前面已經認識的選項
el:指定Vue實例的掛載點,根實例的特有屬性
data:用於聲明需要響應式綁定的數據對象
components:Vue實例配置局部註冊組件
template:用於掛載元素的字符串模板
render:渲染函數,創建虛擬DOM,是字符串模板的替代方案。

現在開始一個例子介紹一下其他常用的選項(options對象的屬性):
在這裏插入圖片描述
下面的代碼局部註冊了一個組件AgeStatistics,並把數據渲染到模板中

<div id="app">
  <age-statistics  inline-template>
    <div>
      <h1>**{{title}}</h1>
      <table border="1">
        <tr>
          <th>編號</th><th>姓名</th><th>年齡</th>
        </tr>
        <tr v-for="(item,i) in list">
          <td>{{i+1}}</td><td>{{item.name}}</td><td>{{item.age}} </td>
        </tr>
      </table>
      <p>平均年齡:avg</p>
      <div class="formGroup">
        <input ref="name" type="text" v-model="currentPerson.name" placeholder="請填寫姓名">
        <input ref="age" type="text" v-model="currentPerson.age" placeholder="請填寫年齡">
        <button>添加</button>
      </div>
    </div>
  </age-statistics>
</div>
<script src="./vue.js"></script>
<script>
  let vm = new Vue({
    el: "#app",
    data:{
      title:'三年五班'
    },
    components: {
      'AgeStatistics':{
        data() {
          return {
            title:'學員統計',
            list:[
              {name:'張三',age:18},
              {name:'李四',age:19}
            ],
            currentPerson:{}
          }
        }
      }
    }
  });
</script>

在這裏插入圖片描述

methods:用於定義Vue實例的方法

methods選項是個對象,在其內部可以定義方法。
下面我們給button的click事件綁定一個方法add,組件的options種添加methods屬性,實現點擊按鈕時新增一條記錄

<button v-on:click="add">添加</button>
methods:{
  add(e){
    console.log(e);
    console.log(event);
    let _currentPerson = JSON.parse(JSON.stringify(this.currentPerson));
    this.currentPerson={};
    this.list.push(_currentPerson);
  }
},          

方法的參數
方法中可以獲得綁定的事件event,綁定事件方法時:

  • 如果不包含(),默認的參數是event,即上面代碼中的e和event都指向事件對象;
  • 如果包含(),參數e就是add傳遞的參數,如上面綁定的是add(),e即爲undefined。

computed:計算屬性

模板內的表達式可以用於簡單運算,對於複雜的計算應當使用實例的計算屬性computed
下面在computed中定義一個方法avg,顯示到平均年齡處

<p>平均年齡:{{avg}}</p>
//計算屬性
computed:{
  avg(){
    console.log('計算屬性avg執行了');
    let sum=this.list.reduce((sum, data) => {
      return sum + parseInt(data.age);
    }, 0);
    return sum/this.list.length
  }
},

在這裏插入圖片描述

計算屬性對於從現有源組合新數據非常方便,與方法相比,它們的一大優點是緩存了輸出。
即:如果獨立於計算屬性的某些內容在頁面上發生更改,並且重新呈現UI。
computed中的方法會返回緩存的結果,不會重新計算;
methods中方法中會重新執行。
如在上例的methods增加一個方法avg2,來比較一下

<p>平均年齡:{{avg}}{{avg2()}}</p>
avg2(){
  console.log('方法avg2執行了');
  let sum=this.list.reduce((sum, data) => {
    return sum + parseInt(data.age);
  }, 0);
  return sum/this.list.length
}

在這裏插入圖片描述
通過這個例子可以發現實現相同的功能methods中的方法代價更高。
另外你注意到了嗎,在模板中調用它們的方式也不一樣,在控制檯中,我們發現avg是個屬性,它的形式和data中的數據類似,但不擁有訪問器屬性get/set,而avg2是一個方法,所以avg2可以傳參;
在這裏插入圖片描述
但avg如果要傳參,需要使用閉包將屬性值改爲一個函數

<p>平均年齡:{{avg(2)}}</p>
computed:{
 avg(){
   return function (decimals) {
     let sum=this.list.reduce((sum, data) => {
       return sum + parseInt(data.age);
     }, 0);
     return sum/this.list.length.toFixed(decimals);
   }
 }
},

在這裏插入圖片描述

filters:過濾器

Vue.js 允許自定義過濾器,用於一些常見的文本格式化。

  • 過濾器可以用在兩個地方:雙花括號插值和 v-bind 表達式 (後者從 2.1.0+ 開始支持)。
  • 過濾器應該被添加在JS表達式的尾部,由“管道”符號連接。
  • 過濾器函數始終以表達式的值作爲第一個參數。帶引號的參數視爲字符串,而不帶引號的參數按表達式計算。
  • 模板中調用過濾器函數時如果使用了參數,順序稱爲過濾器函數的第二、三…個函數
  • 可以添加多個過濾器

如前面的例子中,如果需要格式化平均年齡,保留一位小數點,可以這樣做:

<p>平均年齡:{{avg | formatAge(1,'something')}}</p>
//過濾器
filters:{
  formatAge(val,decimals){
    return val.toFixed(decimals);
  }
},

也可以全局定義過濾器,定義的方法和全局註冊組件類似,要放到Vue實例化之前,如:

Vue.filter('formatAge', function (val) {
  return val.toFixed(1);
})

watch:偵聽屬性

偵聽屬性watch的作用可以監控 Vue 實例上的數據變動,並調用其回調函數。
如:在watch中偵聽數據title和currentPerson的變化,一旦變化就執行回調,其回調函數有兩個參數,新值和舊值,如果偵聽的數據是數組或對象,新值和舊值打印的結果是一樣的。

watch: {
  title(val, oldVal){
    console.log(`監聽到了title的變化:${oldVal}->${val}`);
  },
  currentPerson(val, oldVal) {
    console.log('監聽到了currentPerson的數據變動', val.age, oldVal.age);
  },
}

handler方法和immediate屬性

watch 中的方法最初綁定的時候是不會執行,如果希望一開始就讓他最初綁定的時候就執行改怎麼辦呢?我們需要修改一下我們的 watch中title的監聽方法,修改過後的代碼如下:

/*title(val, oldVal){
  console.log(`監聽到了title的變化:${oldVal}->${val}`);
},*/
title:{
   handler(val, oldVal){
      console.log(`監聽到了title的變化:${oldVal}->${val}`);
    },
    immediate:true
  }

title綁定了一個handler方法,也就是設置回調函數,之前寫的 watch方法其實默認寫的就是這個handler。

深度監聽 deep屬性

watch 裏面還有一個屬性 deep,默認值是 false,代表是否深度監聽,如在本例中currentPerson初次賦值時能夠被handler監聽到,重新賦值時監聽不到,使用deep屬性能夠實現深度的監聽。

currentPerson: {
  handler(val,oldVal){
    console.log('監聽到了queryString的變化:',val.age,oldVal.age)
  },
  deep: true
},

props:用於接收來自父組件的數據

組件實例的作用域是孤立的。在子組件的模板內不能直接引用父組件的數據。父組件的數據需要通過 Prop 才能下發到子組件中,使用選項props申明該組件可接受的 prop 列表。

Prop可以理解爲在組件上註冊的一些自定義屬性,這些屬性的值可以通過組件的props選項接收到。

在本例中,在組件AgeStatistics中希望①獲得根組件的數據title②獲得靜態屬性bg-color,可以這樣傳遞屬性:
PS:html模板中屬性要使用短橫線分隔命名法(kebab-case)命名

<age-statistics v-bind:unit="title" bg-color="gray" inline-template>
...
  <h1 :style="{backgroundColor: bgColor}">{{unit}}{{title}}</h1>
...
</age-statistics>

在組件實例的props選項中申明從父組件接受屬性unit、bgColor。

props:['unit','bgColor'],

單向數據流:父級 prop 的更新會向下流動到子組件中,但是反過來則不行;每次父級組件發生更新時,子組件中所有的 prop 都將會刷新爲最新的值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章