Vue2-computed&watch

computed & watch 官方文档:API — Vue.js 

1.computed 计算属性

#computed:{ [key: string]: Function | { get: Function, set: Function } }
new Vue({
    data: {
        user: {
            email: "fangyinghang@qq.com",
            nickname: "方方",
            phone: "13812312312"
        }
    },
    computed:{
        /* [语法一]computed:{ [key: string]: Function } */
        displayNameXXX(){
            const user=this.user
            return user.email || user.nickname || user.phone
        },
        /* [语法二]computed:{ [key: string]: { get: Function, set: Function } } */
        displayName:{
          get(){
              const user=this.user
              return user.nickname || user.email || user.phone
          },
          set(value){
              this.user.nickname = value
          }
      }
    },
    template: `
    <div>
      {{displayNameXXX}}
      <div>
        {{displayName}}
        <button @click="set">set</button>
      </div>
    </div>
  `,
    methods:{
        set(){
            this.displayName='思思'
        }
    }
}).$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("小玮","女"),
            ],
            selectGender:''
        };
    },
    computed:{
      displayUsers(){
          /* computed缓存: 依赖属性没有变化不会重新计算 */
          console.log("displayUsers 计算了一次")

          /* hash表查 选取gender 值 */
          const hash={
              male: "男",
              female: "女"
          }
          const {users,selectGender} = this
          if(selectGender === ""){
              return users
          }else if(typeof selectGender === "string"){
              return users.filter(u => u.gender===hash[selectGender])
          }else{
              throw new Error("选择了意外 gender 值 !")
          }
      }
    },
    methods:{
        setGender(string){
            this.selectGender=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");

2.watch 监听

#watch 实现撤销功能
new Vue({
    data: {
        n: 0,
        history: [],
        /* watch 会监听所有变化,手动设置watch是否监听 */
        inUndoMode: false
    },
    watch: {
        n(newValue,oldValue){
            console.log(`在不在撤销模式: ${this.inUndoMode ? "yes":"no"}`)
            if(!this.inUndoMode){
                this.history.push({from: oldValue,to: newValue})
                console.log(`n: ${this.n}`)
            }
        }
    },
    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()
            const oldValue = last.from
            this.inUndoMode = true
            this.n = oldValue
            console.log(`last n: ${this.n}`)
            /* watch 的回调是异步的,同级别的异步api $nextTick() 保证 this.inUndoMode = false 在 this.n = oldValue 执行后执行*/
            this.$nextTick(()=>{
                this.inUndoMode = false
            },0)
        }
    }
}).$mount("#app");
#使用 watch 模拟 computed 展示用户信息
new Vue({
    data: {
        user: {
            email: "fangfang@qq.com",
            nickname: "方方",
            phone: "13812312312"
        },
        displayName: ""
    },
    watch: {
        "user.email":{
            /* 处理器 */
            handler: "changed",
            /* 第一次渲染也触发 watch */
            immediate: true
        },
        "user.nickname":{
            handler: "changed",
            immediate: true
        },
        "user.phone":{
            handler: "changed",
            immediate: true
        },
    },
    // 不如用 computed 来计算 displayName
    template: `
    <div>
       {{displayName}}
       <button @click="user.nickname=undefined">remove nickname</button>
    </div>
  `,
    methods: {
        changed(){
            console.log(arguments)
            const {user: {email,nickname,phone}} = this
            this.displayName = nickname || email || phone
        }
    }
}).$mount("#app");


## computed & watch: 都是在数据出现变化时,执行一个函数
## computed 着重于依赖之间变化以及缓存
## watch  着重于数据变化时执行什么,而不是得出结果
#watch(监听器)判断数据是否变化:  [ === 判断规则]
#简单类型value值变化,复杂类型(对象Object)地址变化

new Vue({
    data: {
        n: 0,
        obj: {
            a: "a",
            b: "b",
        }
    },
    template: `
    <div>
      <div>
        {{ n }}
        {{ obj }}
      </div>
      <button @click="n += 1">n+1</button>
      <button @click="obj.a += 'hi'">obj.a + 'hi'</button>
      <button @click="obj = {a:'a',b:'b'}">obj = 新对象</button>
    </div>
  `,
    watch: {
        /* [watch监听变化] 简单类型值变了就认为变化 */
        n() {
            console.log("n 变了");
        },
        /* [复杂类型] 对象地址变化才认为变化 */
        obj() {
            console.log("obj 变了");
            console.log(this.obj)
        },
        /* [复杂类型] obj.a对象中的值依旧是简单类型,值变化就变化;但对象不变化(地址没有改变) */
        "obj.a": function() {
            console.log("obj.a 变了");
            console.log(this.obj)
        },
        "obj.b": function() {
            console.log("obj.b 变了");
        }


        /* deep: true 无论嵌套多深,有值 property 改变,对象监听为变化 */
        /*
        * obj: {
        *     handler(){ 
        *         console.log("obj 变了");
        *     },
        *     deep: true
        * },
        * */ 
    }
}).$mount("#app");

3.computed 与 watch 区别

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值