Vue计算属性和侦听属性

(一)计算属性

1. 计算属性使用Vue实例的computed选项实现
2. 计算属性的书写格式
computed:{
		计算属性:function(){
			... ...
			return 计算属性的计算公式
		}
	}
3. 计算属性不能是出现在Vue实例data区中的变量
4. 计算属性的含义:

当计算属性的依赖变量发生变化时,计算属性会自动重新计算。

5. 计算属性的getter函数与setter函数
computed:{
		计算属性:{
			get:function(){
				//当依赖变量发生变化时触发计算属性的getter函数
			},
			set:function(){
				//当为计算属性赋值时触发计算属性的setter函数
			}
		}
	}
6. 在多个Vue实例之间引用计算属性:

Vue实例名:计算属性名

案例:
  1. 计算两个文本框中数值的和
  2. 根据圆的半径计算圆的面积
  3. 输入姓名,被分解为姓和名。输入姓和名,合成为姓名
<div id="demo" v-cloak>
		<h4>例一:计算两个文本框中数值的和</h4>
		<p>第一个数:<input type="text" v-model.number="numA" /></p>
		<p>第二个数:<input type="text" v-model.number="numB" /></p>
		<p>计算结果:{{result}}</p>
	
		<h4>例二:根据圆的半径计算圆的面积</h4>
		<p>圆的半径:<input type="text" v-model.number="radius" /></p>
		<p>圆的面积:{{area}}</p>

		<h4>例三:输入姓名,被分解为姓和名。输入姓和名,合成为姓名。</h4>
		<p>姓名:<input type="text" v-model="name" /></p>
		<p>
			姓:<input type="text" size="6" v-model="familyname" />
			名:<input type="text" size="6" v-model="lastname" />
		</p>
	</div>
new Vue({
	el:'#demo',
	data:{
		numA:'',
		numB:'',
		radius:'',
		familyname:'',
		lastname:''
	},
	methods:{

	},	
	computed:{
		result:{
			get:function(){
				return this.numA + this.numB
			},
			set:function(){

			}
		},
		area:function(){
			return Math.PI*Math.pow(this.radius,2);
		},
		name:{
			get:function(){
				return this.familyname + this.lastname
			},
			set:function(newName){
				this.familyname = newName==''?'':newName.charAt(0);
				this.lastname = newName==''?'':newName.slice(1);
			}
		}
		
	}
})
  1. 电费计算器。(第一个Vue实例计算两次电表数的差,第二个Vue实例计算电费)
<div id="ammeter1">
		<p><input type="text" placeholder="上月用电量" v-model="lastMounth" /></p>
		<p><input type="text" placeholder="本月用电量" v-model="thisMounth" /></p>
		<p>两月电表差值:{{result}}</p>
	</div>
	<div id="ammeter2">
		<p><input type="radio" v-model="dian" value="1" />商业用电(1.0/度)</p>
		<p><input type="radio" v-model="dian" value="0.52" />民用用电(0.52/度)</p>
		<p>应缴纳电费:{{resultAll}}</p>
	</div>
var ammeter1 = new Vue({
	el:'#ammeter1',
	data:{
		lastMounth:'',
		thisMounth:''
	},
	methods:{

	},
	computed:{
		result:function(){
			return this.thisMounth-this.lastMounth
		}
	}
})
var ammeter2 = new Vue({
	el:'#ammeter2',
	data:{
		dian:'0.52'
	},
	methods:{

	},
	computed:{
		resultAll:{
			get:function(){
				return ammeter1.result*this.dian
			},
			set:function(){

			}
		}
	}
})
  1. 模拟购物车
