4.計算屬性

在模板中綁定表達式是非常便利的描姚,但是它們實際上只用于簡單的操作轰胁。在模板中放入太多的邏輯會讓模板過重且難以維護赃阀。例如:

<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

在這種情況下擎颖,模板不再簡單和清晰。在實現(xiàn)反向顯示 message 之前搂捧,你應該確認它允跑。這個問題在你不止一次反向顯示 message 的時候變得更加糟糕。這就是為什么任何復雜邏輯索烹,你都應當使用計算屬性弱睦。

基礎(chǔ)例子

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // a computed getter
    reversedMessage: function () {
      // `this` points to the vm instance
      return this.message.split('').reverse().join('')
    }
  }
})

結(jié)果:

Original message: "Hello"
Computed reversed message: "olleH"

這里我們聲明了一個計算屬性 reversedMessage 况木。我們提供的函數(shù)將用作屬性 vm.reversedMessage 的 getter 。

console.log(vm.reversedMessage) // -> 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // -> 'eybdooG'

你可以打開瀏覽器的控制臺求类,修改 vm 屹耐。 vm.reversedMessage 的值始終取決于 vm.message 的值尸疆。

你可以像綁定普通屬性一樣在模板中綁定計算屬性仓技。 Vue 知道 vm.reversedMessage 依賴于 vm.message 俗他,因此當 vm.message 發(fā)生改變時兆衅,依賴于 vm.reversedMessage 的綁定也會更新。而且最妙的是我們是聲明式地創(chuàng)建這種依賴關(guān)系:計算屬性的 getter 是干凈無副作用的羡亩,因此也是易于測試和理解的畏铆。

計算緩存 vs Methods

你可能已經(jīng)注意到我們可以通過調(diào)用表達式中的method來達到同樣的效果:

<p>Reversed message: "{{ reverseMessage() }}"</p>
// in component
methods: {
  reverseMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

不經(jīng)過計算屬性,我們可以在 method 中定義一個相同的函數(shù)來替代它楷怒。對于最終的結(jié)果鸠删,兩種方式確實是相同的。然而刃泡,不同的是計算屬性是基于它的依賴緩存烘贴。計算屬性只有在它的相關(guān)依賴發(fā)生改變時才會重新取值撮胧。這就意味著只要 message 沒有發(fā)生改變,多次訪問 reversedMessage 計算屬性會立即返回之前的計算結(jié)果馒闷,而不必再次執(zhí)行函數(shù)叁征。

這也同樣意味著如下計算屬性將不會更新功咒,因為 Date.now() 不是響應式依賴:

computed: {
  now: function () {
    return Date.now()
  }
}

相比而言勘纯,每當重新渲染的時候,method 調(diào)用總會執(zhí)行函數(shù)。

我們?yōu)槭裁葱枰彺娉岬校考僭O(shè)我們有一個重要的計算屬性 A 蚯涮,這個計算屬性需要一個巨大的數(shù)組遍歷和做大量的計算。然后我們可能有其他的計算屬性依賴于 A 张峰。如果沒有緩存棒旗,我們將不可避免的多次執(zhí)行 A 的 getter !如果你不希望有緩存饶深,請用 method 替代粥喜。

計算屬性 vs Watched Property

Vue.js 提供了一個方法 $watch 橘券,它用于觀察 Vue 實例上的數(shù)據(jù)變動。當一些數(shù)據(jù)需要根據(jù)其它數(shù)據(jù)變化時锋华, $watch 很誘人 —— 特別是如果你來自 AngularJS 毯焕。不過磺樱,通常更好的辦法是使用計算屬性而不是一個命令式的 $watch 回調(diào)。思考下面例子:

<div id="demo">{{ fullName }}</div>
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})

上面代碼是命令式的和重復的芜辕。跟計算屬性對比:

var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})

這樣更好侵续,不是嗎?

計算 setter

計算屬性默認只有 getter 需五,不過在需要時你也可以提供一個 setter :

// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...

現(xiàn)在在運行 vm.fullName = 'John Doe' 時轧坎, setter 會被調(diào)用眶根, vm.firstName 和 vm.lastName 也會被對應更新边琉。

觀察 Watchers

雖然計算屬性在大多數(shù)情況下更合適,但有時也需要一個自定義的 watcher 族扰。這是為什么 Vue 提供一個更通用的方法通過 watch 選項定欧,來響應數(shù)據(jù)的變化渔呵。當你想要在數(shù)據(jù)變化響應時扩氢,執(zhí)行異步操作或昂貴操作時爷辱,這是很有用的。

例如:

