1、组件的运行过程
声明周期函数:略
2、父子组件中的数据共享
父向子共享数据
子向父共享数据
父子之间双向数据同步
1、父组件向子组件共享数据
父组件通过v-bind属性想子组件共享数据,子组件使用props接收数据
2、子组件向父组件共享数据
自定义事件
触发自定义事件,参见复习1
3、父子组件共享数据
在2的基础上在父组件上使用v-model
3、兄弟组件之间组件中的数据共享
兄弟组件之间实现共享的方案是EventBus,可以借助第三方的包mitt来创建eventBus对象,从而实现兄弟组件之间的数据共享。
注意,vue3里面生命周期发送变化,created声明周期已经没有了
npm install mitt --save
eventbus.js
//导入mitt包
import mitt from 'mitt'
//创建eventBus对象
const bus=mitt()
//导出eventbus对象
export default {
bus
}
Send.vue
<template>
<h3>the sender count is {{count}}</h3>
<button @click="addCount">addCount</button>
</template>
<script>
import bus from '../js/eventBus.js'
export default {
name: 'Send',
data(){
return {
count:0
}
},
methods:{
addCount(){
this.count++
//通过eventBus来发送事件和数据
bus.emit('countChange',this.count)
console.log(bus)
}
},
}
</script>
<style scoped>
</style>
Receiver.vue
<template>
<div>
<h3>the Receive number is {{num}}</h3>
</div>
</template>
<script>
//导入eventBus模块
import bus from '../js/eventBus.js'
export default {
name: 'Receiver',
data(){
return {
num:0
}
},
created () {
//接受到send方传递过来的自定义事件,然后处理回调函数的逻辑
bus.on('countChange',(count)=>{
//将接受到的事件所带来的参数进行处理
this.num=count
})
},
methods:{
}
}
</script>
<style scoped>
</style>
Receiver.vue
<template>
<div>
<h3>the Receive number is {{num}}</h3>
</div>
</template>
<script>
//导入eventBus模块
import bus from '../js/eventBus.js'
export default {
name: 'Receiver',
data(){
return {
num:0
}
},
created () {
//接受到send方传递过来的自定义事件,然后处理回调函数的逻辑
bus.on('countChange',(count)=>{
//将接受到的事件所带来的参数进行处理
this.num=count
})
},
methods:{
}
}
</script>
<style scoped>
</style>
<template>
<Send></Send>
<hr/>
<Receiver></Receiver>
</template>
<script>
import Send from './components/Send.vue'
import Receiver from './components/Receiver.vue'
export default {
name: 'App',
data(){
return {
}
},
methods:{
},
components: {
Send,
Receiver
}
}
</script>
<style scoped>
</style>
4、后代关系组件之间的数据共享
后代关系组件之间共享数据,指的是父节点的组件向其子孙组件共享数据,此时组件之间的嵌套关系比较复杂,可以使用provide和inject实现后代关系组件之间的数据共享
谁向外共享数据,谁就使用provide函数
谁接收数据,谁就使用inject函数
- 1、父节点通过provide共享数据
父节点的组件可以通过provide方法,对子孙组件共享数据
provide(){
return {
age:this.age
}
},
- 2、子孙节点可以使用inject数组**,**
子孙节点可以使用inject数组,接收父级节点向下共享的数据
export default {
name: 'Son',
inject:['age']
}
ps,这种共享不是即时的共享
完整代码
1、GrandFather.vue
<template>
<h3>here is grandfather component,grandfather is {{age}} years old</h3>
<button @click="changeAge">改变年龄</button>
<hr/>
<Father></Father>
</template>
<script>
import Father from './Father.vue'
export default {
name: 'GrandFather',
data(){
return{
age:100
}
},
methods:{
changeAge(){
this.age++
}
},
provide(){
return {
age:this.age
}
},
components:{
Father
}
}
</script>
<style scoped>
</style>
2、Father.vue
<template>
<h3>here is Father component</h3>
<hr/>
<Son></Son>
</template>
<script>
import Son from './Son.vue'
export default {
name: 'Father',
components:{
Son
}
}
</script>
<style scoped>
</style>
3、Son.vue
<template>
<h3>here is Son component,grandfather is {{age}} years old</h3>
</template>
<script>
export default {
name: 'Son',
inject:['age']
}
</script>
<style scoped>
</style>
4、App.vue
<template>
<GrandFather></GrandFather>
</template>
<script>
import GrandFather from './components/GrandFather.vue'
export default {
name: 'App',
data(){
return {
}
},
methods:{
},
components: {
GrandFather
}
}
</script>
<style scoped>
</style>
5、父节点对外共享响应式数据
父节点使用provide向下共享数据时,可以结合computed汉化书向下共享响应式的数据
- 1、要从vue导入computed
- 2、使用computed函数,可以把要共享的数据‘包装’成为响应式的数据
provide(){
return {
//使用computed函数,可以把要共享的数据‘包装’成为响应式的数据
age:computed(()=>this.age)
}
},
<template>
<h3>here is grandfather component,grandfather is {{age}} years old</h3>
<button @click="changeAge">改变年龄</button>
<hr/>
<Father></Father>
</template>
<script>
import Father from './Father.vue'
import {computed} from 'vue'
export default {
name: 'GrandFather',
data(){
return{
age:100
}
},
methods:{
changeAge(){
this.age++
}
},
provide(){
return {
//使用computed函数,可以把要共享的数据‘包装’成为响应式的数据
age:computed(()=>this.age)
}
},
components:{
Father
}
}
</script>
<style scoped>
</style>
6、vuex(以后专章讨论)
vuex是终极的组件之间的数据共享防范,在企业级的vue项目开发中,vuex可以让组件之间的数据共享变得高校、清晰、且易于维护
实际就是有一个数据中心store(消息中心)
react也有类似的机制
7、全局配置axios
在main.js入口文件中,通过app.config.globalProgerties全局挂载axios,示例代码如下:
8、ref引用
vue不建议使用jquery
re用来辅助开发者在不依赖jquery的情况下,获取dom元素或组件的应用
每个vue的组件实例上,都包含一个$ref
对象,里面存储着对应的DOM元素或组件的引用,默认情况下,组件的$refs
指向一个空对象
<template>
<div>
<h3>获取refs组件</h3>
<button @click="getrefs">获取$refs引用</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return {
}
},
methods:{
getrefs(){
console.log(this)
}
},
components: {
}
}
</script>
<style scoped>
</style>
9、使用ref引用dom元素
如果想要使用ref应用页面上的dom元素,则可以按照以下步骤实现
- 1、在标签上使用ref属性
ref=‘属性名’
- 2、通过
this.$refs属性名
来活动dom
- 3、对dom进行操作
ps:ref还是很方便的,其实vue作为框架应该有一套直接对dom操作的接口
<template>
<div>
<!-- 添加ref属性及属性名-->
<h3 ref="getRef">获取refs组件</h3>
<button @click="changStyle">改变样式</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return {
}
},
methods:{
changStyle(){
//通过ref获得dom
const h3dom=this.$refs.getRef
//对dom进行操作
h3dom.style.backgroundColor='red'
}
},
components: {
}
}
</script>
<style scoped>
</style>
10、使用ref引用页面上组件的实例(如使用组件的方法)
grandfather.vue
<template>
<h3>here is grandfather component,grandfather is {{age}} years old</h3>
<button @click="changeAge">改变年龄</button>
<hr/>
</template>
<script>
export default {
name: 'GrandFather',
data(){
return{
age:100
}
},
methods:{
//自己的一个改变年龄的方法
changeAge(){
this.age++
}
},
components:{
}
}
</script>
<style scoped>
</style>
app.vue
<template>
<div>
<!-- 添加ref属性及属性名-->
<GrandFather ref="grandfather"></GrandFather>
<button @click="useComponentMethod">使用组件上的方法</button>
</div>
</template>
<script>
import GrandFather from './components/GrandFather.vue'
export default {
name: 'App',
data(){
return {
}
},
methods:{
useComponentMethod(){
//通过ref获得自定义组件的dom
const grandfather=this.$refs.grandfather
//对通过ref获取到的自定义组件上的方法进行调用
grandfather.changeAge()
}
},
components: {
GrandFather
}
}
</script>
<style scoped>
</style>
12、使用this.$nextTick(cb)方法异步更新组件
this.$nextTick(cb)能够将回调函数内部的操作推迟到下次dom更新之后
关键代码:
methods:{
changeflag(){
this.flag=!this.flag
this.$nextTick(()=>{
this.$refs.ipt.focus()
})
}
},
完整代码
<template>
<input type="text" ref="ipt" v-if="flag"/>
<div>
<button v-else @click="changeflag">显示</button>
</div>
<hr/>
</template>
<script>
export default {
name: 'GrandFather',
data(){
return{
flag:true
}
},
methods:{
changeflag(){
this.flag=true
this.$nextTick(()=>{
this.$refs.ipt.focus()
})
}
},
components:{
}
}
</script>
<style scoped>
</style>