<div id="car">
		<h4>我的购物车>></h4><hr />
		<template v-if="product.length!=0">
			<table>
				<thead>
					<tr>
						<th><input type="checkbox" v-model="checkedAll" @click="checkAll" />全选</th>
						<th>序号</th>
						<th>品牌</th>
						<th>品名</th>
						<th>单价</th>
						<th>数量</th>
						<th>合计</th>
						<th>操作</th>
					</tr>
				</thead>
				<tbody>
					<tr v-for="(item,index) in product">
						<td><input type="checkbox" v-model="selected" :value="item.id" /></td>
						<td>{{index+1}}</td>
						<td>{{item.brand}}</td>
						<td>{{item.name}}</td>
						<td>{{item.price}}</td>
						<td>
							<button @click="item.count--" :disabled="item.count===1">-</button>
							{{item.count}}
							<button @click="item.count++">+</button>
						</td>
						<td>{{item.count*item.price}}</td>
						<td><button @click="DeleteFn(index)">删除</button></td>
					</tr>
				</tbody>
			</table>
			<div>总价:{{all}}</div>
		</template>
		<template v-else>
			<p>您的购物车空空如也,请到主页逛一逛</p>
		</template>
	</div>
#car{
	width: 1200px;
	margin: 0 auto;
}
#car table{
	width: 100%;
	height: auto;
	border-collapse: collapse;
}
#car table tr td,
#car table tr th{
	border-bottom: 1px solid #aaa;
	text-align: center;	
}
#car table tr th{
	height: 50px;
}
#car table tr td{
	height: 80px;
}
var car = new Vue({
	el:'#car',
	data:{
		product:[
			{
				id:1,
				brand:'三星',
				name:'Galaxy S4',
				price:2400,
				count:1
			},{
				id:2,
				brand:'Apple',
				name:'iPhone X',
				price:5200,
				count:1
			},{
				id:3,
				brand:'Apple',
				name:'iPad Pro 2018',
				price:10400,
				count:1
			},{
				id:4,
				brand:'ASUS',
				name:'S150笔记本电脑',
				price:4500,
				count:1
			},{
				id:5,
				brand:'联想',
				name:'L400笔记本电脑',
				price:3900,
				count:1
			}
		],
		checkedAll:false,
		selected:[]
	},
	methods:{
		DeleteFn(index){
			
			for(var i=0;i<this.selected.length;i++){
				if(this.selected[i].id === this.product[index].id){
					this.selected.splice(i,1);
					break;
				}
			}
			this.product.splice(index,1);
		},
		checkAll(){
			this.checked = [];
			if(!this.checkedAll){
				for(var i=0;i<this.product.length;i++){
					this.selected.push(this.product[i].id)
				}
			}else{
				this.selected = []
			}
		}
	},
	computed:{
		all(){
			var sum = 0;
			for(var i=0;i<this.product.length;i++){
				var select = this.selected.indexOf(this.product[i].id);
				if(select!=-1){
					sum += this.product[i].price*this.product[i].count
				}
			}
			return sum;
		}
	},
	watch:{
		selected:function(newValue,oldValue){
			if(newValue.length === this.product.length){
				this.checkedAll = true;
			}else{
				this.checkedAll = false;
			}
		}
	}
})

(二)侦听属性

1. 侦听属性使用Vue实例的watch选项实现。
2. 侦听属性的书写格式:
格式一:书写在Vue实例内部:
watch:{
	被侦听的变量:function(newValue,oldValue){
      ... ...
  }
}

侦听函数的参数:
newValue 表示被侦听的变量变化后的取值。
oldValue 表示被侦听的变量变化前的取值。

格式二:书写在Vue实例外部,利用Vue实例的$watch()方法实现:
vm.$watch('被侦听的变量',function(newValue,oldValue){
	... ...
},{
	immediate:true/false,
	deep:true/false
})
3. 侦听属性必须是出现在Vue实例data区中的变量
4. 侦听属性的含义

当被侦听的变量发生变化时,执行侦听属性所对应的函数

5. 侦听属性的高级选项
  • immediate:设置侦听属性对应的函数是否在Vue实例创建时立即执行。默认值
    为false,表示默认情况下不立即执行。
  • deep:设置侦听属性是否采用深度侦听模式,即是否希望侦听一个对象类型的变量
    中所有的成员。默认值为false。

