一、Vue的生命周期
这里可以比作人的一生需要经历:出生=>小孩=>成人=>结婚=>衰老=>病死
而Vue生命周期亦是如此。
一个组件从创建一直到销毁。这整个过程就叫做生命周期 ,在这个过程中,他经历了从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程。
下面是一张官网的图:
这里做了解释:
这个图看着有点绕,让我们直接看代码了解一下生命周期
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue的生命周期</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <h2>{{message}}</h2> <button type="button" @click="handlerUpdate">更新</button> </div> <script type="text/javascript"> const vm = new Vue({ el: '#app', data() { return { message:'123456789' } }, methods: { handlerUpdate() { this.message = this.message.split('').reverse().join('-') } }, beforeCreate() { // console.log(this.$el); console.log('执行了beforeCreate'); console.log('——————'); }, created() { // console.log(this.$el); console.log('执行了Create'); console.log('——————'); }, beforeMount() { // console.log(this.$el); console.log('执行了beforeMount'); console.log('——————'); }, mounted() { // console.log(this.$el); console.log('执行了mounted'); console.log('——————'); }, beforeUpdate() { console.log('执行了beforeUpdate'); }, updated() { console.log('执行了updated'); }, beforeDestroy() { console.log('执行了beforeDestroy'); }, destroyed() { console.log('执行了destroyed'); }, }) </script> </body> </html>
这里记住八个方法:
beforeCreate(创建前)
created(创建后)
beforeMount(载入前)
mounted(载入后)
beforeUpdate(更新前)
updated(更新后)
beforeDestroy(销毁前)
destroyed(销毁后)
1、初始化页面调用的方法
效果如下图:
2、更新过后数据调用生命周期的方法
打印效果如下图:
3、销毁过后生命周期出现的方法:
打开控制台直接输入 vm.$destroy()就会销毁这个组件并且执行beforeDestroy和destroyed销毁前和销毁后的方法并返回undefined,这时再去修改其值已经不起作用了
二、el对生命周期的影响:
加el时:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <h2>{{message}}</h2> <button type="button" @click="handlerUpdate">更新</button> </div> <script type="text/javascript"> const vm = new Vue({ el: '#app', data() { return { message:'123456789' } }, methods: { handlerUpdate() { this.message = this.message.split('').reverse().join('-') } }, beforeCreate() { console.log(this.$el); console.log('执行了beforeCreate'); console.log('——————'); }, created() { console.log(this.$el); console.log('执行了Create'); console.log('——————'); }, beforeMount() { console.log(this.$el); console.log('执行了beforeMount'); console.log('——————'); }, mounted() { console.log(this.$el); console.log('执行了mounted'); console.log('——————'); }, beforeUpdate() { console.log('执行了beforeUpdate'); }, updated() { console.log('执行了updated'); }, beforeDestroy() { console.log('执行了beforeDestroy'); }, destroyed() { console.log('执行了destroyed'); }, }) </script> </body> </html>
没有el时:
// el: '#app'
效果如下:
由此证明了没有el选项,则停止编译,也意味着暂时停止了生命周期。生命周期到created钩子函数就结束了。
能够使暂停的生命周期进行下去可以使用vm.$mount(el)方法
Vue 的$mount()为手动挂载,在项目中可用于延时挂载(例如在挂载之前要进行一些其他操作、判断等),之后要手动挂载上。new Vue时,el和$mount并没有本质上的不同。
在代码末尾添加vm.$mount('#app')效果如下:
直接在控制台输入vm.$mount('#app')效果如下:
三、template与html之间的优先级
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>测试html与template的优先级</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <h3>测试html与template的优先级</h3> <div id="app"> <p>是html优先?</p> </div> <script type="text/javascript"> const vm = new Vue({ el:'#app', data(){ return{ message:'是template优先?' } }, template: `<p>{{message}}<p>` , }) </script> </body> </html>
效果如下:
template参数选项的优先级要比外部的HTML高
绑定不加冒号与加冒号的区别:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>绑定加不加冒号</title> </head> <body> <div id="app"> <cpn message="content"></cpn> <!-- 不加冒号会被Vue识别为字符串 --> <cpn :message="content"></cpn> <!-- 加冒号会进行数据绑定 --> </div> <template id="cpn"> <div> <h2>{{msg}}</h2> <h2>{{message}}</h2> </div> </template> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> <script> const cpn = { template: '#cpn', data() { return { msg: '我是子组件数据' } }, props: { message: { type: String } } } const app = new Vue({ el: "#app", data() { return { content: '我是父组件数据' } }, components: { cpn } }) </script> </body> </html>
不加冒号的效果:
加冒号的效果如下:
四、总线机制(bus):
非父子组件之间通信可以用bus和vuex
bus比较适合小项目,而vuex适合中、大型项目
这里实现一个兄弟之间的通信,看例子:
第一种写法:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>bus</title> <script src="https://cdn.jsdelivr.net/npm/vue"></script> </head> <body> <div id="app"> <child content='Nan'></child> <child content="Chen"></child> </div> <script type="text/javascript"> // 这里需要使用Vue的原型 // 添加一个变量到 Vue.prototype // 变量前面最好以$开头,避免数据、方法、计算属性等发生冲突 Vue.prototype.$bus =new Vue(); Vue.component('child',{ template: `<div @click="handelClick">{{message}}</div>`, data(){ return{ message:this.content } }, props:{ content:[String] }, methods:{ handelClick(){ // 很像父子之间传值的方法 this.$bus.$emit('change',this.message) } }, // 挂载后执行 mounted(){ var that = this // $on 用来监听$emit所派发的事件 this.$bus.$on('change',function(msg){ // 将获取到的msg值传给message console.log(msg); console.log(that); that.message = msg }) } }) const vm = new Vue({ el:'#app', }) </script> </body> </html>
实现效果:
这样就实现了简单的兄弟之间的通讯 下面来说一下$emit与$on之间的关系
$emit与$on之间的关系:
详细解析可以参考vue中的$on,$emit,v-on 三者关系_oiery的博客-CSDN博客
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
如果把Vue看成一个家庭(相当于一个单独的components),女主人一直在家里指派($emit)男人做事,而男人则一直监听($on)着女士的指派($emit)里eventName所触发的事件消息,一旦 $emit 事件一触发,$on 则监听到 $emit 所派发的事件,派发出的命令和执行派执命令所要做的事都是一一对应的。
第二种写法:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>第二种写法</title> </head> <body> <div id="app"> <cpn content="Nan"></cpn> <cpn content="Chen"></cpn> </div> <template id="cpn"> <div @click="handelClick">{{message}}</div> </template> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> <script> Vue.prototype.$bus = new Vue() const cpn = { template:'#cpn', data(){ return { message:this.content } }, props:{ content:{ type:String } }, methods:{ handelClick(){ this.$bus.$emit('change',this.message) } }, mounted(){ var that = this this.$bus.$on('change',function(msg){ console.log(msg); that.message = msg }) } } const app = new Vue({ el: "#app", components:{ cpn } }) </script> </body> </html>
效果如下: