vue computed和watch的区别

computed

是一个计算属性(被计算出来的属性就是计算属性),不需要加括号,会根据依赖是否变化来缓存。

  • 展示用户名

 

//引用的是完整版Vue
import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;

new Vue({
  data: {
      user: {
        email: "wuyouzhen@qq.com",
        nickname: "Luna",
        phone: "13112345678"
      }
  },
  computed: {
    displayName(){
      const user = this.user
      return user.nickname || user.email || user.phone//优先展示nickname,再展示email,再展示phone
    }
  },
  template: `
    <div>
      {{displayName}}
    </div>
  `
}).$mount("#app");

如果要多次展示,那就多写几遍即可,哪天改了需求,只需要改顺序就行return user.nickname || user.phone || user.email,不用再多次重复写。

 

template: `
    <div>
      {{displayName}}
      <div>
        {{displayName}}
      </div>
    </div>
  `

计算属性可以让根据其他属性计算而来的属性变成一个属性,也可以用getter和setter来写

 

computed: {
    displayName: {
      get() {
        const user = this.user;
        return user.nickname || user.email || user.phone;
      },
      set(value) {
        this.user.nickname = value;
      }
    }
  },
template: `
    <div>
      {{displayName}}
      <button @click="add">set</button>
    </div>
  `,
methods: {
  add() {
    this.displayName = "圆圆";
  }
}

我们既能读displayName,也可以写它

  • 展示列表

 

let id = 0;
const createUser = (name, gender) => {
  id += 1;
  return { id: id, name: name, gender: gender };
};
new Vue({
  data() {
    return {
      users: [
        createUser("方方", "男"),
        createUser("圆圆", "女"),
        createUser("小新", "男"),
        createUser("小葵", "女")
      ],
      gender: ""
    };
  },
  computed: {
    displayUsers() {
      const hash = {
        male: "男",
        female: "女"
      };
      const { users, gender } = this;
      if (gender === "") {
        return users;
      } else if (typeof gender === "string") {
        return users.filter(u => u.gender === hash[gender]);
      } else {
        throw new Error("gender 的值是意外的值");
      }
    }
  },
  methods: {
    setGender(string) {
      this.gender = string;
    }
  },

  template: `
    <div>
      <div>
      <button @click="setGender('') ">全部</button>
      <button @click="setGender('male')">男</button>
      <button @click="setGender('female')">女</button></div>
      <ul>
        <li v-for="(u,index) in displayUsers" :key="index">{{u.name}} - {{u.gender}}</li>
      </ul>
      
    </div>
  `
}).$mount("#app");

computed有缓存属性,如果依赖的属性没有变化,也就不会重新计算;getter和setter默认不会做缓存,因为Vue做了特殊处理。

watch

监听/侦听(当数据变化时,执行一个函数)

  • 撤销

 

new Vue({
  data: {
    n: 0,
    history: [],
    inUndoMode: false
  },
  watch: {
    n: function(newValue, oldValue) {
      if (!this.inUndoMode) {
        this.history.push({ from: oldValue, to: newValue });
      }
    }
  },
  template: `
    <div>
      {{n}}
      <hr />
      <button @click="add1">+1</button>
      <button @click="add2">+2</button>
      <button @click="minus1">-1</button>
      <button @click="minus2">-2</button>
      <hr/>
      <button @click="undo">撤销</button>
      <hr/>
      {{history}}
    </div>
  `,
  methods: {
    add1() {
      this.n += 1;
    },
    add2() {
      this.n += 2;
    },
    minus1() {
      this.n -= 1;
    },
    minus2() {
      this.n -= 2;
    },
    undo() {
      const last = this.history.pop();
      this.inUndoMode = true;
      const old = last.from;
      this.n = old; // watch n 的函数会异步调用
      this.$nextTick(() => {
        this.inUndoMode = false;
      });//nextTick延迟回调
    }
  }
}).$mount("#app");
  • 模拟computed(不建议使用)

 

new Vue({
  data: {
    user: {
      email: "fangfang@qq.com",
      nickname: "方方",
      phone: "13812312312"
    },
    displayName: ""
  },
  watch: {
    "user.email": {
      handler() {
        const {user: { email, nickname, phone }} = this;//从this中解析出user,从user中解析出三个变量
        this.displayName = nickname || email || phone;
      },
      immediate: true // 第一次渲染也触发 watch
    },
    "user.nickname": {
       handler() {
        const {user: { email, nickname, phone }} = this;
        this.displayName = nickname || email || phone;
      },
      immediate: true
    },
    "user.phone": {
       handler() {
        const {user: { email, nickname, phone }} = this;
        this.displayName = nickname || email || phone;
      },
      immediate: true
    }
  },
  template: `
    <div>
       {{displayName}}
       <button @click="user.nickname=undefined">remove nickname</button>
    </div>
  `,
  methods: {
    changed() {
      console.log(arguments);
      const user = this.user;
      this.displayName = user.nickname || user.email || user.phone;
    }
  }
}).$mount("#app");

什么是变化

 

new Vue({
  data: {
    n: 0,
    obj: {
      a: "a"
    }
  },
  template: `
    <div>
      <button @click="n += 1">n+1</button>
      <button @click="obj.a += 'hi'">obj.a + 'hi'</button>
      <button @click="obj = {a:'a'}">obj = 新对象</button>
    </div>
  `,
  watch: {
    n() {},
    obj() {},
    "obj.a": function() {}
  }
}).$mount("#app");

当点击“n+1”时,n变为1
当点击“obj.a + 'hi'”时,obj没有变(内存地址没变),obj.a变了
当点击"obj = 新对象"时,obj变了(内存地址变了),obj.a没变
但如果需要obj.a变了的同时obj也变,可以使用deep:true,意思时监听object的时候往深了看,默认为false。
watch语法

  • watch: {a: function (val, oldVal) {}}也可以是watch: {a() {}}
  • watch: {b: [f1,f2]}
  • watch: {c: 'methodName'}
  • watch: {d: {handler:fn, deep:true, immediate:true}}
  • `vm.$watch('n', function(){}, {immediate: true})
    注意:不要使用箭头函数,因为this 将不会按照期望指向 Vue 实例,而是全局对象

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值