Vue計算屬性computed可以做什麼?又能應用在什麼場景呢?以下這篇文章就來帶大家了解Vue computed屬性,並將其與methods、watch比較一下,希望對大家有幫助!
Vue中的計算屬性是所有屬性的計算,而這些計算都是變向的在過濾值,透過資料的不斷變化計算出來不同的值和運算不同的方法. 而在Vue中,會使用到計算屬性的場景常見的有:
#模板內的表達式
v-bind裡可以進行的表達式。 (學習影片分享:
vue影片教學)
,字元拼接,三元表達式,那麼使用相當方便。當然,以上方式也有自己的劣勢。一旦要處理的邏輯複雜,程式碼量就會變得大得多,而且難於維護。比如說用到if語句來控制流程。那麼這個時候可能會想到用filter
,咱們來看一個簡單的範例。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:html;toolbar:false"><div id="app">
<button @click="count++">{{count + &#39;分&#39;}}</button>
<div>
<input v-model="message" />
</div>
<p>{{ message.split(&#39; &#39;).reverse().join(&#39; &#39;) }}</p>
</div></pre><div class="contentsignin">登入後複製</div></div><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false">let app = new Vue({
el: &#39;#app&#39;,
data () {
return {
count: 0,
message: &#39;&#39;
}
}
})</pre><div class="contentsignin">登入後複製</div></div>
效果如下:
#從上面的範例我們可以看出:
指定綁定了一個click
事件,它只做了一件事情,就是count
,button
每點擊一次,count
值增加1
,注意,這裡並沒有使用methods
透過v-model
做了資料雙向綁定,綁定了message
,並且在p
標籤中對message
字串進行反轉。
標籤中對message
#進行計算轉換的時候,是不是覺得語意不是很強烈,那麼用什麼辦法更好呢?這就需要我們使用到前面提到的filter。
來修改前面的範例。事實下,在Vue中使用filter
具有自己的優勢,也具有自己的劣勢:
filter給我們用於計算和過濾一些模板表達式和v-bind屬性表達式一些弊端的地方進行計算,他們會返回當前計算的值,可以進行傳參在多地方共用這個過濾方法
filter就比較難過濾到了,本質上
filter就是一個一對一的行為,對單一資料進行過濾,可以進行傳參,同方法,但不同參
##把上面的範例,用
<div id="app"> <button @click="count++">{{count + '分'}}</button> <div> <input v-model="message" /> </div> <p>{{ message | reverseString }}</p> </div> let app = new Vue({ el: '#app', data () { return { count: 0, message: '' } }, filters: { reverseString (value) { if (!value) return '' value = value.split('').reverse().join('') return value } } })
在這個範例中,我們使用filter來實現,很明顯程式碼量多了那麼一點點,但整體的語意化就變得相當明顯了,讓人一看這裡就要進行一些過濾計算,看到reverseString就知道是字串反轉。
computed可以做些什麼?又能應用在什麼場景呢? Vue中的
computed
其實規避了模板語法和
兩個所有的劣勢,他的優勢在於透過計算所有依賴的資料進行計算,然後返回一個值,記住可以依賴方法裡所有的數據,只要一個數據發生變化,則會重新計算,來更新視圖的改變
。是不是很意思,迫切的想知道它是怎麼玩。 咱們還是拿用場景來說事吧。先給大家示範一個簡單實用的應用場景,後面再做一個更好玩一點的應用程式場景。 大家是否還記得,我們在玩微博的時候,發微博會有一個字數限制,比如說只限輸入
個字元。為了讓使用者體驗更好,在文字域中輸入內容的時候,同時有一個提示訊息,告訴使用者你還能輸入多少字元。那麼使用Vue來做這樣的事情就會顯得容易的多。例如下面這個範例:
<div id="app"> <div class="twitter"> <img :src="imgUrl" / alt="Vue計算屬性computed可以做什麼?應用場景淺析" > <div class="content"> <textarea v-model="content" :maxlength="totalcount">有什么新鲜事情?</textarea> <p>您还可以输入{{ reduceCount }}字</p> </div> </div> </div> let app = new Vue({ el: '#app', data () { return { imgUrl: '//pbs.twimg.com/profile_images/468783022687256577/eKHcWEIk_normal.jpeg', totalcount: 140, // 总共只给输入140字 content: '' } }, computed: { reduceCount () { return this.totalcount - this.content.length } } })
效果如下:<p><iframe id="jGZJqe" src="//codepen.io/airen/embed/jGZJqe?height=400&theme-id=0&slug-hash=jGZJqe&default-tab=result&user=airen" width="100%" height="500"></iframe></p><p>你可以尝试在文本域中输入内容,你将体验的效果类似下图一样:</p><p><img src="https://img.php.cn/upload/image/501/880/200/1660117549349930.gif" title="1660117549349930.gif" alt="Vue計算屬性computed可以做什麼?應用場景淺析"/></p><p>在<code>computed
创建了一个reduceCount
,一直在监听文字的字符长度,来再次进行计算,返回值给视图,让视图进行变化。这也是一个很简单的示例。前面也提到过,我们可以监听多个数据,只要一个数据变了,整个方法就会重新计算,然后反馈到视图,这个方法只是一个简单的应用。咱们再来看一个示例,这样会更好的帮助我们理解。
这个示例是一个足球比赛记分的示例。简单的对示例进行分析:
比赛时间,用time
来维护
比赛双方的进球数,用对象team
来维护
比赛的播报情况,在90分钟内,要显示中国领先或者韩国领先或者双方僵持,如果到了90分钟我们要显示中国队赢还是韩国队赢,还是平局
第三个数据相对而言比较复杂,也是比较关键的数据。那么我们用什么方式来维护,可以说比赛情况是多样化的,用一个数据去定死,这样不符合我们的场景。那么我们先列出将会改变的地方:
我们需要检测双方的进球数
通过时间来比对,确定比赛是否结果,然后显示对应的方案
这样我们就要不断的监听两个维护的数据,一是比赛时间,二是比赛两队进球数。
<div id="app"> <h1>比赛时间:{{ time }}s</h1> <h2>直播播报:{{ result }}</h2> <div class="team"> <div> <span>中国队进球数:{{ team.china }}</span> <button @click="team.china++">点击中国队进一球</button> </div> <div> <span>韩国队进球数:{{ team.korea }}</span> <button @click="team.korea++">点击韩国队进一球</button> </div> </div> </div> let app = new Vue({ el: '#app', data () { return { time: 0, team: { china: 0, korea: 0 } } }, created () { let time = setInterval(() => { this.time++ if (this.time == 90) { clearInterval(time) } }, 1000) }, computed: { result () { if (this.time < 90) { if (this.team.china > this.team.korea) { return '中国队领先' } else if (this.team.china < this.team.korea) { return '韩国领先' } else { return '双方僵持' } } else { if (this.team.china > this.team.korea) { return '中国队赢' } else if (this.team.china < this.team.korea) { return '韩国队赢' } else { return '平局' } } } } })
看到的效果如下:
注:这里时间90分钟是一个写死的时间值。如果要让Demo更为完美,这个时间我们可以写一个90分钟的倒计时效果。如果你感兴趣的话,可以自己动手修改上面的Demo,然后在下面的评论中与我们一起分享。
这个示例中,用了点击事件来进行双方进球数,这个Demo帮助我们能能更充分的理解Vue中的computed
的含义。说到底是观察一个或多个数据,每当其中一个数据改变的时候,这个函数就会重新计算,还有就是通过观察所有数据来维护一个状态,就是所谓的返回一个状态值。从上面这个Demo,我们就可以很容易的知道computed
到底用在什么场景,如何去维护返回一个多状态的场景。
在Vue中,使用methods
可以做computed
同样的事情,不同的是,computed
可以进行缓存。什么意思呢?就是在上个例子中我们对比赛时间和两个球队的进球数进行了检测数据。如果随着时间的改变,但是球数没动,对于computed
来说只会重新计算这个球数,进入缓存,而不会再次计算,而重新计算的是这个时间,而且页面的DOM更新也会触发methods
来重新计算属性。所以,如果不想让计算属性进入缓存,请使用methods
,但我个人更推荐使用computed
,语义化会更好一点。毕竟是什么选项里就应该做什么事,methods
里面就是应该来管事件的。
computed
和watch
都可以做同一件事,就像跑步运动员都可以跑步,但是分100米和1000米,术业有专攻嘛,两个选项都是对数据进行时时监听,但是两个的适用场景就不一样了:
computed
前面说了是适用于对多数据变动进行监听,然后来维护一个状态,就是返回一个状态
wacth
是对一个数据监听,在数据变化时,会返回两个值,一个是value
(当前值),二是oldvalue
是变化前的值
我们可以通过这些变化也可以去维护一个状态,但是不符合场景。那么watch
主要用于什么地方呢?其主要用于监听一个数据来进行复杂的逻辑操作。
<div id="app"> <h1>比赛时间:{{ time }}s</h1> <h2>直播播报:{{ result }}</h2> <div class="team"> <div> <span>中国队进球数:{{ team.china }}</span> <button @click="team.china++">点击中国队进一球</button> </div> <div> <span>韩国队进球数:{{ team.korea }}</span> <button @click="team.korea++">点击韩国队进一球</button> </div> </div> </div> let app = new Vue({ el: '#app', data () { return { time: 0, team: { china: 0, korea: 0 }, result: '双方僵持' } }, created () { let time = setInterval(() => { this.time++ if (this.time == 90) { clearInterval(time) } }, 1000) }, wacth: { time (value, oldval) { if (value < 90) { if (this.team.china > this.team.korea) { this.result = '中国队领先' } else if (this.team.china < this.team.korea) { this.result = '韩国队领先' } else { this.result = '双方僵持' } } else { if (this.team.china > this.team.korea) { this.result = '中国队赢' } else if (this.team.chian < this.team.korea) { this.result = '韩国队赢' } else { this.result = '平局' } } }, team (value, oldval) { if (this.time < 90) { if (value.china > value.korea) { this.result = '中国队领先' } else if (value.china < value.korea) { this.result = '韩国队领先' } else { this.result = '双方僵持' } } else { if (value.china > value.korea) { this.result = '中国队赢' } else if(value.chian < value.korea) { this.result = '韩国队赢' } else { this.result = '平局' } } } } })
以上代码和computed
产生的效果是一模一样,但是很明显,就像我对computed
和watch
阐述过了应用场景,这个场景只是维护了一个比赛状态,而不牵扯到逻辑操作。虽然也能完成,但无论从代码量的比对还是可读性,还是可维护性的都不胜于computed
。但说到底谁更强大呢?我还是老实说watch
更强大,哪里有然他有场景的局限性,但是他可以做牵扯到计算属性的一切操作,缺点是watch
只能一个一个监听。
我相信图片预加载大家肯定都有接触过,当图片量大的时候,为了保证页面图片都加载出来的时候,才渲染页面,再进行一些 Ajax请求,或者逻辑操作。那些时你用computed
对这种监听一个数据然后进行一系列逻辑操作和Ajax
请求,那watch
再适合不过了,如果用computed
的话,那是无法实现的。
<template> <div v-show=show> <img src="https://img.alicdn.com/simba/img/TB14sYVQXXXXXc1XXXXSutbFXXX.jpg" alt=""> <img src="//img.alicdn.com/tfs/TB1iZ6EQXXXXXcsXFXXXXXXXXXX-520-280.jpg_q90_.webp" alt=""> <img src="https://img.alicdn.com/simba/img/TB1C0dOPXXXXXarapXXSutbFXXX.jpg" alt=""> <img src="//img.alicdn.com/tfs/TB1iZ6EQXXXXXcsXFXXXXXXXXXX-520-280.jpg_q90_.webp" alt=""> </div> </template> <script> export default { mounted () { var _this = this let imgs = document.querySelectorAll('img') console.log(imgs) Array.from(imgs).forEach((item)=>{ let img = new Image() img.onload = ()=>{ this.count++ } img.src=item.getAttribute('src') }) }, data () { return { count : 0, show : false } }, watch : { count (val,oldval) { if(val == 4){ this.show = true alert("加载完毕") //然后可以对后台发送一些ajax操作 } } } } </script>
我们可以发现四张图片都加载完毕的时候,页面才渲染出来。
Vue官方有一句话说得很重要:
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的
watcher
。这是为什么Vue提供一个更通用的方法,使用wacth
来响应数据的变化。当你想要在数据变化响应时,执行异步操作或开销较大的操作,这是很有用的。
基于这个描述,我对computed
和watch
的总结:
computed
:监听多个数据或者一个数据来维护返回一个状态值,只要其中一个或多个数据发生了变化,则会重新计算整个函数体,重新返回状态值
watch
:只能一个一个监听数据,只要这个数据发生变化,就会返回两个参数,第一个是当前的值,第二个是变化前的值。每当变化的时候,则会触发函数体的逻辑行为,根据逻辑行为做后续的操作
其实,computed
、watch
这几个都不是有多难,如果从表层上来说都很易理解,但从深层面上看,很多时候还是会存在问题。比如说会滥用,混用。这篇文章通过一些示例来讲解Vue的计算属性,并且对其做了一定的分析。我想这些对学习Vue的初级人员或许会有一些帮助。
原文地址:https://www.w3cplus.com/vue/vue-computed.html
以上是Vue計算屬性computed可以做什麼?應用場景淺析的詳細內容。更多資訊請關注PHP中文網其他相關文章!