<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
<!-- Since there is already a rich ecosystem of ajax libraries    -->
<!-- and collections of general-purpose utility methods, Vue core -->
<!-- is able to remain small by not reinventing them. This also   -->
<!-- gives you the freedom to just use what you're familiar with. -->
<script src="https://unpkg.com/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://unpkg.com/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
  el: '#watch-example',
  data: {
    question: '',
    answer: 'I cannot give you an answer until you ask a question!'
  },
  watch: {
    // 如果 question 發(fā)生改變双饥,這個函數(shù)就會運行
    question: function (newQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.getAnswer()
    }
  },
  methods: {
    // _.debounce 是一個通過 lodash 限制操作頻率的函數(shù)弟断。
    // 在這個例子中阀趴,我們希望限制訪問yesno.wtf/api的頻率
    // ajax請求直到用戶輸入完畢才會發(fā)出
    // 學習更多關(guān)于 _.debounce function (and its cousin
    // _.throttle), 參考: https://lodash.com/docs#debounce
    getAnswer: _.debounce(
      function () {
        var vm = this
        if (this.question.indexOf('?') === -1) {
          vm.answer = 'Questions usually contain a question mark. ;-)'
          return
        }
        vm.answer = 'Thinking...'
        axios.get('https://yesno.wtf/api')
          .then(function (response) {
            vm.answer = _.capitalize(response.data.answer)
          })
          .catch(function (error) {
            vm.answer = 'Error! Could not reach the API. ' + error
          })
      },
      // 這是我們?yōu)橛脩敉V馆斎氲却暮撩霐?shù)
      500
    )
  }
})
</script>

結(jié)果:

Ask a yes/no question:  
?

Yes

在這個示例中刘急,使用 watch 選項允許我們執(zhí)行異步操作(訪問一個 API)棚菊,限制我們執(zhí)行該操作的頻率,并直到我們得到最終結(jié)果時排霉,才設(shè)置中間狀態(tài)窍株。這是計算屬性無法做到的民轴。

除了 watch 選項之外,您還可以使用 vm.$watch API 命令球订。

綜合上述內(nèi)容后裸,具體例子如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>level03</title>
<script type="text/javascript" src="js/vue.2.1.0.js"></script>
</head>
<body>
<div id="app">
    <p>
        firstName:{{firstName}}
    </p>
    <p>
        lastName:{{lastName}}
    </p>
    <p>
        fullName:{{fullName}}
    </p>
    <!--萬能的文本編輯器-->
    <p>
        fullNameMethod:{{fullNameMethod()}}
    </p>
</div>
<script type="text/javascript">

var app = new Vue({
    el:'#app'
    ,data:{
        firstName:'wen'
        ,lastName:'quan'
    }
    ,methods:{
        fullNameMethod:function(){
            return this.firstName + " " +this.lastName
        }
    }
    //觀察選項
    ,watch:{
        firstName:function(){
            console.log("firstName 發(fā)生過改變")
        }
    }
    //計算單位
    ,computed:{
        fullName:function(){
            return this.firstName + " " +this.lastName
        }
    }
});

setTimeout(function(){
    app.firstName = "wang";
    app.lastName = "Xue shi";
},5000);

</script>
</body>
</html>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市冒滩,隨后出現(xiàn)的幾起案子微驶,更是在濱河造成了極大的恐慌,老刑警劉巖开睡,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件篇恒,死亡現(xiàn)場離奇詭異款筑,居然都是意外死亡奈梳,警方通過查閱死者的電腦和手機攘须,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門限煞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來署驻,“玉大人,你說我怎么就攤上這事宣吱≌骱颍” “怎么了兆解?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵历谍,是天一觀的道長望侈。 經(jīng)常有香客問我扛点,道長眠饮,這世上最難降的妖魔是什么仪召? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮运褪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘雅倒。我一直安慰自己劣欢,他們只是感情好年鸳,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布灭忠。 她就那樣靜靜地躺著涕蜂,像睡著了一般机隙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上葱跋,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天荠卷,我揣著相機與錄音,去河邊找鬼屑彻。 笑死,一個胖子當著我的面吹牛搏恤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播搞莺,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了岁歉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年逸尖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纯衍。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡歌亲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出杂穷,到底是詐尸還是另有隱情飞蚓,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布著榴,位于F島的核電站,受9級特大地震影響叔壤,放射性物質(zhì)發(fā)生泄漏妄田。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一鲁冯、第九天 我趴在偏房一處隱蔽的房頂上張望撞芍。 院中可真熱鬧衡创,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挨稿。三九已至京痢,卻和暖如春奶甘,著一層夾襖步出監(jiān)牢的瞬間方淤,已是汗流浹背携茂。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工医吊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留草描,地道東北人。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像乙濒,于是被迫代替她去往敵國和親贵试。 傳聞我的和親對象是個殘疾皇子琉兜,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對于 Vue 1.0 印象不深的內(nèi)容毙玻。關(guān)于...
    云之外閱讀 5,052評論 0 29
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理豌蟋,服務發(fā)現(xiàn),斷路器桑滩,智...
    卡卡羅2017閱讀 134,699評論 18 139
  • 摘要: {{ number + 1 }} {{ ok ? 'YES' : 'NO' }} {{ message.s...
    吳高亮閱讀 7,032評論 1 10
  • 1.安裝 可以簡單地在頁面引入Vue.js作為獨立版本梧疲,Vue即被注冊為全局變量,可以在頁面使用了运准。 如果希望搭建...
    Awey閱讀 11,034評論 4 129
  • 他慌慌張張地拐進一條小巷幌氮,呼吸急促,身后那雙眼睛窮追不舍胁澳。他不知道還能做些什么该互,才能逃避他的追蹤。 那雙眼睛更像一...
    舟啊粥粥閱讀 557評論 0 1