一,props自定义属性
组件传值的过程中,会涉及到自定义属性的使用;除了基本的数组格式之外,我们有多种使用方式
1, 子组件中,可以给自定义属性指定类型、指定默认数据
<template>
<div class="c-container">
<h3>子组件</h3>
<p>接受的父组件基本类型数据:{{ msg }} </p>
<p>接受的父组件数组数据:{{ techs }}</p>
</div>
</template>
<script>
export default {
// 1、基本语法
// props: ['msg', 'techs']
// 2、指定类型
// props: {
// msg: String,
// techs: Array
// }
// 3、指定默认值:如果是数组或者对象,必须通过函数指定默认值
props: {
msg: {
type: String,
default: '默认数据'
},
techs: {
type: Array,
default: () => {
return ['默认数组']
}
}
}
}
</script>
<style>
</style>
2,props
父组件传递给子组件数据,子组件默认不能修改父组件数据【单向数据流】
- 默认情况下,父组件传递数据给子组件,单向数据流;子组件不能直接修改父组件传递的数据
- 子组件中需要使用修改父组件传递的数据,可以在
data
选项中对自定义属性重新赋值,操作data数据
- 子组件中需要父组件传递的数据参与运算,可以在
computed
选项中添加计算属性
<template>
<div class="c-container">
<h3>子组件</h3>
<p>接受的父组件基本类型数据:{{ msg }} </p>
<p>接受的父组件数组数据:{{ techs }}</p>
<p>接受并赋值的数据:{{ myMsg }}</p>
<p>接受并运算的数据:{{ transfer }}</p>
<button @click="myMsg='new data'">修改父组件数据</button>
</div>
</template>
<script>
export default {
// 3、指定默认值:如果是数组或者对象,必须通过函数指定默认值
props: {
msg: {
type: String,
default: '默认数据'
},
techs: {
type: Array,
default: () => {
return ['默认数组']
}
}
},
data() {
return {
// 如果只是要使用父组件数据,可以将父组件数据接收到自己的数据中
myMsg: this.msg
}
},
computed: {
// 如果需要父组件数据参与运算,通过计算属性完成数据运算,不要直接修改父组件数据
transfer() {
return this.msg + "新数据处理"
}
}
}
</script>
<style>
</style>
二,嵌套生命周期
问题:当出现父子组件嵌套关系时,父子组件各自都有独立的生命周期,他们的生命周期执行顺序是什么样的?关注重点- 父组件的生命周期、子组件的生命周期 -- 混合
- 父组件:
beforeCreate()
- 父组件:
created()
- 父组件:
beforeMount()
- 子组件:
beforeCreate()
- 子组件:
created()
- 子组件:
beforeMount()
- 子组件:
mounted()
- 子组件:
- 父组件:
mounted()
<template>
<div class="c-container">
<h2>父组件</h2>
<Child2/>
</div>
</template>
<script>
import Child2 from '../components/Child2.vue'
export default {
components: {
Child2
},
beforeCreate() {
console.log("1.父组件 beforeCreate")
},
created() {
console.log("2.父组件 created")
},
beforeMount() {
console.log("3.父组件 beforeMount")
},
mounted() {
console.log("4.父组件 mounted")
},
beforeUpdate(){},
updated() {},
beforeDestroy() {},
destroyed() {}
}
</script>
<style>
</style>
三,组件边界处理
核心:数据访问和数据传递问题
1,$root
,可以在任意组件中,直接访问根组件数据
2,$parent
,允许子组件中直接通过该属性访问和修改父组件中的数据,一般不推荐
问题:默认情况下,Vue
中父组件给子组件传递数据,是单向数据流,那么子组件是否可以直接 修改父组件中的数据?
父子组件传值时,如果通过自定义属性的方式传递给子组件数据,子组件不可以修改父组件数 据;但是边界传值中可以在子组件中直接通过$parent
属性修改父组件中的数据,如果没有必要 不会推荐这样的操作,会导致数据管理比较混乱;项目中推荐子组件通过自定义事件方式让父组 件主动修改数据
3,ref
,允许父组件可以直接操作子组件中的数据,推荐
ref
,允许父组件可以直接操作子组件中的数据,推荐
4,$forceUpdate
,控制强制更新
<template>
<div class="d-container">
<h2>$forceUpdate数据强制更新</h2>
<p>数据:{{ techs }}</p>
<button @click='add1'>标准方式修改数据</button>
<button @click='add2'>索引方式添加数据</button>
<button @click='add3'>内建函数set完成索引更新</button>
</div>
</template>
<script>
import Vue from 'vue'
export default {
data() {
return {
techs: ['javascript']
}
},
methods: {
add1() {
// 标准函数添加数据
this.techs.push('nodejs')
},
add2() {
// 索引方式添加数据
this.techs[1] = 'express'
console.log(this.techs)
// 不依赖vue本身更新方式,强制更新
this.$forceUpdate()
},
add3() {
// 内建函数完成数据更新:只需要知道即可,Vue3中废弃
// this.$set(this.techs, 1, 'java')
// Vue原型对象上的set()函数,通过索引添加数据
Vue.set(this.techs, 1, 'python')
}
}
}
</script>
<style>
</style>
四,动画
1,通用动画
VUE
提供了一种简单的页面切换动画,内建了一些通用动画样式可以直接使用
.v-enter{} 进入前 .v-enter-active{} 进入中 .v-enter-to{} 进入后 .v-leave{} 离开前 .v-leave-active{} 离开中 .v-leave-to{} 离开后
上述样式会针对组件中出现的所有包含在<transition></transition>
标签的单个元素产生动画效果
<transition>
<component :is="page"></component>
</transition>
2,命名动画
可以针对不同的需要定制的动画,进行命名来区别
.myname-enter{} 进入前 .myname-enter-active{} 进入中 .myname-enter-to{} 进入后 .myname-leave{} 离开前 .myname-leave-active{} 离开中 .myname-leave-to{} 离开后
只会针对如下的节点产生动画效果
<transition name="myname">
<component :is="page"></component>
</transition>
3,列表动画
如果需要动画效果的元素不是单元素;而是列表元素,此时可以通过如下方式进行操作:
<transition-group name="myname">
<tr v-for="..." :key="...">...</tr>
</transition-group>
如果需要一些较为复杂的动画效果,可以借助第三方动画插件:animate.css
五,DOM加载
项目组件中,经常会遇到这样一种,需要指定节点的DOM
加载成功后再去操作数据
1,延时加载
通过setTimeout()
延时函数,产生一个加载时间差,让对应的DOM
元素加载成功后设置对应的数据,即使不指定延时事件~函数的执行也是需要时间的,所以延时延时的操作可以给DOM元素设置数据的,但是不推荐
setTimeout(function() {
this.$refs.input.value = "xxxx"
})
2,nextTick
Vue.nextTick()
以及this.$nextTick()
都是等待当前组件DOM
更新结束后再去执行的函数,一般用于等待DOM
更新结束后执行对应的操作,通过回调函数实现
// 1、this.$nextTick()不能在普通函数中,等待子组件加载完成再去执行
// 2、Dialog.nextTick()在组件上直接调用nextTick()不可行
// 3、通过缓存方式直接操作子组件DOM元素,不可行
原因:
nextTick()
底层工作原理等待当前组件mounted()
执行结束再去执行回调函数
- 子组件在某个单击事件发生时,加载子组件;父组件
nextTick()
会等待自组件加载完成后再去执行代码吗? nextTick()
一般会在created()
和mounted()
生命周期中使用