Vue計算屬性和偵聽器

計算屬性和偵聽器

計算屬性

模板內(nèi)的表達(dá)式非常便利叙量,但是設(shè)計它們的初衷是用于簡單運算的九串。在模板中放入太多的邏輯會讓模板過重且難以維護猪钮。例如:

                                                                                       HTML
<div id="example">
  {{ message.split('').reverse().join('') }}
</div>
在這個地方谆奥,模板不再是簡單的聲明式邏輯酸些。上面示例是指將變量message字符串翻轉(zhuǎn)

對于任何復(fù)雜邏輯魄懂,你都應(yīng)當(dāng)使用計算屬性闯第。

基礎(chǔ)例子

                                                                                       HTML
<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

computed為計算屬性

                                                                                       JS
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 計算屬性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 實例
      return this.message.split('').reverse().join('')
    }
  }
})

結(jié)果:
Original message: "Hello"
Computed reversed message: "olleH"

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

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

計算屬性 帶有緩存機制 只計算一遍在本頁面 如果不改變內(nèi)容的值不會計算第二遍

你可以打開瀏覽器的控制臺,自行修改例子中的 vm嘹悼。vm.reversedMessage 的值始終取決于 vm.message 的值其监。

你可以像綁定普通屬性一樣在模板中綁定計算屬性限匣。Vue 知道 vm.reversedMessage 依賴于 vm.message膛腐,因此當(dāng) vm.message 發(fā)生改變時哲身,所有依賴 vm.reversedMessage 的綁定也會更新怔揩。而且最妙的是我們已經(jīng)以聲明的方式創(chuàng)建了這種依賴關(guān)系:計算屬性的 getter 函數(shù)是沒有副作用 (side effect) 的商膊,這使它更易于測試和理解宠进。

計算屬性緩存 vs 方法

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

                                                                                       HTML
<p>Reversed message: "{{ reversedMessage() }}"</p>
                                                                                       JS
// 在組件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

我們可以將同一函數(shù)定義為一個方法而不是一個計算屬性实幕。兩種方式的最終結(jié)果確實是完全相同的昆庇。然而整吆,不同的是計算屬性是基于它們的依賴進行緩存的。只在相關(guān)依賴發(fā)生改變時它們才會重新求值乓旗。這就意味著只要 message 還沒有發(fā)生改變欲诺,多次訪問 reversedMessage 計算屬性會立即返回之前的計算結(jié)果扰法,而不必再次執(zhí)行函數(shù)毅厚。

這也同樣意味著下面的計算屬性將不再更新吸耿,因為 Date.now() 不是響應(yīng)式依賴:

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

相比之下咽安,每當(dāng)觸發(fā)重新渲染時妆棒,調(diào)用方法將總會再次執(zhí)行函數(shù)。

我們?yōu)槭裁葱枰彺妫考僭O(shè)我們有一個性能開銷比較大的計算屬性 A澜公,它需要遍歷一個巨大的數(shù)組并做大量的計算坟乾。然后我們可能有其他的計算屬性依賴于 A 糊渊。如果沒有緩存,我們將不可避免的多次執(zhí)行 A 的 getter菱鸥!如果你不希望有緩存殷绍,請用方法來替代主到。

計算屬性 vs 偵聽屬性

Vue 提供了一種更通用的方式來觀察和響應(yīng) Vue 實例上的數(shù)據(jù)變動:偵聽屬性。當(dāng)你有一些數(shù)據(jù)需要隨著其它數(shù)據(jù)變動而變動時,你很容易濫用 watch看锉。然而伯铣,通常更好的做法是使用計算屬性而不是命令式的 watch 回調(diào)腔寡。細(xì)想一下這個例子:

                                                                                       HTML
<div id="demo">{{ fullName }}</div>
                                                                                       JS
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
    }
  }
})

上面代碼是命令式且重復(fù)的。將它與計算屬性的版本進行比較:

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

計算屬性的 setter

