計(jì)算屬性computed和偵聽器watch

計(jì)算屬性computed和偵聽器watch

一萨螺、計(jì)算屬性computed

計(jì)算屬性,顧名思義愧驱,就是計(jì)算出一個屬性慰技,并且計(jì)算屬性的求值結(jié)果會被緩存起來,只在它的響應(yīng)式依賴發(fā)生改變時該屬性才會重新求值组砚。

計(jì)算屬性一般用于簡化模板中的表達(dá)式吻商,如下,只要 firstNamelastName還沒有發(fā)生改變糟红,多次訪問 fullName 計(jì)算屬性會立即返回之前的計(jì)算結(jié)果艾帐,而不必再次執(zhí)行函數(shù)。

    <div id="app">
        <!--這種方式 若出現(xiàn)次數(shù)多盆偿,或內(nèi)容冗長柒爸,則很繁瑣 -->
        <p>{{ firstName + lastName }}</p>
        
        <!--使用計(jì)算屬性簡化模板表達(dá)式 -->
        <p>{{ fullName }}</p> 
    </div>
<script>
        var app = new Vue({
            el: '#app',
            data: {
                firstName: "梅梅",
                lastName: "李",
            },
            computed: {
                fullName: function () {
                    return this.firstName + this.lastName
                }
            }
        })
</script>

組件模板應(yīng)該只包含簡單的表達(dá)式,復(fù)雜的表達(dá)式則應(yīng)該重構(gòu)為計(jì)算屬性或方法事扭。復(fù)雜的表達(dá)式會讓模板變得不是那么聲明式捎稚。我們應(yīng)該盡量描述理應(yīng)出現(xiàn)什么,而非如何計(jì)算那個值求橄。而且計(jì)算屬性和方法使得代碼可以重用今野。

此外應(yīng)該把復(fù)雜的計(jì)算屬性分割為極可能多簡單的屬性。

computed:{
    basePrice(){
        return this.manufactureCost / ( 1 - this.profitMargin)
    },
    discount(){
        return this.basePrice * (this.discountPercent || 0)
    },
    finalPrice(){
        return this.basePrice -  this.discount
    }
}

也可以進(jìn)行一些更復(fù)雜的操作:

<div id="app">
     <h2>總價格:{{ totalPrice }}</h2>
</div>
<script>
        var app = new Vue({
            el: '#app',
            data: {
                // 給一個對象數(shù)組book,數(shù)組每一個元素都是一個對象
                books: [
                    { id: 110, name: "編程之美", price: 119 },
                    { id: 111, name: "代碼大全", price: 115 },
                    { id: 112, name: "深入理解計(jì)算機(jī)原理", price: 99 },
                    { id: 113, name: "圖解HTTP", price: 85 },
                ]
            },
            computed: {
                totalPrice: function () {
                    let result = 0
                    for (let i = 0; i < this.books.length; i++) {
                        result += this.books[i].price
                    }
                    return result
                }
            }
        })
</script>

computed的完整形式,其中包括一個setter方法和一個getter方法罐农。一般只需要實(shí)現(xiàn)getter方法腥泥。setter一般是空的,不希望別人給這個計(jì)算屬性設(shè)置值啃匿,就會直接刪去setter方法。如:

<script>
        var app = new Vue({
            el: '#app',
            data: {
                firstName: '旺旺',
                lastName: '仙貝'
            },
            computed: {
                fullName: {
                    // 未給fullName外加賦值時,輸出為get方法的輸出
                    // 但如果外界再賦值溯乒,則會輸出 console.log('---', newValue)
                    set: function (newValue) {
                        console.log('---', newValue)
                    },
                    get: function () {
                        return 'abc'
                    // 之后使用fullName屬性時就會調(diào)用get方法夹厌,返回abc
                    }
                }
            }
        })
    </script>

二、偵聽屬性watch

偵聽屬性watch可以監(jiān)聽data中指定數(shù)據(jù)的變化裆悄,然后觸發(fā)這個watch中對應(yīng)的function處理函數(shù)矛纹。當(dāng)我們需要深度監(jiān)聽對象中的屬性時,可以打開deep:true選項(xiàng), 這樣便會對對象中的每一項(xiàng)屬性進(jìn)行監(jiān)聽光稼。

image-20200815102054597.png

