zoukankan      html  css  js  c++  java
  • Vue.js 生命周期、计算属性及侦听器

    一、创建一个Vue实例

    每个Vue应用都是使用Vue函数创建一个Vue实例。所有的Vue组件都是一个Vue实例,并且接受相同的选项对象(一些根实例特有的选项除外)。

    数据和方法

    当一个实例被创建后,它向Vue的响应式系统加入了其data对象中能找到的所有属性。当这些属性的值改变的时候,视图也会跟着响应。

    注意:

    1.值得注意的是,只有当Vue实例被创建的时候的data对象中的存在的属性才是响应式的。
    2.如果你知道你会在晚些时候需要一个属性,但是一开始它为空或者不存在,那么你仅需要设置一些初始值。
    3.这里唯一的例外是使用object.freeze(),这会阻止修改现有的属性。
    4.当然除了数据属性,Vue实例还暴露出了一些实例属性和方法,它们都有前缀$,这样便于和用户自定义的属性区分开来。

    二、实例生命周期钩子

    每个Vue实例在被创建时都要经过一系列的初始化过程,例如,需要设置数据监听,编译模板,将实例挂载到DOM并且在数据变化时更新DOM。同时在这个
    过程中会运行一些叫生命周期钩子的函数。生命周期钩子的this上下文指向调用它的实例

    • 初始化事件和生命周期
    • beforeCreate: 这时候访问不到数据和真实DOM
    • beforeCreate和created之间的时间,挂载数据和绑定事件
    • created:用于在一个实例被创建之后执行的代码。倒数第二次机会更改数据,更改数据之后不会触发updated钩子函数
      created和beforeMount之间,会寻找实例或组件是否有模板(template),编译模板为虚拟DOM放到render函数中渲染。
    • beforeMount:这是倒数第一次机会更改数据。更改数据之后不会触发updated钩子函数
    • mounted: 这时候可以访问到真实的DOM
    • beforeUpdate:当实例或组件的数据变化的时候,这时候会立即调用beforeUpdate钩子函数,然后Vue的虚拟DOM机制会重新创建dom树,和之前的dom树进行比较,利用diff算法
    • updated:
    • beforeDestroy:在这里可以清除定时器,清除事件绑定
    • destroyed:在这里也可以做类似清除定时器的事情
      所有生命周期方法被调用的时候,this都指向所在的Vue实例。

    实际的生命周期方法调用次序:
    1.new Vue();
    2.在进行create之前,需要调用beforeCreate生命周期钩子;
    3.然后挂载数据,绑定事件;
    4.然后调用created生命周期方法;
    5.判断是否有el的选项,如果有,再判断其是否有template选项;如果没有的话,就在vm.$mount(el)被called的时候,再去判断其是否有template的选项。
    6.这时候判断有无template选项,如果有的话,就看他将template模板变成render function,
    7.在mount之前,还要调用beforeMount,执行完beforeMount之后,就将el渲染成vm.$el。然后调用mounted。
    8.渲染完之后,如果数据有变化的话,就需要重新渲染,然后就调用beforeUpdate,虚拟DOM重新渲染并更新。更新完之后调用updated;
    9.如果页面即将被销毁的时候,先调用beforeDestroy,然后等销毁完之后,就调用destroyed。

    三、计算属性和侦听器

    1.计算属性

    var vm = new Vue({
    	el: '#example',
    	data:{
    		message: 'hello'
    	},
    	computed:{
                    //reverseMessage是计算属性,因为其依赖了message数据属性,当message变化的时候,reverseMessage也跟着改变
    		reverseMessage: function(){
    			return this.message.split("").reverse().join("");
    		},   
                    //now也是计算属性,但是它并不是响应式依赖,计算属性是基于它们的依赖来缓存
    		now: function(){
    			return Date.now();
    		}
    	}
    	methods:{
    	 	reverseMessage:function(){
    	 		return this.message.split("").reverse().join("");
    		}
    	}
    })
    

    计算属性缓存vs方法
    (1)计算属性是基于响应式依赖进行缓存的。一个计算属性B依赖于某个属性A,如果这个属性A是依赖于遍历一个比较大的数组进行缓存的。这时候使用计算属性可以降低遍历大数组的开销。
    如果使用方法的话,则这个计算属性B则每次根据A进行计算,而每次A要根据大数组来计算,这时候就会每次获取属性B,都会遍历一次大数组。
    2.侦听属性

    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
        }
      }
    })
    

    看起来计算属性要比侦听属性好用得多,侦听属性看起来滥用watch。

    3.计算属性的setter
    计算属性默认只有getter,不过在需要的时候,也提供一个setter。

    computed:{
    		reverseMessage: function(){
    			return this.message.split("").reverse().join("");
    		},
    		now: function(){
    			return Date.now();
    		},
    		fullName:{
    			get: function(){
    				return this.firstName + this.lastName;
    			},
    			set:function(newValue){
    				var names = newValue.split(" ");
    				this.firstName = names[0];
    				this.lastName = names[names.length - 1] 
    			}
    		}
    	}
    

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

    四、class与style绑定

    在将v-bind用于class和style的时候,表达式结果的类型除了字符串,因为字符串拼接比较繁琐,Vue对其进行增强,还可以是对象和数组。

    1、对象语法

    data: {
        isActive: true,
        hasError: false
    }
    
    // 单个属性
    <div class="color" v-bind:class="{active: isActive}" >fff</div>
    <div class="color active"></div>
    
    // 多个属性
    <div v-bind:class="{active: isActive,'text-danger': hasError}"></div>
    <div class="active"></div>
    
    // 直接通过classObj计算属性来
    <div v-bind:class="classObj"></div>
    <div class="active"></div>
    {
        data: {
            isActive: true,
            hasError: false
        },
        computed: {
            classObj:  function() {
                return {
                    active: isActive && !hasError,
                    text-danger: hasError
                }
            }
        }
    }
    

    2、数组

    // 单纯使用数组中的值
    <div v-bind:class="[activeClass,dangerClass]"></div>
    <div class="active text-danger"></div>
    data:{
        activeClass: 'active',
        dangerClass: 'text-danger',
    }
    
    // 数组中运用三元表达式
    <div v-bind:class="[isActive?activeClass : '', dangerClass]"></div>
    <div class="active text-danger"></div>
    data:{
        isActive: true,
        activeClass: 'active',
        dangerClass: 'text-danger'
    }
    
    // 数组中也可以使用对象
    <div v-bind:class="[{active: isActive}, dangerClass]"></div>
    <div class="active text-danger"></div>
    data:{
        isActive: true,
        dangerClass: 'text-danger'
    }
    
  • 相关阅读:
    数据结构总结(UPDATING......)
    课件例题4.11,4.12
    Luogu P1525 关押罪犯
    Luogu P1540 机器翻译
    Luogu P1313 计算系数
    Luogu P1311 选择客栈
    Luogu P1519 穿越栅栏 Overfencing
    Luogu P2863 [USACO06JAN]牛的舞会The Cow Prom
    Tarjan学习笔记
    Luogu P3393 逃离僵尸岛
  • 原文地址:https://www.cnblogs.com/sminocence/p/9872138.html
Copyright © 2011-2022 走看看