[Vue]监视属性

简介: [Vue]监视属性

43cdcf91c98c4f1a98d8dbe4002392f9.jpg


前言

系列文章目录:

[Vue]目录

老师的课件笔记,不含视频 https://www.aliyundrive.com/s/B8sDe5u56BU

笔记在线版: https://note.youdao.com/s/5vP46EPC

视频:尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通

1. 实现效果

2. methods实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">切换天气</button>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      // 标记天气是否炎热
      isHot: true
    },
    computed: {
      info() {
        return this.isHot ? '炎热' : '凉爽'
      }
    },
    methods: {
      // 修改天气
      changeWeather() {
        this.isHot = !this.isHot
      }
    },
  })
</script>
</html>

3. js表达式实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="isHot = !isHot">切换天气</button>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      // 标记天气是否炎热
      isHot: true
    },
    computed: {
      info() {
        return this.isHot ? '炎热' : '凉爽'
      }
    }
  })
</script>
</html>

4. 监视属性实现

上述效果实现的代码,是通过修改isHot的值,当isHot的值改变时,Vue会重新解析模板,由于计算属性info依赖于isHot,当isHot改变时,info会被重新调用,从而实现效果。

监视属性使用watch侦听器实现,侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作。这样子就不用使用另外单独书写的函数针对数据的变化进行相应的处理。

4.1 handler()

handler()为属性侦听器的回调函数,当被监视的属性值变化时,回调函数会自动调用,进行相应的处理

watch: {
      isHot: {
        // 当被监视的属性值变化时,回调函数会自动调用,进行相应的处理
        handler() {
          console.log('isHot被修改了')
        }
      }
    }

当被监视的属性值变化时,回调函数会自动调用,进行相应的处理,同时会向处理函数传入两个参数,第一个参数为改变后的值,第二个参数修改之前的值。

watch: {
      isHot: {
        // 当数据元素的值改变时,调用的处理函数为handler
        handler(newVal, oldVal) {
          console.log('isHot被修改了', '新的值为:', newVal, '旧的值为:', oldVal)
        }
      }
    }

4.2 immediate

immediate,默认值为false。

immediate的值设置为true,初始化数据元素时,立即调用属性侦听器的回调函数handler()。

watch: {
      isHot: {
        // 初始化时,立即调用handler()
        immediate: true,
        // 当数据元素的值改变时,调用的处理函数为handler
        handler(newVal, oldVal) {
          console.log('isHot被修改了', '新的值为:', newVal, '旧的值为:', oldVal)
        }
      }
    }

4.3 通过vue实例对象监视属性

这种写法用于最开始不知道要监视什么属性,后期知道要监视的属性,需要添加监视属性时使用。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="isHot = !isHot">切换天气</button>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      // 标记天气是否炎热
      isHot: true
    },
    computed: {
      info() {
        return this.isHot ? '炎热' : '凉爽'
      }
    }
  })
  // 使用vue实例监视属性必须保证vue实例已经创建完成
  // 调用$watch()方法实现
  // 第一个参数为需要进行监视的属性名
  // 第二个参数为对应的配置项
  vm.$watch('isHot', {
    // 初始化时,立即调用handler()
    immediate: true,
    // 当被监视的属性值变化时,回调函数会自动调用,进行相应的处理
    handler(newVal, oldVal) {
      console.log('isHot被修改了', '新的值为:', newVal, '旧的值为:', oldVal)
    }
  })
</script>
</html>

4.4 深度监视

实现深度监视使用deep,默认值为false。vue提供的属性侦听器默认不能监视多级结构中某个属性的变化。

开启深度监视,能够监视多级结构中某个属性的变化。

vue自身可以监测对象内部值的改变,即vue能够监视多级结构中某个属性的变化,但是vue提供的watch默认不可以。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    <h2>a的值:{{num.a}}</h2>
    <button @click="num.a++">点击使a加一</button>
    <h2>b的值:{{num.b}}</h2>
    <button @click="num.b++">点击使b加一</button>
    <br><br>
    <button @click="num = {a: 666, b: 888}">点击修改num的值</button>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      isHot: true,
      num: {
        a: 1,
        b: 2
      }
    },
    watch: {
      // 监视num,当num里面的值修改了也视为num改变
      num: {
        deep: true,
        handler(newVal, oldVal) {
          console.log('num被修改了')
        }
      }
    }
  })
</script>
</html>

4.5 监视属性的简写

如果监视属性不需要设置初始化立即调用监视属性的回调函数,也不需要设置深度监视,可以使用监视属性的简写形式。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="isHot = !isHot">切换天气</button>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      isHot: true,
      num: {
        a: 1,
        b: 2
      }
    },
    computed: {
      info() {
        return this.isHot ? '炎热' : '凉爽'
      }
    },
    watch: {
      // 完整写法:
      // isHot: {
      //   // immediate: true,
      //   // deep: true,
      //   handler(newVal, oldVal) {
      //     console.log('isHot被修改了', '新的值为:', newVal, '旧的值为:', oldVal)
      //   }  
      // }
      // 如果监视属性不需要设置初始化立即调用监视属性的回调函数
      // 也不需要设置深度监视,可以使用监视属性的简写形式
      // 此时的函数相当于原来的handler()
      isHot(newVal, oldVal) {
        console.log('isHot被修改了', '新的值为:', newVal, '旧的值为:', oldVal)
      }
    }
  })
