(一)计算属性
1. 计算属性使用Vue实例的computed选项实现
2. 计算属性的书写格式
computed:{
计算属性:function(){
... ...
return 计算属性的计算公式
}
}
3. 计算属性不能是出现在Vue实例data区中的变量
4. 计算属性的含义:
当计算属性的依赖变量发生变化时,计算属性会自动重新计算。
5. 计算属性的getter函数与setter函数
computed:{
计算属性:{
get:function(){
//当依赖变量发生变化时触发计算属性的getter函数
},
set:function(){
//当为计算属性赋值时触发计算属性的setter函数
}
}
}
6. 在多个Vue实例之间引用计算属性:
Vue实例名:计算属性名
案例:
- 计算两个文本框中数值的和
- 根据圆的半径计算圆的面积
- 输入姓名,被分解为姓和名。输入姓和名,合成为姓名
<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);
}
}
}
})
- 电费计算器。(第一个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(){
}
}
}
})
- 模拟购物车
<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){ … }
}
结论:若只侦听对象数据中的某一个成员,则该成员名必须用引号引住
案例:
- 计算任意整数的阶乘。(公式: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;
}
}
}
})
- 货币单位兑换(美元与人民币)。
<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
})
- 颜色拾取器。
<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;
},
}
})