計算屬性默認(rèn)只有 getter 犀斋,不過在需要時你也可以提供一個 setter :

                                                                                       JS
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]
    }
  }
}

隨著修改fullName時,set會被調(diào)用firstName和lastName會跟著改變虫几。

偵聽器

雖然計算屬性在大多數(shù)情況下更合適挽拔,但有時也需要一個自定義的偵聽器螃诅。這就是為什么 Vue 通過 watch 選項提供了一個更通用的方法倘是,來響應(yīng)數(shù)據(jù)的變化袭艺。當(dāng)需要在數(shù)據(jù)變化時執(zhí)行異步或開銷較大的操作時猾编,這個方式是最有用的轰传。

                                                                                       HTML
<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
                                                                                       JS
<!-- 因為 AJAX 庫和通用工具的生態(tài)已經(jīng)相當(dāng)豐富绸吸,Vue 核心代碼沒有重復(fù) -->
<!-- 提供這些功能以保持精簡。這也可以讓你自由選擇自己更熟悉的工具叉存。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/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, oldQuestion) {
      this.answer = '正在輸入...'
      this.debouncedGetAnswer()
    }
  },
  created: function () {
    // `_.debounce` 是一個通過 Lodash 限制操作頻率的函數(shù)瓣履。
    // 在這個例子中练俐,我們希望限制訪問 yesno.wtf/api 的頻率
    // AJAX 請求直到用戶輸入完畢才會發(fā)出袖迎。想要了解更多關(guān)于
    // `_.debounce` 函數(shù) (及其近親 `_.throttle`) 的知識腺晾,
    // 請參考:https://lodash.com/docs#debounce
    this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
  },
  methods: {
    getAnswer: function () {
      if (this.question.indexOf('?') === -1) {
        this.answer = 'Questions usually contain a question mark. ;-)'
        return
      }
      this.answer = 'Thinking...'
      var vm = this
      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
        })
    }
  }
})
</script>

在這個示例中,使用 watch 選項允許我們執(zhí)行異步操作 (訪問一個 API)归形,限制我們執(zhí)行該操作的頻率,并在我們得到最終結(jié)果前鼻由,設(shè)置中間狀態(tài)。這些都是計算屬性無法做到的蕉世。

極客大全 http://www.jikedaquan.com/ 帶你玩java從入門到精通

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市讨彼,隨后出現(xiàn)的幾起案子哩至,更是在濱河造成了極大的恐慌,老刑警劉巖卢佣,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虚茶,死亡現(xiàn)場離奇詭異嘹叫,居然都是意外死亡罩扇,警方通過查閱死者的電腦和手機怕磨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門肠鲫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來导饲,“玉大人,你說我怎么就攤上這事棠枉”惭龋” “怎么了贱除?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵月幌,是天一觀的道長悬蔽。 經(jīng)常有香客問我,道長录语,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮氮趋,結(jié)果婚禮上江耀,老公的妹妹穿的比我還像新娘决记。我一直安慰自己倍踪,他們只是感情好建车,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布缤至。 她就那樣靜靜地躺著,像睡著了一般领斥。 火紅的嫁衣襯著肌膚如雪月洛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天细层,我揣著相機與錄音疫赎,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的陌僵。 我是一名探鬼主播创坞,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼偎谁,長吁一口氣:“原來是場噩夢啊……” “哼巡雨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤正蛙,失蹤者是張志新(化名)和其女友劉穎营曼,沒想到半個月后蒂阱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡鳄厌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年部翘,在試婚紗的時候發(fā)現(xiàn)自己被綠了新思。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赘风。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡邀窃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鞍历,到底是詐尸還是另有隱情,我是刑警寧澤惧蛹,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布香嗓,位于F島的核電站装畅,受9級特大地震影響掠兄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜迅诬,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一百框、第九天 我趴在偏房一處隱蔽的房頂上張望牍汹。 院中可真熱鬧慎菲,春花似錦锨并、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽害晦。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背灵莲。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工笆呆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赠幕。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓榕堰,卻偏偏與公主長得像逆屡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子砍的,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

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