</script>
</html>

4.6 $watch()监视属性的简写

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="isHot = !isHot">切换天气</button>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      isHot: true,
      num: {
        a: 1,
        b: 2
      }
    },
    computed: {
      info() {
        return this.isHot ? '炎热' : '凉爽'
      }
    }
  })
  // 完整写法:
  // vm.$watch('isHot', {
  //   // immediate: true,
  //   // deep: true,
  //   handler(newVal, oldVal) {
  //     console.log('isHot被修改了', '新的值为:', newVal, '旧的值为:', oldVal)
  //   }  
  // })
  // 简写形式
  vm.$watch('isHot', function() {
    console.log('isHot被修改了', '新的值为:', newVal, '旧的值为:', oldVal)
  })
</script>
</html>

4.7 监视属性实现天气案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="isHot = !isHot">切换天气</button>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      isHot: true,
      info: ''
    },
    watch: {
      isHot: {
        immediate: true,
        handler(newVal) {
          this.info = newVal ? '炎热' : '凉爽'
          console.log('当前的天气为:', this.info)
        }
      }
    }
  })
</script>
</html>

5. 监视属性与计算属性的对比

5.1 监视属性实现姓名案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    姓:<input type="text" v-model="firstname"> <br><br>
    名:<input type="text" v-model="lastname"> <br><br>
    姓名:<span>{{fullname}}</span>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      firstname: '张',
      lastname: '三',
      fullname: '张-三'
    },
    watch: {
      firstname(newVal) {
        this.fullname = newVal + '-' + this.lastname
      },
      lastname(newVal) {
        this.fullname = this.firstname + '-' + newVal
      }
    }
  })
</script>
</html>

5.2 案例结果显示延时

5.2.1 监视属性实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    姓:<input type="text" v-model="firstname"> <br><br>
    名:<input type="text" v-model="lastname"> <br><br>
    姓名:<span>{{fullname}}</span>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      firstname: '张',
      lastname: '三',
      fullname: '张-三'
    },
    watch: {
      firstname(newVal) {
        // 定时器中的this
        // 由于箭头函数没有自己的this
        // 所以会向外寻找this,firstname()有自己的this,指向vue实例对象
        // vue实例对象上的函数都有自己this,指向vue实例对象
        // 如果vue实例对象上的函数写成箭头函数,则由原来的有自己的this变为没有自己的this
        // 此时this指向Windows
        setTimeout(()=>{
          // 这里指向vue实例对象,是由于外层的函数有this且指向vue实例对象
          this.fullname = newVal + '-' + this.lastname
        }, 1000)
      },
      lastname(newVal) {
        setTimeout(()=>{
          this.fullname = this.firstname + '-' + newVal
        }, 1000)
      }
    }
  })
</script>
</html>

5.2.2 计算属性实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="root">
    姓:<input type="text" v-model="firstname"> <br><br>
    名:<input type="text" v-model="lastname"> <br><br>
    姓名:<span>{{fullname}}</span>
  </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
  const vm = new Vue({
    el: '#root',
    data: {
      firstname: '张',
      lastname: '三',
    },
    computed: {
      fullname() {
        // 由于计算属性需要一个返回值
        // 但是延时需要在setTimeout中的回调函数进行处理
        // 处理后的返回值无法进行接收,所有该功能无法实现
        setTimeout(()=>{
          return this.firstname + '-' + this.lastname
        }, 1000)
        return 123
      }
    }
  })
</script>
</html>

computed: {
      fullname() {
        // 使用如下的写法
        // 由于定时器的回调函数执行时间在return之后,所以还是无法实现需求
        let t = ''
        setTimeout(()=>{
          t = this.firstname + '-' + this.lastname
        }, 1000)
        return t
      }
    }

5.3 监视属性与计算属性的对比总结

  • computed和watch之间的区别:
  • computed能完成的功能,watch都可以完成
  • watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
  • 两个重要的小原则:
  • 所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vue实例对象或 组件实例对象
  • 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vue实例对象或 组件实例对象。



相关文章
|
1月前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
7天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
1月前
|
JavaScript 前端开发 开发者
Vue是如何劫持响应式对象的
Vue是如何劫持响应式对象的
29 1
|
1月前
|
JavaScript 前端开发 API
介绍一下Vue中的响应式原理
介绍一下Vue中的响应式原理
32 1
|
1月前
|
JavaScript 前端开发 开发者
vue 数据驱动视图
总之,Vue 数据驱动视图是一种先进的理念和技术,它为前端开发带来了巨大的便利和优势。通过理解和应用这一特性,开发者能够构建出更加动态、高效、用户体验良好的前端应用。在不断发展的前端领域中,数据驱动视图将继续发挥重要作用,推动着应用界面的不断创新和进化。
|
1月前
|
JavaScript 前端开发 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
1月前
|
存储 JavaScript 前端开发
介绍一下Vue的核心功能
介绍一下Vue的核心功能
|
1月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
41 1
vue学习第一章
|
1月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
30 1
|
1月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
38 1
vue学习第四章

热门文章

最新文章