例1:对一个对象类型的变量进行侦听。当该对象变量中任何一个键名的值发生变化时都
执行侦听函数。

var obj={a:10,b:20};
watch:{
	obj:{
		handler:function(newValue,oldValue){},
		deep:true
	}
}

例2:若真希望侦听obj对象中的a成员,不希望侦听obj对象的b成员。

watch:{
	'obj.b':function(newValue,oldValue){}
}

结论:若只侦听对象数据中的某一个成员,则该成员名必须用引号引住

案例:
  1. 计算任意整数的阶乘。(公式:n!=123*…*n)
<h4>案例一:阶乘计算器</h4>
	<div id="factorial">
		<input type="number" min="1" step="1" placeholder="请输入整数" v-model="sum" />
		<p>概数的阶乘:{{result}}</p>
	</div>
var factorial = new Vue({
	el:'#factorial',
	data:{
		sum:'',
		result:''
	},
	watch:{
		sum:function(newValue){
			this.result=1;
			for(var i=1;i<=newValue;i++){
				this.result=this.result*i;
			}
		}
	}
})
  1. 货币单位兑换(美元与人民币)。
<h4>案例二:单位换算(人民币/美元)</h4>
	<div id="unit"><input type="number" v-model="china" min="0" />
	<span>=</span>
	$<input type="number" v-model="dollar" min="0" />
	</div>
var unit = new Vue({
	el:'#unit',
	data:{
		china:1,
		dollar:1,
		rate:7.0119
	}
})
unit.$watch('china',function(newValue){
	this.dollar = this.china/this.rate;
})
unit.$watch('dollar',function(newValue){
	this.china = this.dollar*this.rate;
},{
	immediate:true
})
  1. 颜色拾取器。
<div id="color">
		<p>R: 
			<input type="range" min="0" max="255" v-model.number="R" /> 
			<span :style="{color:cr}">{{R}}</span>
		</p>
		<p>G: 
			<input type="range" min="0" max="255" v-model.number="G" /> 
			<span :style="{color:cg}">{{G}}</span>
		</p>
		<p>B: 
			<input type="range" min="0" max="255" v-model.number="B" /> 
			<span :style="{color:cb}">{{B}}</span>
		</p>
		<p>颜色码:<input type="text" v-model="color" size="7" /></p>
		<div id="box" :style="{backgroundColor:bgc}"></div>
	</div>
#box{
	width:150px;
	height: 150px;
	border: 1px solid #ccc;
}
var color = new Vue({
	el:'#color',
	data:{
		R:0,
		G:0,
		B:0,
		bgc:'#000000'
	},
	computed:{
		color:{
			get:function(){
				var red = this.R.toString(16).length===1?'0'+this.R.toString(16):this.R.toString(16);
				var green = this.G.toString(16).length===1?'0'+this.G.toString(16):this.G.toString(16);
				var blue = this.B.toString(16).length===1?'0'+this.B.toString(16):this.B.toString(16);
				this.bgc = "#" + red + green + blue;
				return "#" + red + green + blue;
			},
			set:function(newValue){
				if(newValue.length===7){
					this.bgc = newValue;
					this.R = parseInt(newValue.slice(1,3),16);
					this.G = parseInt(newValue.slice(3,5),16);
					this.B = parseInt(newValue.slice(5),16);
				}
			}
		},
		cr(){
			var red = this.R.toString(16).length===1?'0'+this.R.toString(16):this.R.toString(16);
			return "#" + red + "0000";
		},
		cg(){
			var green = this.G.toString(16).length===1?'0'+this.G.toString(16):this.G.toString(16);
			return "#00" + green + "00";
		},
		cb(){
			var blue = this.B.toString(16).length===1?'0'+this.B.toString(16):this.B.toString(16);
			return "#0000" + blue;
		},
	}
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值