# 生命周期

has template option,当为no时,会读取嵌套在div指定根节点里的内容。

总结

  • beforecreated:el 和 data 并未初始化
  • created:完成了 data 数据的初始化,el没有【完成了属性和方法的运算,watch、event事件的回调配置】
  • beforeMount:完成了 el 和 data 初始化
  • mounted :完成挂载

  • beforeCreate(){} // 执行时组件实例还未创建,通常用于插件开发中执行一些初始化任务,举个栗子:可以在这加个loading事件
  • created(){} // 组件初始化完毕,各种数据可以使用,常用于异步数据获取
  • beforeMount(){} // 未执行渲染、更新,dom未创建
  • mounted(){} // 初始化结束,dom已创建,可用于获取访问数据和dom元素
  • beforeUpdate(){} // 更新前,可用于获取更新前各种状态
  • updated(){} // 更新后,所有状态已是最新
  • beforeDestroy(){} // 销毁前,可用于一些定时器或订阅的取消
  • destroyed(){} // 组件已销毁,作用同上
beforeCreate  组件实例刚被创建,组件属性计算之前,获取不到 props 或者 data 中的数据的。
			  这些数据的初始化都在 initState 中。data和methods中的数据都没初始化

created  组件实例创建完成,data和methods中的数据都被初始化好了,属性已绑定,
		但DOM还未生成,$el属性还不存在

beforeMount:模板编译/挂载前 开始创建VDOM,最后执行mounted 钩子,并将VDOM渲染为真实DOM且渲染数据。
		组件中如果有子组件的话,会递归挂载子组件,当所有子组件全部挂载完毕,才会执行根组件的挂载钩子.
<div id=“app”>{{msg}} </div>->在内存中生成一个编译好的最终模板字符串->把这个模板字符串渲染为内存中dom

注意:只是在内存中渲染好了模板,并没有把模板挂载到页面上去,此时 页面还是旧的,
就是在内存中渲染了一个 <div id=“app”>ok</div> 的dom元素,但页面上还是 <div id=“app”>{{msg}} </div>

mounted     模板编译/挂载之后 
将内存中渲染好的dom元素即 < div id=“app”>ok< /div>已经 提换了页面上的 < div id=“app”>{{msg}} < /div>

activated   for keep-alive,组件被激活时调用

deactivated for keep-alive,组件被移除时调用
beforeCreate(){
    console.log('beforecreate:',document.getElementById('first'))//null
    console.log('data:',this.text);//undefined
    this.sayHello();//error:not a function
},
created(){
    console.log('create:',document.getElementById('first'))//null
    console.log('data:',this.text);//this.text
    this.sayHello();//this.sayHello()
},
beforeMount(){
    console.log('beforeMount:',document.getElementById('first'))//null
    console.log('data:',this.text);//this.text
    this.sayHello();//this.sayHello()
},
mounted(){
    console.log('mounted:',document.getElementById('first'))//<p></p>
    console.log('data:',this.text);//this.text
    this.sayHello();//this.sayHello()
}
生命周期 是否获取dom节点 是否可以获取data 是否获取methods
beforeCreate
created
beforeMount
mounted

created和mounted (opens new window)

TIP

一、加载渲染过程 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

二、子组件更新过程 父beforeUpdate->子beforeUpdate->子updated->父updated

三、父组件更新过程 父beforeUpdate->父updated

四、销毁过程 父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

# watch监听

# computed 计算属性

fullName作为计算属性,那么data里就不该再定义了!

<p id="app">  {{fullName}}  </p>

<script>
    var vm = new Vue({  
        el: '#app',  
        data: {  
            firstName: 'Foo',  
            lastName: 'Bar',  
        },  
        computed: {  
            fullName: function () {  
                return this.firstName + ' ' + this.lastName  
            }  
        }  
    })
</script>

计算属性默认只有getter,可以在需要的时候自己设定setter, 计算属性需要改成对象形式

// ...
    computed: {
        fullName: {
            // getter
            get: function () {
                return this.firstName + ' ' + this.lastName
            },
            // setter
            set: function (newValue) {
                var names = newValue.split(' ')
                this.firstName = names[0]
                this.lastName = names[names.length - 1]
            }
        }
    }
//这个时候在控制台直接运行vm.fullName = ‘bibi wang’,相应的firstName和lastName也会改变。

computed与vuex数据的结合运用

# filter

过滤器

# methods

vue所有事件方法的集合

  methods:{
    //   清除被选中的颜色
      removecolor(){       
      }  
 },
  • 这是因为计算属性会基于它们的依赖关系进行 缓存
  • 在数据不发生变化时,计算属性是不需要重新计算的;
  • 但是如果依赖的数据发生变化,在使用时,计算属性依然会重新进行计算;

# data写成函数的原因

组件中 data 什么时候可以使用对象?

组件复用时所有组件实例都会共享 data,如果 data 是对象的话,就会造成一个组件修改 data 以后会影响到其他所有组件,所以需要将 data 写成函数,每次用到就调用一次函数获得新的数据。

当使用 new Vue() 的方式的时候,无论我们将 data 设置为对象还是函数都是可以的,因为 new Vue() 的方式是生成一个根组件,该组件不会复用,也就不存在共享 data 的情况了。

// 当data如果是对象时就直接获取,那么如果复用组件的话,数据就会污染
function initData (vm: Component) {
  let data = vm.$options.data
  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {}
  if (!isPlainObject(data)) {
    data = {}
    process.env.NODE_ENV !== 'production' && warn(
      'data functions should return an object:\n' +
      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
      vm
    )
  }
strats.data = function (
  parentVal: any,
  childVal: any,
  vm?: Component
): ?Function {
  if (!vm) {
    if (childVal && typeof childVal !== 'function') {
      process.env.NODE_ENV !== 'production' && warn(
        'The "data" option should be a function ' +
        'that returns a per-instance value in component ' +
        'definitions.',
        vm
      )

      return parentVal
    }
    return mergeDataOrFn(parentVal, childVal)
  }
    return mergeDataOrFn(parentVal, childVal, vm)
}
类别引用数据类型

Object是引用数据类型,如果不用function返回,每个组件的data都是内存的同一个地址,一个数据改变了其他也改变了;????(是复用组件还是所有组件)

JS只有函数构成作用域(注意理解作用域,只有函数{}构成作用域,对象的{}以及if(){}都不构成作用域),data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响。

这里模仿组件构造函数,定义data属性,采用对象的形式:

function Component(){
 
}
Component.prototype.data = {
	count : 0
}
const componentA = new Component()
const componentB = new Component()
console.log(componentB.data.count)  // 0
componentA.data.count = 1
console.log(componentB.data.count)  // 1

如果是函数则不会相互干扰:

function Component(){
	this.data = this.data()
}
Component.prototype.data = function (){
    return {
   		count : 0
    }
}
console.log(componentB.data.count)  // 0
componentA.data.count = 1
console.log(componentB.data.count)  // 0

当然根节点还是可以使用对象的方法:

new Vue({
  data:{
    ss:1111
  },
  mounted(){
    console.log(this.ss)
  },
  router,
  store,
  render: h => h(App)
}).$mount('#app')

注意

注意,不应该使用箭头函数来定义 method 函数 (例如 plus: () => this.a++)。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.a 将是 undefined。

最后更新: 4/21/2024, 8:03:54 AM