Vue.js 计算属性+ 监听属性

Vue.js 计算属性

计算属性关键词: computed。

计算属性在处理一些复杂逻辑时是很有用的。

可以看下以下反转字符串的例子:

<template>
  <div id="app">
    <p>{{info}}</p>
    <p>{{reverse}}</p>
  </div>
</template>

<script>
export default {
  name: 'App',
  data(){
    return{
      info:'califonia'
    }
  },
  computed:{
    reverse(){
      return this.info.split('').reverse().join('');
    }
  }
}
</script>

<style scoped>

</style>

computed vs methods
我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。
可以说使用 computed 性能会更好,但是如果你不希望缓存,你可以使用 methods 属性。
 
computed 属性默认只有 getter ,不过在需要时你也可以提供一个 setter 
 
在使用 reversedMessage 这个计算属性的时候,第一次会执行代码,得到一个值,以后再使用 reversedMessage 这个计算属性,因为 vm 对象没有发生改变,于是界面渲染就直接用这个值,不再重复执行代码。而 reversedMessage2 没有这个缓存,只要用一次,函数代码就执行一次,于是每次返回值都不一样。
<template>
  <div id="app">
    <p>{{info}}</p>
    computed计算,不需要加()
    <p>第一次:{{reverse1}}</p>
    <p>第二次:{{reverse1}}</p>
    methods方法,需要加()
    <p>第一次:{{reverse2()}}</p>
    <p>第二次:{{reverse2()}}</p>
  </div>
</template>

<script>
var count=1;
export default {
  name: 'App',
  data(){
    return{
      info:'baidu'
    }
  },
  computed:{
    reverse1(){
      count+=1;
      return count+this.info.split('').reverse().join('');
    }
  },
  methods:{
    reverse2(){
      count+=1;
      return count+this.info.split('').reverse().join('');
    }
  }
}

</script>

<style scoped>

</style>

当你没有使用到计算属性的依赖缓存的时候,可以使用定义方法来代替计算属性,在 methods 里定义一个方法可以实现相同的效果,甚至该方法还可以接受参数,使用起来更灵活。

在vue.js中,有methods和computed两种方式来动态当作方法来用的。

  •  1.首先最明显的不同 就是调用的时候,methods要加上()
  •  2.我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。

而使用 methods ,在重新渲染的时候,函数总会重新调用执行。

Vue.js 监听属性

可以通过 watch 来响应数据的变化。

以下实例通过使用 watch 实现计数器:

<template>
  <div id="app">
    <p>{{count}}</p>
    <button @click="count++">click me</button>
  </div>
</template>

<script>
var count=1;
export default {
  name: 'App',
  data(){
    return{
      count:1
    }
  },
  watch:{
    count(nVal,oVal){
      console.log('oldValue: '+nVal+'  newValue: '+oVal);
    }
  }
}

</script>

<style scoped>

</style>

以下实例进行千米之间的换算:

<template>
  <div id="app">
    kilometers:
    <input type="text" v-model="kilometers">
    <br>
    meters:
    <input type="text" v-model="meters">
  </div>
</template>

<script>
var count=1;
export default {
  name: 'App',
  data(){
    return{
      kilometers:0,
      meters:0
    }
  },
  watch:{
    kilometers(val){
      this.kilometers=val;
      this.meters=val*1000;
    },
    meters(val){
      this.meters=val;
      this.kilometers=val/1000;
    },
  }
}

</script>

<style scoped>

</style>

模拟购物车效果

<template>
  <div id="app">
    <table>
      <tr>
        <th>序号</th>
        <th>商品名</th>
        <th>价格</th>
        <th>数量</th>
        <th>操作</th>
      </tr>
      <tr v-for="item in list" :key="item.id">
        <td>{{item.id}}</td>
        <td>{{item.name}}</td>
        <td>{{item.price}}</td>
        <td>
          <button v-bind:disabled="item.count===0" v-on:click="item.count--">-</button>
          {{item.count}}
          <button v-on:click="item.count++">+</button>
        </td>
        <td><button v-on:click="item.count=0">移除</button></td>
      </tr>
    </table>
    <p>总价:{{total()}}</p>
  </div>
</template>

<script>
var count=1;
export default {
  name: 'App',
  data(){
    return{
      list:[
        {
          id:1,
          name:'iphone6',
          price:6000,
          count:1
        },
        {
          id:2,
          name:'iphone8',
          price:7000,
          count:1
        },
        {
          id:3,
          name:'iphonex',
          price:8000,
          count:1
        }
      ]
    }
  },
  methods:{
    total(){
      var totalPrice=0;
      for(var i=0;i<this.list.length;i++){
        totalPrice+=this.list[i].price*this.list[i].count;
      }
      return totalPrice;
    }
  }
}

</script>

<style scoped>
table {
    border: 1px solid black;
}
table {
    width: 100%;
}

th {
    height: 50px;
}
th, td {
    border-bottom: 1px solid #ddd;
}
</style>

简单的省市联动

<template>
  <div id="app">
    省:
    <select v-model="province">
      <option>请选择</option>
      <option v-bind:value="p" v-for="p in provinces" :key="p">{{p}}</option>
    </select>
    市:
    <select v-model="city">
      <option>请选择</option>
      <option v-bind:value="c" v-for="c in cityList" :key="c">{{c}}</option>
    </select>
  </div>
</template>

<script>
var count=1;
export default {
  name: 'App',
  data(){
    return{
      city: '请选择',
      province: '请选择',
      provinces: ['广东', '湖南', '湖北', '北京'],
      cityList: [],
      area: [{
        name: '广东',
        id: 1,
        child: ['广州', '深圳', '东莞']
      },
      {
        name: '湖南',
        id: 2,
        child: ['长沙', '株洲', '湘潭']
      },
      {
        name: '湖北',
        id: 3,
        child: ['武汉']
      },
      {
        name: '北京',
        id: 4,
        child: ['北京']
      }]
    }
  },
  watch:{
    province(nVal,oVal){
      if(nVal==='请选择'){
        this.cityList=[];
      }
      if(nVal!==oVal){
        for(var i=0;i<this.area.length;i++){
          if(this.area[i].name===nVal){
            this.cityList=this.area[i].child;
          }
        }
      }
      this.city='请选择';
    }
  }
}

</script>

<style scoped>

</style>

 
 

猜你喜欢

转载自www.cnblogs.com/chenyingying0/p/12738684.html