最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue学习笔记之computed&watch

    正文概述 掘金(isisxu)   2021-02-01   365

    computed计算属性

    • 作用:用于在data数据被渲染前的操作,有利于逻辑代码和模板的分离。这里指明是data中的数据,因为data中的数据是响应式的。
    • 两种使用方式::
      • 可以在计算属性中直接使用this访问data的数据
      • 使用回调函数的形式接受一个vm实例通过vm实例访问data的属性
    • 注意点:computed中定义的属性名不能和data中的属性名重名,不然警告已经被定义The computed property "categories" is already defined in data.

    1. 基本使用

    <!-- 示例1:-->
    <div id="app">
      <!-- 这种比较繁琐 -->
      {{ this.firstName + ' ' + this.lastName }}
      <!-- 计算属性的方式比较简洁 -->
      {{ fullName }}
    </div>
    <script>
      new Vue({
        el: '#app',
        data: {
          firstName: 'Nice',
          lastName: 'alice'
        },
        computed: {
          // 通过箭头函数接受vm实例的方式
          fullName: vm => vm.firstName.concat('-').concat(vm.lastName)
        }
      })
    </script>
    
    <!-- 示例2: -->
    <body>
        <!-- 308 --308  -->
        <div id="app">{{ totalPrice }} -- {{totalPriceTwo}}</div>
        <script>
            var vm = new Vue({
                el: "#app",
                data: {
                    categories: [
                        { id: 1, name: '计算机网络', price: 100 },
                        { id: 2, name: '操作系统', price: 98 },
                        { id: 3, name: '深入理解计算机系统', price: 110 },
                    ]
                },
              	// 通过this的方式
                computed: {
                    totalPrice() {
                        return this.categories.reduce((a, b) => {
                            a.price += b.price
                            return a;
                        }, { price: 0 }).price
                    },
                    totalPriceTwo() {
                        return this.categories.map(item => item.price).reduce((a, b) => a + b);
                    },
                },
    
    
            });
        </script>
    </body>
    
    

    2. 计算属性本质

    • 计算属性的本质是包含settergetter方法的一个属性,所以在模板中访问的时候不是函数调用的方式,而是像访问data中的属性一样访问计算属性;说白了计算属性跟data中的数据属性一样是属性而不是方法
    • 如果没有自己实现set,那么计算属性默认是只读的,不能更改。
    <!-- 示例1:本质写法 -->
    <div id="app">{{ fullName }}</div>
    <script>
      var vm = new Vue({
        el: "#app",
        data: {
          firstName: 'Nice',
          lastName: 'alice'
        },
        computed: {
          // 本质是个包含setter和getter方法的对象; 在访问fullName属性时,会默认调用get函数,并将get函数的返回值作为fullName属性的值
          fullName: {
            set() { },
            get() {
              return this.firstName.concat(' ').concat(this.lastName)
            }
          }
        }
      });
    </script>
    
    // 示例2:简写过度阶段
    computed: {
      fullName: {
        get() {
            return this.firstName.concat(' ').concat(this.lastName)
        }
      }
    }
    
    // 示例3: 简写最终版————因为一般我们不希望别人给我们的计算属性设置值,所以就把set函数删掉了,相当于计算属性是个只读属性;那么计算属性都只有一个get方法,每次都写get方法太麻烦了,所以直接把get省略了
    computed: {
      fullName: function{
        return this.firstName.concat(' ').concat(this.lastName)
      }
    }
    
    <!-- 示例4:自己实现set函数
    // 可以自己实现set方法,实现了set方法就不是只读属性了;
    // 备注:自己实现的set方法,set方法是有一个参数的,fullName被赋值时的值就是set的参数
    -->
    
    <div id="app">{{ fullName }}</div>
    <script>
      var vm = new Vue({
        el: "#app",
        data: {
          firstName: 'Nice',
          lastName: 'alice',
        },
        computed: {
          fullName: {
            // 当执行 vm.fullName = 'hello bob'时,就会默认调用set函数,newValue就等于'hello bob'
            set(newValue) {
              var names = newValue.split(' ')
              this.firstName = names[0];
              this.lastName = names[1];
            },
            get() {
              return this.firstName.concat(' ').concat(this.lastName)
            }
          }
        }
      });
    </script>
    

    3. 计算属性缓存问题

    • 计算属性的值fullName会被缓存,它只会监听get中使用的data数据项里面的属性(比如data的flag没有被计算属性使用,所以flag的变化不会导致重新计算),如果有变化,则会重新更新计算属性
    • 由于计算属性的值会被缓存,所以多次访问计算属性值只会调用一次get函数;所以计算属性比methods性能更好一点
    <body>
        <div id="app">
            <h1>{{this.firstName + ' ' + this.lastName}}</h1>
            <div>
                methods方法调用次数:3次
                <h1>{{getFullName()}}</h1>
                <h1>{{getFullName()}}</h1>
                <h1>{{getFullName()}}</h1>
            </div>
            <div>
                computed属性调用次数:1次
                <h1>{{fullName}}</h1>
                <h1>{{fullName}}</h1>
                <h1>{{fullName}}</h1>
            </div>
    
        </div>
        <script>
            var vm = new Vue({
                el: "#app",
                data: {
                    firstName: 'Nice',
                    lastName: 'alice',
                    flag: '111',
                },
                computed: {
                    fullName: vm => {
                        console.log('fullName');
                        return vm.firstName.concat(' ').concat(vm.lastName)
                    }
                },
                methods: {
                    getFullName() {
                        console.log('getFullName');
                        return this.firstName.concat(' ').concat(this.lastName)
                    }
                }
            });
        </script>
    </body>
    
    • computed和methods的区别
      • computed计算属性值可以缓存,性能更好。(如果方法中有循环,那么使用方法则会每调用一次方法都会进行for循环)
      • computed计算属性本质是一个属性,不是方法;methods定义的时方法
      • computed除了可以使用基本函数的this访问data之外,还提供箭头函数接受参数vm实例的方式访问data数据;methods中的方法不能使用箭头函数的形式
    • 场景选择:将data的数据做一些变化重新展示的情况建议选择computed, 方法和computed都适用的情况下优先选择com

    4. 场景

    场景1:计算属性没有监听data中的数据,而是直接返回了123,这种情况不会报错,但是当我们在控制台修改vm.lastName值时,也就是改变dta中的值,计算属性fullname也感知不到,所以这种写法没有任何意义。

    // 场景1:
    <div id="app">
      {{ fullName }}
    </div>
    <script>
      var vm = new Vue({
        el: '#app',
        data: {
          firstName: 'Nice',
          lastName: 'alice'
        },
        computed: {
          fullName() {
            return 123
          }
        }
      })
    </script>
    

    场景2:在控制台修改temp变量的值为'hello',此时页面渲染fullName的值不会变化,还是初始的'xxx';但如果fullName中监听的是data中的属性值,那么在控制台中通过vm修改data中的值,此时页面会重新渲染fullName,因为data中的值是响应式的。

    // 场景2:
    <div id="app">
      <!-- 在控制台修改temp的值,不会触发这里的重新渲染;这里一直保持temp的初始值xxx;因为temp不是响应式属性 -->
      {{ fullName }}
    </div>
    <script>
      var temp = 'xxx'
      var vm = new Vue({
        el: '#app',
        data: {
          firstName: 'Nice',
          lastName: 'alice'
        },
        computed: {
          fullName() {
            return temp;
          }
        }
      })
    </script>
    

    watch

    简介:虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

    注意点:不应该使用箭头函数来定义 watcher 函数

    watch中的几个常见属性:

    1. handler: 定义监听到键名发生变化后执行的回调
    
    2. immediate:因为默认是监听到数据改变时,才会执行handler回调;如果我们想一开始就让他的变化回调handler执行,就需要使用`immediate: true`
    
    3. deep:可以深度监听整个键名内部的所有属性
    

    1. 基本使用

    • 被监听的data中的键名对应键值类型String | Function | Object | Array
    <!-- 基本使用示例1: -->
    <body>
        <div id="app">
            <input v-model="count" />
        </div>
        <script>
            new Vue({
                el: '#app',
                data: {
                    count: 10,
                },
                watch: {
                  	// watch中实时监听的是 data中的 count键名,count键对应的键值是一个回调函数
                  	// 回调函数接受两个参数,newVal是count变化后的值,oldValue是count变成newValue的前一个值
                    count: function (newVal, oldVal) {
                        console.log(`new: %s, old: %s`, newVal, oldVal);
                    }
                }
            })
        </script>
    </body>
    
    <!-- 基本使用示例2:监听到变化之后可以操作 -->
    <div>
          <p>FullName: {{fullName}}</p>
          <p>FirstName: <input type="text" v-model="firstName"></p>
    </div>
    <script>
          new Vue({
            el: '#root',
            data: {
              firstName: 'Dawei',
              lastName: 'Lou',
              fullName: ''
            },
            watch: {
              firstName(newName, oldName) {
                // 监听到firstName变化,操作之后赋值给fullName
                this.fullName = newName + ' ' + this.lastName;
              }
            } 
          })
    </script>
    

    2. watch属性使用

    // 示例2:监听data中的键名所对应的键值的各种类型
    var vm = new Vue({
      data: {
        a: 1,
        b: 2,
        c: {
          	title:'my-blog',
            categories:[]
        },
        d: 4,
        e: {
          f: {
            g: 5
          }
        }
      },
      watch: {
        
        a: function (newVal, oldVal) {
            console.log(`new: %s, old: %s`, newVal, oldVal);
        },
        // 可以是方法名
        b: 'someMethod',
        
        c: function (newVal, oldVal) {
            console.log("如果c对象中的某个属性发生了变化,我们这种直接监听c对象是监听不到变化的,因为c对象的指向并没有发生改变");
        },
        
        // 下面监听方式的缺点是,只要修改c对象中的任何一个属性(无论嵌套多深的属性),都会执行handler;这样会造成更多的性能开销
        c: {
          handler: function (val, oldVal) { /* ... */ },
          deep: true
        },
        
        // 只监听某个对象的特定属性,'c.title' 字符串写法;这种方式的优点弥补了深度监听整个对象而造成了更多的性能开销
        'c.title': function(newVal, oldVal){
          
        }
        
        // 因为默认是监听到数据改变时,才会执行handler回调;如果想一开始就让他的变化回调handler执行,就需要使用`immediate: true`
        d: {
          handler: 'someMethod',
          immediate: true
        },
        
        // 你可以传入回调数组,当e发生变化时,这一组回调函数它们会被逐一调用;感觉有点像观察者模式
        e: [
          'handle1',
          function handle2 (val, oldVal) { /* ... */ },
          {
            handler: function handle3 (val, oldVal) { /* ... */ },
            /* ... */
          }
        ],
      }
    })
    vm.a = 2 // => new: 2, old: 1
    

    3. watch中的异步操作

    可以在watch中执行复杂的异步操作等;这些是computed不能胜任的。具体可以参考官网的案例

    4. vm.$watch实例方法

    注意:在变更 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变更之前值的副本

    语法vm.$watch( expOrFn, callback, [options] )

    • expOrFn:{String | Function},可以是监听的字符串键名,或者监听函数(就像监听一个未被定义的计算属性)

    • callback: {Function | Object} 监听的键名发生变化后的回调

    • options: { handler | immediate | deep)

    // 示例1:
    // 键路径
    vm.$watch('a.b.c', function (newVal, oldVal) {
     // 做点什么
    })
    
    
    // 示例2:
    // 函数
    vm.$watch(
     function () {
       // 表达式 `this.a + this.b` 每次得出一个不同的结果时
       // 处理函数都会被调用。
       // 这就像监听一个未被定义的计算属性
       return this.a + this.b
     },
     function (newVal, oldVal) {
       // 做点什么
     }
    )
    

    5. watch注销

    vm.$watch: 返回一个取消观察函数,用来停止触发回调

    注意:组件选项中的watch中可以随着组件的销毁而销毁,而实例方法的vm.$watch(),我们需要手动销毁

    var unwatch = vm.$watch('a', callback);
    // 停止触发回调
    unwatch()
    

    起源地下载网 » vue学习笔记之computed&watch

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元