我自己很笨,学习编程也是一点一点啃,总是把在别人看起来很简单的一个问题,自己都要反复琢磨好多遍,特别是有时候啃官方文档的时候,出现一些比较绕口的词,我怎么也不能理解,所以我就会不停的反问自己,你真的理解这个词吗?之后就会琢磨好久,用自己能理解的语言写出来,并记录下来!
如果,我分享的对您有帮助,那么我们一起进步,点赞随缘,收藏随心!
什么是动态数据?
发挥一下阅读理解能力,动态数据应该指的就是不断变化的数据,非固定一成不变的数据!
常见的几种场景:
- 商城种常见的购物车数据就是不断变化的
- 购买商品支付的金额会根据选购的数量不断变化
- 字符串实时拼接等
vue实现这种需求有四种方式
1.JavaScript表达式
vue提供了一种非常方便的操作,模板语法{{}}
中可以使用单一的JavaScript表达式,但只适合简单的需求(比如字符串拼接),稍微复杂的需求不建议试用!
- 例子 - 反转字符串:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
<script type="text/javascript">
const app = new Vue({
el: "#example",
data:{
message: '我是一个例子!'
}
})
</script>
上边的反转字符串我们也可以通过定义一个方法来实现,但是这种简单的需求单独定义个方法又是大材小用了!
2.method方法
那么,假如我们有一个购物车的需求,我们要根据商品的价格和数量来计算出总价的时候,这个场景就相对复杂了,就可以使用这种方法!
<div id="app">
<ul>
<li v-for="(item, index) in books" :key="index">
<span>名称:{{item.name}}</span>
<span>价格:{{item.price.toFixed(2)}}</span>
<span>数量:{{item.num}}</span>
<br>
<input type="button" value="+" @click="item.num += 1">
<input type="button" value="-" @click="item.num -= 1">
</li>
</ul>
<p>总价:{{totalPrice()}}</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
books: [
{
name: 'Android',
price: 12.00,
num: 0
},{
name: 'IOS',
price: 13.00,
num: 0
},{
name: 'javaScript',
price: 14.00,
num: 0
},
],
// totalPrice: 0.00
},
methods:{
totalPrice: function(){
var result = 0
// forEach()获得数组的每个元素,参数为一个回调函数
this.books.forEach(book => {
result += book.price * book.num;
});
return result;
}
}
});
</script>
我们通过定义了一个方法实现了购物车基本的运算,但是我们发现,每进行一次计算,一旦触发了页面的重新渲染,totalPrice()
方法都要执行一次,我们重新写个点击事件来验证下!
- 在以上代码中添加,如图:
<h1>验证</h1>
<p>{{testData}}</p>
<input type="button" value="test" @click="testMethod()">
testMethod: function(){
console.log('testMethod');
this.testData += 1
},
data
中别忘了声明testData
属性,点击这个事件我们来验证下!
点击之后我们发现,只要我们定义的这个testMethod
方法触发一次页面渲染,totalPrice
方法也要跟着执行一次,那么,如果我们这个页面有很多操作事件,每一次触动渲染,它都跟着执行一次,就会造成很多性能浪费,此时,这个带有缓存功能的计算属性computed就很好的解决了这个问题!
3.computed属性
计算属性是基于它们的响应式依赖进行缓存的,只在相关响应式依赖发生改变时它们才会重新求值。
这句话什么意思呢?以刚才我们验证totalPrice
方法只要有方法触发了dom
的实时渲染,他都要跟着执行一次,变成现在他自己缓存起来,只要他自身不改变不触发dom
渲染,你执行别的方法,它就不会再受影响!
如何定义,计算属性?
如图所示: 计算属性computed与mefthods是同级,将我们在methods中定义的totalProice方法移到computed中,名称改为totalProice1。
在data中声明一个totalProice属性,如下图:
将总价中模板语法渲染改为{{ totalPricel }}
此时,我们再去执行testMethod方法就不会影响到他的计算值!如下图:
这就是computed
计算属性解决的问题!
计算属性的getter和setter方法
computed
提供了一个 getter
和 setter
方法,默认情况下,我们只需要关注 computed
的 getter
方法,看看官网给出的例子,拼接字符串:
<div id="app">
{{ fullname }}
</div>
<script>
var app = new Vue({
el: '#app',
data:{
firstName: '刘',
lastName: '德华'
},
computed:{
fullname: function(){
return this.firstName + this.lastName
}
}
})
</script>
同样可以试用computed
的getter
方法实现,getter
方法可以简写成get
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
}
}
可以发现运行的结果是一样的,同时也可以去重写它的 setter 方法,如下:
computed: {
fullName: {
// getter
get: function () {
console.log('get方法');
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
console.log('set方法:' + newValue);
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
当在控制台去执行app.fullName = 'The Vue’的时候,Vue 会先调用 setter 方法为 firstName 和 lastName 赋值,然后执行 getter 方法,来返回 fullName。
4.watch属性
watch属性又叫侦听属性,顾名思义它具有时刻监听数据的作用!
当你有一些数据(结果数据)需要随着其他数据(目标数据)变动而变动时,可以使用 watch 来监听目标数据的变化,当目标数据发生变化时,Vue 会回调我们的监听事件。
注释掉,上一步定义的computed,添加如下代码,这就是watch的定义方式,需要监听哪个数据就位那个数据定义一个回调函数!
watch:{
books:{
handler: function(val, oldval){
this.totalPrice = 0;
val.forEach(item => {
this.totalPrice += item.num * item.price;
});
},
deep: true,
}
},
上例中,使用 watch 属性来对 books 进行数据监听,当 books 发生数据变化时,会回调 handler 方法,handler 方法接收两个参数监听数据的当前值(val),监听数据变化之前的值(注意:当监听的数据为对象或数组时,val 和 oldVal 是相等的,因为这两个引用指向同一块内存空间),这样就可以在回调方法 handler 来计算 totalPrice。
侦听器能实现的效果很多时候都可以用计算属性来实现,那为什么还要定义这样一个方法呢,官方给的说法是:当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
意思是应用场景主要在:异步操作和性能开销较大时采用!
我们用刚才的例子加一个定时器,模拟下异步操作,改造handler
回调方法!
watch: {
books: {
// 监听到数据变化之后的回调方法
handler:function(val,oldval){
this.totalPrice = '计算中...';
var $this = this;
setTimeout(() => {
$this.totalPrice = 0;
val.forEach(item => {
$this.totalPrice += item.num * item.price;
});
}, 1000);
},
deep:true// 对象内部的属性监听,也叫深度监听
}
},
通过上边的模拟异步请求,实现了一个计算中的效果!
四种方式的对比
截止到这里就已经了解了 Vue 中进行动态数据计算的所有方式了,我们把这些方式进行一个总结。
(1)JavaScript 表达式:方法最为简单,不需要学习新的属性和概念就可以直接使用,但是它只有简单的运用场景(比如,简单的字符串拼接),当应用常见变得复杂的时候(如购物车)这种方式就不在适用了。
(2)method 方法:method 方法的形式可以帮助我们应对一个复杂的场景,当页面重新渲染的时候,method 方法每次都会执行。如果页面有大量的渲染动作,并且大量的渲染动作与动态数据计算无关的话,使用这种方式会带来一定的性能浪费。
(3)watch 属性:使用 watch 属性可以对数据进行监听,当被监听的数据发生变化的时候,对应的数据监听方法会被调用,watch 属性同样可以帮助我们应对一个复杂的操作,并且可以提供异步的事件处理。当需要监听一个目标数据的变化时,这种方式是一种非常好的选择,同时如果目标数据有多个 (firstName、lastName),多个目标数据共同影响一个结果数据的话 (fullName),这种监听方式会让人觉得比较奇怪。
这里可以参考官方解释:https://cn.vuejs.org/v2/guide/computed.html
(4)computed 属性:computed 属性也是 Vue 中大力推广的一个特性,它会通过声明的方式来确定依赖的关系,只有依赖数据发生响应式变化的时候,才会调用 computed 属性的 getter 方法,并且 computed 属性默认提供了缓存机制,如果依赖数据并没有发生响应式变化,computed 属性不会重新计算,而只是读取缓存数据。
如何选择用那种: 选择那种方式实现,取决于面对了什么样的问题。
感谢您的阅读,如果对您有帮助,欢迎关注"CRMEB"。码云上有我们开源的商城项目,知识付费项目,JAVA版全开源商城系统,学习研究欢迎使用,老铁顺手点个star呗,老板奖励*,分你两毛五,