生命周期的基本概念
我们一起回顾一下上节课讲到的,过渡的几个钩子函数:
<body>
<div id='app'>
<button @click='show=!show'>btn</button>
<transition :css=false @before-enter='fn1' @enter='fn2' @after-enter='fn3'>
<h1 v-if='show'>嘿嘿嘿</h1>
</transition>
</div>
<script src='./js/vue.js'></script>
<script>
const app = new Vue({
el: '#app',
data: {
show: false
},
methods: {
fn1(el) {
el.style.color = 'red'
},
fn2(el, done) {
const id = setInterval(() => {
if (el.style.color === 'red') {
el.style.color = 'green'
} else {
el.style.color = 'red'
}
}, 1000);
setTimeout(() => {
clearInterval(id)
done()
}, 3000);
},
fn3() {
alert(666)
}
}
})
</script>
</body>
以上的3个过渡的钩子函数,就是在我们的动画这个周期内,在每个时间段,我们都可以去设置不同的代码去完成相对应的事,比如在动画开始之前我们需要什么操作,在动画执行过程中我们需要什么操作,动画执行完后我们需要什么操作,都可以写在函数里面去完成
vue的生命周期也是同样的道理,每个 Vue 实例在被创建时都要经过一系列的初始化过程
例如,需要设置数据监听、编译模板、将实例挂载到DOM 并在数据变化时更新DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如created钩子可以用来在一个实例被创建之后执行的代码:
<script>
const app = new Vue({
el: '#app',
data: {
msg: '哈哈哈'
},
created: function () {
console.log(this.msg);
}
})
</script>
生命周期的基本概念
vue的方法和混入/自定义指令
vue的全局方法
Vue.extend( options )
使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数.
const Profile = Vue.extend({
template: '<h1>{{name}}->{{num}}</h1>',
data() {
return {
name: 'kobe',
num: 8
}
}
})
vue的全局方法之nextTick
Vue.nextTick( [callback, context] )
在下次DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。
const app = new Vue({
el: '#app',
data: {
msg: '123'
}
})
console.log(app.msg);
app.msg = 'new msg' //更改数据
console.log(document.getElementById('app').innerText); //dom还没有更新
Vue.nextTick(function () {
console.log(document.getElementById('app').innerText); //dom已经更新
})
vue的实例方法之nextTick
app.$nextTick( [callback] )
将回调延迟到下次DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待DOM 更新。它跟全局方法Vue.nextTick 一样,不同的是回调的this 自动绑定到调用它的实例上。
const app = new Vue({
el: '#app',
data: {
msg: '你好,世界'
},
methods: {
fn() {
this.msg = 'hello world'
console.log(document.getElementById('demo').innerText); //dom还没有更新
this.$nextTick(function () {
console.log(document.getElementById('demo').innerText); //dom已经更新
})
}
}
})
vue的实例方法之destroy
vm.$destroy()
完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器。触发beforeDestroy和destroyed的钩子。
vue的混入
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项( 比如可以单独把数据或是方法什么的单独变成一个混合对象 )。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
<script>
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn1: {
template: '<div><h1 v-if="show">cpn1</h1><button @click="fn">cpn1</button></div>',
data() {
return { show: true }
},
methods: {
fn() {
this.show = !this.show
}
}
},
cpn2: {
template: '<div><h1 v-if="show">cpn2</h1><button @click="fn">cpn2</button></div>',
data() {
return { show: true }
},
methods: {
fn() {
this.show = !this.show
}
}
}
}
})
</script>
上面的案例罗级很简单,我们定义了两个组件cpn1和cpn2,用show的布尔值去控制h1标签内容的显示,我们发现cpn1和cpn2这两个组件中的data和methods中的内容时一样的,此时我们可以用mixins将这些相同的内容提取出来再分发到每个组件中.
<script>
const mixData = {
data() {
return { show: true }
},
methods: {
fn() {
this.show = !this.show
}
}
}
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn1: {
mixins: [mixData],
template: '<div><h1 v-if="show">cpn1</h1><button @click="fn">cpn1</button></div>',
},
cpn2: {
mixins: [mixData],
template: '<div><h1 v-if="show">cpn2</h1><button @click="fn">cpn2</button></div>',
}
}
})
</script>
vue混入的数据选项合并
当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。
比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
<script>
const mixData = {
data() {
return {
show: true,
name: 'kobe'
}
},
methods: {
fn() {
this.show = !this.show
}
}
}
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn1: {
mixins: [mixData],
template: '<div><h1 v-if="show">cpn1{{show}}</h1><button @click="fn">cpn1</button></div>',
data() {
return {
show: 'test',
num: 8
}
},
},
cpn2: {
mixins: [mixData],
template: '<div><h1 v-if="show">cpn2</h1><button @click="fn">cpn2</button></div>',
}
}
})
</script>
vue混入的钩子函数选项合并
同名钩子函数将合并为一个数组( 数组的每一项都是一个函数, 当钩子被触发之后, 数组里面的每个函数都会执行依次的 ),因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
<script>
const mixData = {
data() {
return {
show: true,
name: 'kobe'
}
},
methods: {
fn() {
this.show = !this.show
}
},
created() {
console.log('混入对象的钩子被调用');
}
}
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn1: {
mixins: [mixData],
template: '<div><h1 v-if="show">cpn1{{show}}</h1><button @click="fn">cpn1</button></div>',
data() {
return {
show: 'test',
num: 8
}
},
created() {
console.log('组件钩子被调用');
}
}
}
})
</script>
相当于:
created: [function () { console.log('混入对象的钩子被调用') }, function () { console.log('组件钩子被调用') }]
vue混入的对象选项合并
值为对象的选项,例如methods、components和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。
<script>
const mixData = {
data() {
return {
msg: '嘿嘿嘿'
}
},
methods: {
fn() {
console.log('from mixins');
},
fn1() {
console.log('from mixins1');
}
}
}
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn: {
mixins: [mixData],
template: '<div><h1>{{msg}}</h1><button @click="fn">btn</button><button @click="fn1">btn1</button></div>',
methods: {
fn() {
console.log('from cpn');
}
}
}
}
})
</script>
vue的全局混入
混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的Vue 实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。
Vue.mixin( options )
<body>
<div id='app'>
<cpn></cpn>
</div>
<div id="vm">
<cpn></cpn>
</div>
<script src='./js/vue.js'></script>
<script>
Vue.mixin({
methods: {
fn() {
console.log('我是全局mixins');
}
}
})
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn: {
template: '<div><button @click="fn">btn_app</button></div>'
}
}
})
const vm = new Vue({
el: '#vm',
data: {
},
components: {
cpn: {
template: '<div><button @click="fn">btn_vm</button></div>'
}
}
})
</script>
</body>
使用全局方法设置的混合, 会在之后的每一个Vue实例中进行混合,就如同是直接修改了Object.prototype一样
请谨慎使用全局混入,因为它会影响每个单独创建的Vue 实例 (包括第三方组件)。