Vue ---- 计算(computed)属性和侦听(watch)属性

提示:主要内容来自老杜的Vue视频教学,大家可以去学习!!!
注意:如果大家看我的文章的话记得直接将代码复制过去运行,然后前后对比学习。

Vue ---- 计算(computed)属性和侦听(watch)属性

  • 计算属性案例引入
    • 插值语法实现字符串反转案例1
      • 存在的问题
    • methods配置项实现字符串反转案例2
      • 存在的问题
    • 计算属性实现字符串反转案例3
      • 计算属性
      • 代码示例
  • 侦听属性的变化
    • 代码样例
  • 总结
    • computed 和 watch 的选择
      • computed 实现比较大小案例
      • watch 实现比较大小案例
    • 关于函数的写法,写普通函数还是箭头函数?
  • 参考


计算属性案例引入

插值语法实现字符串反转案例1

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>字符串反转案例title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="app">
        <h1>{{msg}}h1>
        输入的数据:<input type="text" placeholder="请输入您需要反转的数据" v-model="data"> <br>
        反转的数据:{{data.split('').reverse().join('')}}
    div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                msg: '字符串反转案例',
                data: ''
            }
        })
    script>
body>
html>

存在的问题

  • 可读性差
  • 代码没有得到复用
  • 难以维护

methods配置项实现字符串反转案例2

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>methods 计算属性----实现字符串的反转title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="app">
        <h1>{{msg}}h1>
        输入的数据:<input type="text" placeholder="请输入您需要反转的数据" v-model="info"> <br>
        反转的数据:{{reversedData()}}  <br>
        {{reversedData()}}  <br>

    div>
    <script>
        let count = 0
        const vm = new Vue({
            el : '#app',
            data : {
                msg: 'methods 实现字符串反转',
                info: ''
            },
            methods: {
                reversedData(){
                    count++;
                    return this.info.split('').reverse().join('')
                }
            }
        })
    script>
body>
html>

存在的问题

  • 当有多个地方使用 methods 时同一个函数会被多次调用,效率十分的低。

计算属性实现字符串反转案例3

计算属性

  • 什么是计算属性?
    • 使用 Vue 的原有属性,经过一系列的运算/计算,最终得到了一个全新的属性,叫做计算属性。
      • Vue 的原有属性:data 对象当中的属性可以叫做 Vue 的原有属性。
      • 全新的属性:表示生成了一个新的属性,和 data 中的属性无关了,新的属性也有自己的属性名和属性值。
  • 计算属性怎么用?
    • 语法格式:需要一个新的配置项 computed(具体使用方法见代码示例部分)
      • get方法被自动调用的两个时机:(缓存机制的实现关键点在调用 getter 方法的时机)
        1.第一次访问这个属性的时候。
        2.该计算属性所关联的 Vue 原有属性的值发生变化时,getter方法会被重新调用一次。
      • set 方法在计算属性值被修改的时候,set 方法被自动调用
      • 注意:getter 和 setter 方法中的 this 就是 Vue 实例对象,但是不能使用箭头函数,使用箭头函数会导致 this 的指向是:window
      • 由于 setter 方法使用的很少,当不使用set方法的时候可以采用简写的方式(具体使用方法详见参考代码)
  • 计算属性的作用?
    • 代码得到复用。
    • 代码更加便于维护。
    • 代码的执行效率高了。(利用了缓存机制)
  • 注意:计算属性也是代理机制实现的,但是_data和$data中没有计算属性,因为计算属性是computed对象中的不是data对象中的。

代码示例

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>计算属性实现字符串反转title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="app">
        <h1>{{msg}}h1>
        原始输入数据:<input type="text" placeholder="请输入您需要反转的数据" v-model="info"> <br>
        反转后的数据:{{reversedData}} <br>
        {{reversedData}} <br>
        {{reversedData}} <br>
        {{reversedData}} <br>
        {{reversedData}} <br>
    div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                msg: '计算属性----实现字符串的反转',
                info: ''
            },
            computed:{
                // reversedData:{
                //     get(){
                //         console.log('计算属性的 getter方法执行了!!!')
                //         return this.info.split('').reverse().join('')
                //     },
                //     set(){}
                // }
                //计算属性的简写形式,注意这里看起来和函数是一模一样的但是这是一个计算属性
                reversedData(){
                    return this.info.split('').reverse().join('')
                }
            }
        })
    script>
body>
html>

侦听属性的变化

  • data 中的就是属性。
  • 侦听属性的变化其实就是监听某个属性的变化。当被监听的属性一旦发生改变时,执行某段代码。
  • 监听属性变化时使用的就是 watch 配置项。
  • 如何深度监视:
    • 监视多级结构中某个属性的变化,写法是: ‘a.b.b’:{}。注意:要使用单引号。
    • 监视多级结构中的所有属性的变化,可以通过添加深度监听来完成:deep: true。因为多级结构的顶级是一个对象,对象存储的是地址,内容改变了地址没有改变,所以不能直接写属性名。
  • 如果需要让该代码片段立即执行需要配置 immediate: true。
  • 如何后期添加监视:
    • 调用 API: vm.$watch(‘需要添加监视的属性名’,{})
  • watch 的简写:
    • 简写的前提条件:当不需要配置 immediate 和 deep 时,可以简写
    • 如何简写:
      • watch: {监听的属性名(newValue, oldValue){},…}
    • 后期添加的监视如何简写:
      • vm.$watch(‘需要添加监视的属性名’, function(newValue, oldValue){})

代码样例

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>监听属性的变化title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id='app'>
        <h1>{{msg}}h1>
        姓名:<input type="text" placeholder="请输入姓名" v-model="stu.name"> <br>
        年龄:<input type="text" placeholder="请输入年龄" v-model="stu.age"> <br>
        {{stu.profile}}
        
    div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                msg: '监听属性的变化',
                stu: {
                    name: 'jackson',
                    age: 18,
                    profile: ''
                }
            },
            watch: {
                stu:{
                    deep: true,    //监听整个对象,如果对象中任何东西变化就会执行 handler 中的代码片段
                    immediate: true,
                    handler(newValue, oldValue){
                        this.stu.profile = '我叫' + this.stu.name + ",今年" + this.stu.age + '岁了。'
                    }
                }
            }
        })
    script>
body>
html>

总结

computed 和 watch 的选择

  1. computed 和 watch 如果都能够完成某个功能,优先选择 computed。
  2. 有 一种情况下,必须使用 watch,computed 无法完成!!!
    • 如果程序当中采用了异步的方式。只能使用 watch。

computed 实现比较大小案例

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>比较大小案例title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="app">
        <h1>{{msg}}h1>
        数值1:<input type="number" v-model="number1"> <br>
        数值2:<input type="number" v-model="number2"> <br>
        比较的结果:{{comparedInfo}}
    div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                msg: 'computed实现比较大小案例',
                number1: 0,
                number2: 0
            },
            computed: {
                comparedInfo(){
                    res = this.number1 - this.number2
                    if (res == 0)
                        return this.number1 + '=' + this.number2
                    return res>0 ? this.number1 + '>' + this.number2 : this.number1 + '<' + this.number2
                }
            }
        })
    script>
body>
html>

watch 实现比较大小案例

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>比较大小案例title>
    <script src="../js/vue.js">script>
head>
<body>
    <div id="app">
        <h1>{{msg}}h1>
        数值1:<input type="number" v-model="number1"> <br>
        数值2:<input type="number" v-model="number2"> <br>
        比较的结果:{{comparedInfo}}
    div>
    <script>
        const vm = new Vue({
            el : '#app',
            data : {
                msg: 'watch实现比较大小案例',
                number1: 0,
                number2: 0,
                comparedInfo: ''
            },
            watch: {
                //不使用简写的方式
                number1:{
                    immediate: true,
                    handler(newValue, oldValue){
                        res = newValue - this.number2
                        if(res == 0)
                            this.comparedInfo = newValue + '=' + this.number2
                        else if(res > 0)
                            this.comparedInfo = newValue + '>' + this.number2
                        else
                            this.comparedInfo = newValue + '<' + this.number2
                    }
                },
                //使用简写的方式
                number2(newValue, oldValue){
                    res = newValue - this.number1
                        if(res == 0)
                            this.comparedInfo = this.number1 + '=' + newValue
                        else if(res > 0)
                            this.comparedInfo = this.number1 + '<' + newValue
                        else
                            this.comparedInfo = this.number1 + '>' + newValue
                }
            }
        })
    script>
body>
html>

关于函数的写法,写普通函数还是箭头函数?

  • 不管写普通函数还是箭头函数,目标是一致的,都是为了让 this 和 vm 相等。
  • 所有 Vue 管理的函数,建议写成普通函数。
  • 所有不属于 Vue 管理的函数,例如 setTimeout 的回调函数、Promise 的回调函数、AJAX的回调函数,建议使用箭头函数。

参考

其他参考文章以及文章部分内容的来源
来源:老杜的视频讲解

你可能感兴趣的:(Vue,vue.js,前端,javascript)