watch监听表单的某个值_Vue-computed 和 watch

Computed计算属性

被计算出来的属性就是计算属性

例子1、用户名展示 可以将一些根据其他计算出来的属性变成一个属性

import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;

new Vue({
  data: {
    user: {
      email: "12345678@qq.com",
      nickname: "小明",
      phone: "15612312312"
    }
  },
  computed: {
    displayName: {
      get() {
        const user = this.user;
        return user.nickname || user.email || user.phone;
      },
      set(value) {
        console.log(value);
        this.user.nickname = value;
      }
    }
  },
  // 不如用 computed 来计算 displayName
  template: `
    <div>
      {{displayName}}
      <div>
      {{displayName}}
      <button @click="add">set</button>
      </div>
    </div>
  `,
  methods: {
    add() {
      console.log("add");
      this.displayName = "小红";
    }
  }
}).$mount("#app");

例子2、列表展示

import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;
let id = 0;
const createUser = (name, gender) => {
  id += 1;
  return { id, name, gender };
};
new Vue({
  data() {
    return {
      users: [
        createUser("方方", "男"),
        createUser("圆圆", "女"),
        createUser("小新", "男"),
        createUser("小葵", "女")
      ]
    };
  },
  // 如何给三个按钮加事件处理函数
  // 思路一:点击之后改 users
  // 思路二:使用 computed
  template: `
    <div>
      <div><button>全部</button><button>男</button><button>女</button></div>
      <ul>
        <li v-for="u in users" :key="u.id">
          {{u.name}} - {{u.gender}}
        </li>
      </ul>
    </div>
}).$mount("#app");

不使用computed

// 引用完整版 Vue,方便分析
import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;
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("小葵", "女")
      ],
      displayUsers: []
    };
  },
  created() {
    this.displayUsers = this.users;
  },
  methods: {
    showMale() {
      this.displayUsers = this.users.filter(u => u.gender === "男");
    },
    showFemale() {
      this.displayUsers = this.users.filter(u => u.gender === "女");
    },
    showAll() {
      this.displayUsers = this.users;
    }
  },

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

每一个button都对应一个method。按下对应的button都要处理一次。

2e51a47b4553cbd0fa067a173b3a8854.png

使用computed

import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;
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");

4d7637f974d58ae48b942080655af873.png

button只设置了依赖属性gender,不同gender对应的变化由computed去计算。

76bfac7118c5b0c8a8f5107e5b7009d4.png

缓存

如果依赖的属性没有变化,就不会重新计算

getter / setter默认不会做缓存,Vue做了特殊处理

Watch-监听

在用户数据变化的时候执行一个函数

例子1、撤销

import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;

new Vue({
  data: {
    n: 0,
    history: [],
    inUndoMode: false
  },
  watch: {
    n: function(newValue, oldValue) {
      console.log(this.inUndoMode);
      if (!this.inUndoMode) {
        this.history.push({ from: oldValue, to: newValue });
      }
    }
  },
  // 不如用 computed 来计算 displayName
  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;
      console.log("ha" + this.inUndoMode);
      const old = last.from;
      this.n = old; // watch n 的函数会异步调用,会等把当前的代码执行完后才调用watch,
                                              如果不设定后面的代码,会一直是false状态
      this.$nextTick(() => { //
        this.inUndoMode = false;//尽快变成false,加了此句后watch会先于此部
      });
    }
  }
}).$mount("#app");

例子2、模拟computed,很复杂

import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;

new Vue({
  data: {
    user: {
      email: "fangfang@qq.com",
      nickname: "方方",
      phone: "13812312312"
    },
    displayName: ""
  },
  watch: {
    "user.email": {
      handler: "changed",
      immediate: true // 第一次渲染是也触发 watch,因为第一次从无到有watch不会监听
    },
    "user.nickname": {
      handler: "changed",
      immediate: true // 第一次渲染是也触发 watch
    },
    "user.phone": {
      handler: "changed",
      immediate: true // 第一次渲染是也触发 watch
    }
  },
  // 不如用 computed 来计算 displayName
  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");

33e37620cac7f9fd6f9ce7458101af27.png

当email变化时,从this里解析处user,再从user里解析出email,nickname,phone三个变量

watch默认不监听第一次变化,使用handler和immediate,设置immediate:true,handler就会立即执行

43a57675bfd673707316b0eabb9933ef.png

什么是变化?

例子:

import Vue from "vue/dist/vue.js";

Vue.config.productionTip = false;

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() {
      console.log("n 变了");
    },
    obj() {
      console.log("obj 变了");
    },
    "obj.a": function() {
      console.log("obj.a 变了");
    }
  }
}).$mount("#app");

obj原本是{a:'a'},现在obj={a:'a'},请问obj变了没有?(变了,其地址变了) obj.a变了没有(没有,之前是a现在还是a)

简单类型看值,复杂类型(对象) 看地址,这其实就是===的规则

deep: true是干什么的?

如果object.a变了,请问object算不算也变了

如果你需要答案是「也变了」,那么就用deep:true

如果你需要答案是「没有变」,那么就用deep:false

deep的意思是,监听object的时候是否往深了看

语法:查看文档 https://cn.vuejs.org/v2/api/#watch

箭头函数没有this,获取不到this.n,watch不要使用箭头函数

a5b75874b3e6a87c9409829df74f0818.png

watch和computed的区别

computed是计算属性的意思,watch是监听的意思;computed是用来计算出一个值,这个值在调用的时候不需要括号可以当成属性去使用,它会根据依赖去自动缓存,如果依赖不变computed的值就不会自动计算;watch在用户数据变化的时候执行一个函数,它有两个选项,第一个immediate表示第一次渲染的时候是否执行这个函数,第二个deep,监听一个对象是是否要监听该属性里面的变化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值