通過watch除了可以監(jiān)聽一些DOM元素外或南,還可以監(jiān)聽DOM之外的元素,比如路由對象艾君。

watch:{
    '$route': function ( newVal, oldVal ){
        console.log(`之前的路由:${oldVal},現(xiàn)在的路由${newVal}`);
        if (newVal.path === '/register'){
            console.log('這是注冊組件')采够;
        }else{
            console.log('這是登錄組件')
        }
     }
}

當(dāng)需要在數(shù)據(jù)變化時執(zhí)行異步或開銷較大的操作時,watch是最有用的冰垄。使用 watch 選項(xiàng)允許我們執(zhí)行異步操作 (訪問一個 API)蹬癌,限制我們執(zhí)行該操作的頻率,并在我們得到最終結(jié)果前虹茶,設(shè)置中間狀態(tài)逝薪。這些都是計(jì)算屬性無法做到的。

以下是官網(wǎng)例子:

<div id="watch-example">
  <p>
    Ask a yes/no question:
    <input v-model="question">
  </p>
  <p>{{ answer }}</p>
</div>
<!-- 因?yàn)?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ù)就會運(yùn)行
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      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>

三、computed狂巢、watch撑毛、methods的對比

computed

  • computed形式上是function()函數(shù),主要當(dāng)做屬性來使用唧领;監(jiān)聽data里的數(shù)據(jù)變化藻雌,會根據(jù)data數(shù)據(jù)變化而自動重新計(jì)算;
  • computed中屬性的結(jié)果會被緩存斩个,除非依賴的響應(yīng)式屬性變化才會重新計(jì)算胯杭;
  • 最后一定要有個返回值,而且不帶參數(shù)受啥。

watch

  • 監(jiān)聽一個對象做个,鍵是需要觀察的表達(dá)式鸽心,值是對應(yīng)回調(diào)函數(shù)。
  • 主要用來監(jiān)聽某些特定數(shù)據(jù)的變化居暖,從而進(jìn)行某些具體的業(yè)務(wù)邏輯顽频;可以看作是computed和methods的結(jié)合體。

methods

  • 方法表示一個具體的操作太闺,主要書寫業(yè)務(wù)邏輯糯景;methods的返回值和參數(shù)都是可有可無的。
  • methods無法監(jiān)聽data數(shù)據(jù)省骂,并且methods中的方法誒有緩存蟀淮,每次刷新都會去執(zhí)行。

總結(jié):
如果一個值依賴多個屬性(多對一)钞澳,用computed更加方便怠惶;
如果一個值變化后會引起一系列操作,或一個值變化會引起一系列值的變化(一對多)略贮,用watch更方便一些甚疟。
watch的回調(diào)里面會傳入監(jiān)聽屬性的新舊值,通過這兩個值可以做一些特定的操作逃延;computed通常就是簡單的計(jì)算览妖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市揽祥,隨后出現(xiàn)的幾起案子讽膏,更是在濱河造成了極大的恐慌,老刑警劉巖拄丰,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件府树,死亡現(xiàn)場離奇詭異,居然都是意外死亡料按,警方通過查閱死者的電腦和手機(jī)奄侠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來载矿,“玉大人垄潮,你說我怎么就攤上這事∶瓶” “怎么了弯洗?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長逢勾。 經(jīng)常有香客問我牡整,道長,這世上最難降的妖魔是什么溺拱? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任逃贝,我火速辦了婚禮谣辞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沐扳。我一直安慰自己潦闲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布迫皱。 她就那樣靜靜地躺著,像睡著了一般辖众。 火紅的嫁衣襯著肌膚如雪卓起。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天凹炸,我揣著相機(jī)與錄音戏阅,去河邊找鬼。 笑死啤它,一個胖子當(dāng)著我的面吹牛奕筐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播变骡,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼离赫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了塌碌?” 一聲冷哼從身側(cè)響起渊胸,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎台妆,沒想到半個月后翎猛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡接剩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年切厘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片懊缺。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡疫稿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出桐汤,到底是詐尸還是另有隱情而克,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布怔毛,位于F島的核電站员萍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏拣度。R本人自食惡果不足惜碎绎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一螃壤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧筋帖,春花似錦奸晴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至代箭,卻和暖如春墩划,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嗡综。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工乙帮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人极景。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓察净,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盼樟。 傳聞我的和親對象是個殘疾皇子氢卡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354