目录
1.4.1了解beforeCreate和created生命周期函数的特点
1.4.2了解beforeMount和mounted生命周期函数
1、组件生命周期
1.1 生命周期 & 生命周期函数
- 生命周期(Life Cycle)是指一个组件从创建 -> 运行 -> 销毁的整个阶段,强调的是一个时间段。
- 生命周期函数:是由 vue 框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行。
注意:
生命周期
强调的是
时间段
,
生命周期函数
强调的是
时间点
。
1.2组件生命周期函数的分类
1.3生命周期图示
可以参考
vue
官方文档给出的“生命周期图示”,进一步理解组件生命周期执行的过程:
https://cn.vuejs.org/v2/guide/instance.html#
生命周期图示:
1.4生命周期函数特点
<template>
<div class="test-container">
<h3 id="myh3">Test.vue 组件 --- {{ books.length }} 本图书</h3>
<p id="pppp">message 的值是:{{ message }}</p>
<button @click="message += '~'">修改 message 的值</button>
</div>
</template>
<script>
export default {
props: ['info'],
data() {
return {
message: 'hello vue.js',
// 定义 books 数组,存储的是所有图书的列表数据。默认为空数组!
books: []
}
},
watch: {
message(newVal) {
console.log('监视到了 message 的变化:' + newVal)
}
},
methods: {
show() {
console.log('调用了 Test 组件的 show 方法!')
},
// 使用 Ajax 请求图书列表的数据
initBookList() {
const xhr = new XMLHttpRequest()
xhr.addEventListener('load', () => {
const result = JSON.parse(xhr.responseText)
console.log(result)
this.books = result.data
})
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
xhr.send()
}
},
// 创建阶段的第1个生命周期函数
beforeCreate() {
// console.log(this.info)
// console.log(this.message)
// this.show()
},
created() {
// created 生命周期函数,非常常用。
// 经常在它里面,调用 methods 中的方法,请求服务器的数据。
// 并且,把请求到的数据,转存到 data 中,供 template 模板渲染的时候使用!
this.initBookList()
},
beforeMount() {
// console.log('beforeMount')
// const dom = document.querySelector('#myh3')
// console.log(dom)
},
// 如果要操作当前组件的 DOM,最早,只能在 mounted 阶段执行
mounted() {
// console.log(this.$el)
// const dom = document.querySelector('#myh3')
// console.log(dom)
},
beforeUpdate() {
// console.log('beforeUpdate')
// console.log(this.message)
// const dom = document.querySelector('#pppp')
// console.log(dom.innerHTML)
},
// 当数据变化之后,为了能够操作到最新的 DOM 结构,必须把代码写到 updated 生命周期函数中
updated() {
// console.log('updated')
// console.log(this.message)
// const dom = document.querySelector('#pppp')
// console.log(dom.innerHTML)
},
beforeDestroy() {
console.log('beforeDestroy')
this.message = 'aaa'
console.log(this.message)
},
destroyed() {
console.log('destroyed')
// this.message = 'aaa'
}
}
</script>
<style lang="less" scoped>
.test-container {
background-color: pink;
height: 200px;
}
</style>
1.4.1了解beforeCreate和created生命周期函数的特点
1.4.2了解beforeMount和mounted生命周期函数
1.4.3生命周期 - 组件运行阶段的生命周期函数
1.4.4生命周期 - 组件销毁阶段的生命周期函数
2、组件之间的数据共享
App.vue:
<template> <div class="app-container"> <h1>App 根组件--{{countFromSon}}</h1> <p>{{userinfo}}</p> <hr /> <div class="box"> <!-- 渲染 Left 组件和 Right 组件 --> <Left :msg="message" :user="userinfo"></Left> <Right @numchange="getNewCount"></Right> </div> </div> </template> <script> import Left from '@/components/Left.vue' import Right from '@/components/Right.vue' export default { data(){ return{ message:'sjf', userinfo:{name:'sjf',age:'18'}, // 定义countFromSon,来接收子组件传递过来的数据 countFromSon:0 } }, methods:{ getNewCount(val){ this.countFromSon=val console.log('numchange事件被触发了',val) } }, components:{ Left, Right } } </script> <style lang="less"> .app-container { padding: 1px 20px 20px; background-color: #efefef; } .box { display: flex; } </style>
Left.vue:
<template> <div class="left-container"> <h3>Left 组件</h3> <p>msg的值是:{{msg}}</p> <p>userinfo的值是:{{user}}</p> <!-- 不要修改props的值 --> <!-- <button @click="msg='123'">修改messsge</button> --> <button @click="send">把str发送给Right</button> </div> </template> <script> // 1 导入eventBus.js import bus from './eventBus.js' export default { props:['msg','user'], data(){ return{ // 要发送的数据 str:'你的报应就是我' } }, methods:{ send(){ // 2 通过eventBus发送数据 bus.$emit('share',this.str) } } } </script> <style lang="less"> .left-container { padding: 0 20px 20px; background-color: orange; min-height: 250px; flex: 1; } </style>
Right.vue:
<template> <div class="right-container"> <h3>Right 组件--{{count}}</h3> <button @click="add">+1</button> <p>{{msgFromLeft}}</p> </div> </template> <script> // 1 导入eventBus.js import bus from './eventBus.js' export default { data(){ return{ // 子组件自己的数据。将来希望把count值传给父组件 count:0, msgFromLeft:'' } }, methods:{ add(){ this.count+=1; // 通过$emit出发自定义事件numchange this.$emit('numchange',this.count) } }, created(){ // 2 为bus绑定自定义事件 bus.$on('share',(val)=>{ console.log('在Right中定义的share被触发了',val) this.msgFromLeft=val }) } } </script> <style lang="less"> .right-container { padding: 0 20px 20px; background-color: lightskyblue; min-height: 250px; flex: 1; } </style>
eventBus.js:
import Vue from 'vue' // 创建一个Vue实例,并把它向外导出 export default new Vue()
2.1. 组件之间的关系
2.2. 父子组件之间的数据共享
2.2.1 父组件向子组件共享数据
父组件向子组件共享数据需要使用自定义属性。示例代码如下:
2.2.2 子组件向父组件共享数据
子组件向父组件共享数据使用
自定义事件
。示例代码如下:
2.3. 兄弟组件之间的数据共享
3、ref引用
App.vue:
<template> <div class="app-container"> <h1 ref="myh1">App 根组件</h1> <button @click="showThis">打印this</button> <button @click="onReset">重置Left的count</button> <hr /> <input type="text" v-if="inputVisiable" @blur="showButton" ref="iptRef"> <button v-else @click="showInput">展示输入框</button> <div class="box"> <!-- 渲染 Left 组件和 Right 组件 --> <Left ref="comeLeft"></Left> </div> </div> </template> <script> import Left from '@/components/Left.vue' export default { data(){ return{ // 默认值为false,表示展示按钮,隐藏输入框 inputVisiable:false } }, methods:{ // 点击按钮,显示输入框 showInput(){ // 切换布尔值,把文本框展示出来 this.inputVisiable=true // 让展示出来的文本框自动获得焦点 // 为什么this.$emit.iptRef是undefined? // 因为:this.inputVisiable=true执行完之后,数据变成了最新,但是页面还没来得及渲染,页面中还没有文本框 console.log(this.$refs.iptRef) this.$refs.iptRef.focus() // this.$nextTick(()=>{ // this.$refs.iptRef.focus() // }) }, // 输入框失去焦点,显示按钮 showButton(){ this.inputVisiable=false }, showThis(){ // 当前App组件的实例对象 console.log(this) // console.log(this.$refs.myh1) this.$refs.myh1.style.color='red' }, onReset(){ // this.$refs.comeLeft.rsetCount() this.$refs.comeLeft.count=0 } }, components:{ Left } } </script> <style lang="less"> .app-container { padding: 1px 20px 20px; background-color: #efefef; } .box { display: flex; } </style>
Left.vue:
<template> <div class="left-container"> <h3>Left 组件---{{count}}</h3> <button @click="count+=1">+1</button> <button @click="rsetCount">重置</button> </div> </template> <script> export default { data(){ return{ count:0 } }, methods:{ rsetCount(){ this.count=0 } } } </script> <style lang="less"> .left-container { padding: 0 20px 20px; background-color: orange; min-height: 250px; flex: 1; } </style>
3.1 什么是 ref 引用
- jquery简化了程序员操作DOM的过程
- vue优势:MWM 在vue中,程序员不需要操作 DOM。程序员只需要把数据维护好即可! (数据驱动视图)
- 结论:在vue项目,强烈不建议大家安装和使用jQuery! !
- 假设:在vue中,需要操作 DOM了,需要拿到页面上某个 DOM元素的引用,此时怎么办?
3.2 使用 ref 引用 DOM 元素
通过refs获取页面元素的DOM:
3.3使用 ref 引用组件实例
3.4控制文本框和按钮的按需切换
3.4.1代码实现
3.4.2让文本框自动获得焦点
以上代码在执行的时候会出现一个问题:
为什么this.$emit.iptRef是undefined?
因为:this.inputVisiable=true执行完之后,数据变成了最新,但是页面还没来得及渲染,页面中还没有文本框。
解决办法:this.$nextTick(cb) 方法
3.4.3this.$nextTick(cb) 方法
4、购物车案例
4.1复习回顾
4.1.1数组中的方法 - some循环
forEach方法:循环一旦开始,无法在中间被停止
some方法:在找到对应的项之后,可以通过 return true 固定的语法,来终止 some 循环