watch和computed的区别

作者: 宏_4491 | 来源:发表于2021-03-05 10:55 被阅读0次

    计算属性Computed:

    计算属性通常依赖于其他数据属性。对于依赖属性的任何改变都会触发计算属性的逻辑。计算属性基于它们的依赖关系进行缓存,因此只有当依赖项发生变化时,它们才会重新运行,否则他会使用缓存中的属性值。(例如,返回 new Date()的计算属性将永远不会重新运行,因为逻辑将不会运行超过一次)。计算属性在默认情况下是getters,但是如果需要实现类似的功能,则可以设置setter函数。
    计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。

    watch:
    watch用来监听当一个数据属性值发生变化时,就可以调用的函数,没有必须依赖的数据属性;属于异步操作;
    Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。

    举个栗子

    var var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar',
        fullName: 'Foo Bar'
      },
      watch: {
        firstName: function (val) {
          this.fullName = val + ' ' + this.lastName
        },
        lastName: function (val) {
          this.fullName = this.firstName + ' ' + val
        }
      }
    })
    
    var var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar'
      },
      computed: {
        fullName: function () {
          return this.firstName + ' ' + this.lastName
        }
      }
    })
    

    但数据量较大的时候,用watch更合适;在过滤数据的时候用computed。

    computed的基础用法:
    计算属性的getter函数---当其依赖的属性的值发生变化的时,这个计算属性的值也会自动更新。多用于"data,computed"的属性。
    计算属性的setter函数---当赋值给计算属性的时候,将调用setter函数。多用于在模板组件中需要修改计算属性自身的值的时候,例子如下:

    computed: {
          didiFamily:{
            //getter
            get:function(){
              return this.didi + ' ' + this.family
            },
            //setter
            set:function(newValue){
              // 这里由于该计算属性被赋值,将被调用
              console.log(newValue)
              this.didi = 123
              this.family = 456
            }
          }
        }
    

    计算属性的缓存---Vue实例中被观察的数据属性发生了改变时才会重新执行getter,但是我们有时候计算属性依赖实时的非观察数据属性,比如下面例子中的Data.now

    computed: {
          now:{
            cache: false,
            get:function(){
              return Date.now() + this.message
            }
          }
        }
    

    computed的常见问题:

    计算属性getter不执行的场景---当包含计算属性的节点被移除并且模板中其他地方没有再引用该属性的时候,那么对应的计算属性的getter函数方法不会执行
    在v-for中使用计算属性,起到类似"过滤器的作用",例子如下:

    <template>
      <div>
        <h4>测试</h4>
        <div>
          <ul>
            <li v-for="n in evenNumbers">{{n}}</li>
          </ul>
        </div>
      </div>
    
    </template>
    
    <script>
       export default {
        data () {
           return {
            numbers: [ 1, 2, 3, 4, 5 ]
           }
         },
        computed: {
          evenNumbers () {
            return this.numbers.filter(function (number) {
              return number % 2 === 0
            })
          }
        }
      }
    </script>
    

    watch与computed的set函数的比较---uex 接收 的computed ,用set监测不到变化,必须要用watch才可以生效;(原理:实质没有改变computd的值,只是改变了get的return值 => 组件外的访问)
    v-model 改变的computed,用watch监测不到变化,必须要用computed对象中的set函数方法才能监测得到(原理:相当于每次改变了computed自身的值 => 组件内的访问)

    computed和watch都不可用箭头函数,因为箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.a 将是 undefined。

    watch的基础用法:

    父组件通过props向子组件传入的值,在子组件中是不可修改的,不然会报错,但是如果需要根据页面需求对props传入的值进行修改的话,则可以在data中重新定义一个变量,改变指向,通过watch来监测props值的改变,并实时修改data中变量的值,例子如下:

    <template>
        <div class="base_radio_wrap">
            <span class="base_radio_title">{{propsLabel}}</span>
            <span
                class="base_radio_item"
                :class="{'base_radio_item_actived': i.label == current}"
                @click="handlerClick(i.label)"
                v-for="i in list"
                v-if="!i.disabled"
                v-text="i.label">
            </span>
        </div>
    </template>
    <script>
    export default {
        name: 'baseRadio',
        data () {
            return {
                current: this.propsCurrent,
                list: this.propsList
            }
        },
        methods: {
            handlerClick (value) {
                this.current = value
                this.$emit('formChange', {
                    'type': this.propsName,
                    'value': value
                })
            }
        },
        watch: {
            // 响应父级数据变化
            propsCurrent (val, oldVal) {
                this.current = val
            },
            propsList (val, oldVal) {
                this.list = val
            }
        },
        props: ['propsLabel', 'propsName', 'propsCurrent', 'propsList']
    }
    </script>
    

    handler方法immediate属性和deep属性

    这里 watch 的一个特点是,最初绑定的时候是不会执行的,要等到 firstName 改变时才执行监听计算。
    那我们想要一开始就让他最初绑定的时候就执行改immediate: true。

    handler,Vue.js会去处理这个逻辑,最终编译出来其实就是这个handler。

    deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改里面任何一个属性都会触发这个监听器里的 handler。

    举个栗子:

    <div>
          <p>obj.a: {{obj.a}}</p>
          <p>obj.a: <input type="text" v-model="obj.a"></p>
    </div>
     
    new Vue({
      el: '#root',
      data: {
        obj: {
          a: 123
        }
      },
      watch: {
        obj: {
          handler(newName, oldName) {
             console.log('obj.a changed');
          },
          immediate: true,
          deep:true
        }
      } 
    })
    

    最后总结一下:watch用来监听数据属性,computed可以用作监听数据属性(数据可以缓存),也可以计算属性值(比如:C值=A值+B值,监听C值, 如果A值或B值发生了改变,C值就会被改变,或者说是计算,C值不用再data中定义,直接在computed中定义就可以使用了)

    相关文章

      网友评论

        本文标题:watch和computed的区别

        本文链接:https://www.haomeiwen.com/subject/afkrqltx.html