Vue入门--第三天--computed和watch

Vue构造选项-进阶属性

今天主要是学以下进阶属性

  • computed 计算属性
  • watch 侦听
  • directives 指令
  • mixin 混入
  • extends 继承
  • provide/inject

之前学了options.data
除了data变化更新UI,还能做点啥?

下面的代码运行在完整版的Vue中

computed - 计算属性

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

new Vue({
  data: {
    user: {
      email: "111111@qq.com",
      nickname: "小王",
      phone: "12323121322"
    }
  },
  computed: {
    displayName: {
      get() {
        const user = this.user;
        return user.nickname || user.email || user.phone;
      },
      set(value) {
        this.user.nickname = value;
      }
    }
  },
  template: `
    <div>
      {{displayName}}
      <div>
        {{displayName}}
        </button @click="add">set</button>
      </div>
    </div>
  `,
  methods: {
    add(){
      this.displayName = '圆圆'
    }
  }
})

get和set让我们可以直接读和写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("小葵", "女"),
      ]
    };
  },

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

需求:点击男就显示全部男的,女和全部同理

思路:不能改变原来的users,那就再去开辟一个新的地方,需要些什么就存什么,然后展示出来

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>
      <ul>
        <li v-for="(u, index) in displayUsers" :key="index">{{u.name}} - {{u.gender}}</li>
      </ul>
    </div>
  `
}).$mount("#app")

这是没有用计算属性实现的,可以看到有一些重复,代码不够简洁。

下面是使用computed的代码

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: {//这个计算出来的就是我们要的,是根据users和gender计算出来的
    displayUsers(){
      const {users, gender} = this
      if(gender === ''){
        return users
      }else if(gender === 'male'){
        return users.filter(u => u.gender === "男")
      }else if(gender === 'female') {
        return users.filter(u => u.gender === "女")
      }
    }
  },
  methods: {
    showMale() {
      this.gender = 'male';
    },
    showFemale() {
      this.gender = 'female';
    },
    showAll(){
      this.gender = '';
    }
  },

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

上面的代码button里面用到gender这些data里面的值,都不需要加this
这样的写法就简单了很多,好懂而且方便改动代码。

computed是有缓存的
意思是:如果我依赖的属性没有变化,这个计算属性就不会再算一次。上面的就是users和gender不变就不会重新计算,一直点击全部,也只会计算一次。

watch - 监听/侦听

用途
当数据变化时,执行一个函数
和computed差不多,都是数据变了,就计算出新的属性,不过还是有区别

watch就是用来监听,就是会执行写的那个函数
但是有时候就不需要执行这个函数,很简单,添加一个判断是否需要执行的一个变量,用if(){},来做就行。

methods

undo() {
  this.inUndoMode = true;
  this.n = old;
  this.inUndoMode = false;
}

data

data: {
  n: 0,
  history: [],
  inUndoMode: false
}

watch

watch: {
  n(newValue, oldValue) {
    console.log(this.inUndoMode)
    if(!this.inUndoMode) {
      //执行操作
    }
  }
}

这个n(){}就是监听data中的n,n变了,就执行里面的代码

但是watch异步的,methodsthis.n = old之后,会立刻去执行watch中的函数吗?
不会,所以一直把methods中的
this.inUndoMode = false;执行了,才去执行watch函数

所以模式还是没有改变

解决:做一个等待,等watch执行了就可以执行this.inUndoMode = false;

methods

watch: {
    undo() {
    this.inUndoMode = true;
    this.n = old;
    this.$nextTick(() => {
      this.inUndoMode = false;
    })
  }
}

this.$nextTick就是Vue里面自己封装的异步函数。
现在就解决了这个问题。

watch: {
  n : {handler(){},immediate: true}
}

当一个数据初始化的时候,watch提供了一个参数的值,immediatetrue就在初始化的时候就开始监听,false就在后面变化的时候监听

这样就和computed的功能差不多没区别了
不过都有了computed,为什么还要不用它而去模拟它呢,所以用处不大.

都是在数据变化的时候执行一个函数
computed着重于依赖之间的变化,得出一个结果
watch着重于变化时去执行什么东西,

数据变化

什么是数据变化?

  • 简单类型看值
  • 复杂类型看地址
    就是===看是否相等
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("a 变了");
    },
  }
})

上面的代码。如果是监听对象里面的属性,就写成"obj.a": function() {}
如果a变了,点击了第二个按钮,obj也没有变化(因为地址没有变)
如果点击按钮三,就会发现obj变了,但是还是{a: 'a'},所以a没有变化

这里是一个对象地址变了,这个对象在Vue中才算变了,才会触发watch的监听

需求:对象里面的属性的值变了,也算对象变了,这里有一个deep属性
watch
obj: {handler(){}, deep: true}
这样就是里面的属性变了,那么这个obj就变了,就会触发watch里面的函数。

watch里面不要写箭头函数,因为watch要用到this,箭头函数没有自己的this,得不到vm,而写function,当这个函数被调用时,就会给被Vue传递一个thisvm

new Vue({...})这是函数的调用
function x() {}这才是函数的声明
前者this指向window或者全局属性
后者this指向x这个函数

还可以使用

this.$watch('n', function(){})

这样来是用watch,可以放到生命周期钩子中使用。

总结

computed

  • 计算属性
  • 计算出一个值,使用这个值不用加括号
  • 根据依赖的变化,有缓存

watch

  • 监听
  • immediate 第一次渲染的时候是否执行函数
  • deep 监听对象时,是否要看对象里面的属性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值