一、父子组件传值
父组件通过props向子组件传值,子组件通过emit触发自定义事件传递新值给父组件。
props:setup函数中第一个参数props用于接收父组件传递进来的参数。注意:props参数中,只会接收props选项中接收的参数 。
context参数:setup函数中的第二个参数是一个上下文对象context。context参数里面有三个对象:attrs,emit,slots。
- attrs:用于获取没有采用props选项接收的参数。
- emit:用于触发自定义事件。
- slots:返回的是插槽里面的虚拟DOM信息。
虚拟DOM:就是vue实例所能识别的一个DOM信息对象。
父组件
父组件
姓名:{{ name }}
年龄:{{ age }}
年龄:{{ sex }}
这里顶部
这里底部
- {{scope.car.name}}
- {{scope.car.price}}
import {ref} from 'vue'
import Son1 from "./Son1.vue";
export default {
name: "Parent",
setup() {
let name = ref('张三')
let age = ref(20)
let sex = ref('男')
let updateData = (e)=>{
name.value = e.myName
age.value = e.myAge
sex.value = e.mySex
}
return {
name,
age,
sex,
updateData
}
},
/* data() {
return {
name:'张三',
age:20
}
},
methods: {
updateData(e){
this.name = e.myName
this.age = e.myAge
}
}, */
components: {
Son1,
},
};
子组件
Son1
姓名:{{ myName }}
年龄:{{ myAge }}
性别:{{ mySex }}
import {ref,reactive} from 'vue';
export default {
name: "Son1",
//接收父组件的传值
props: ["name", "age"],
// setup的第一个参数,用于获取父组件的传值
// 注意:props选项接收了几个参数,setup函数的第一个参数就只能获取几个参数。
// setup的第二个参数,是一个上下文对象;它里面一个方法是emit,用于触发自定义事件
// props选项没有接收的传值,在setup里面通过上下文对象的attrs属性接收
setup(props,{emit,attrs,slots}) {
// slots对象返回的是插槽里面的虚拟DOM信息
console.log(slots.top());
// 中转props里面的数据,因为props是只读的
let myName = ref(props.name)
let myAge = ref(props.age)
let mySex = ref(attrs.sex)
let car = reactive({
name:'奔驰',
price:20
})
let updateData = ()=>{
myName.value = '李四'
myAge.value = 30
mySex.value = '女'
// 触发自定义事件
emit('updateData',{myName:myName.value,myAge:myAge.value,mySex:mySex.value})
}
return {
myName,
myAge,
mySex,
updateData,
car
}
}
/* data() {
return {
myName:this.name,
myAge:this.age
}
},
methods: {
updateData(){
this.myName = '李四'
this.myAge = 30
this.$emit('updateData',{myName:this.myName,myAge:this.myAge})
}
}, */
};
二、祖孙组件传值
祖级组件通过provide将指定的数据添加为依赖数据,让后代组件可以直接使用。孙代组件通过inject注入祖级组件中设置为依赖的数据。
祖级组件
import {ref,provide} from 'vue'
import Son from './components/Son.vue'
export default {
name: 'App',
setup() {
let name = ref('张三')
let age = ref(20)
// 通过provide()方法,定义依赖数据,从此它的子组件,就可以获取这些数据了
provide('name',name)
provide('age',age)
return {
name,
age
}
},
components: {
Son
}
/* data() {
return {
name:'张三',
age:20
}
},
methods: {
// 修改数据的方法
updateData(name,age){
this.name = name
this.age = age
}
},
// 定义依赖数据
provide(){
return {
name:this.name,
age:this.age,
updateData:this.updateData
}
}, */
}
孙级组件
SubSon
- 姓名:{{name}}
- 年龄:{{age}}
-
import {inject} from 'vue'
export default {
name: "SubSon",
setup() {
// inject()方法,用于注入父级中依赖的数据
let name = inject('name')
let age = inject('age')
let update = ()=>{
name.value = '李四'
age.value = 30
}
return {
name,
age,
update
}
}
/* inject:['name','age','updateData'],
data() {
return {
myName:this.name,
myAge:this.age
}
},
methods: {
update(){
this.myName = '李四'
this.myAge = 30
this.updateData('李四',30)
}
}, */
};
三、v-model
在Vue3中,父组件中可以通过v-model指令实现对多个数据的双向绑定。注意:vue3取消了sync修饰符,它将v-model指令和sync修饰符进行了合并。
子组件中,自定义事件名称必须命名为update:属性名,就可以实现对父组件中指定属性的双向绑定。
父级组件
App
import {ref,provide} from 'vue'
import Son3 from './components/Son3.vue'
export default {
name: 'App',
setup() {
//定义飞机的相关数据
let planeName = ref('波音747')
let planePrice = ref(100)
let planeAddress = ref('美国')
return {
// 返回飞机相关信息
planeName,
planePrice,
planeAddress
}
},
components: {
Son3
}
子级组件
Son3
- 飞机名称:{{ planeName }}
- 飞机价格:{{ planePrice }}
- 飞机产地:{{ planeAddress }}
-
-
-
export default {
name: "Son3",
//接收父组件传递过来的数据
props: ["planeName", "planePrice", "planeAddress"],
setup(props, { emit }) {
let updatePlaneName = () => {
// 注意:事件方法必须是update:prop,如果父组件中采用的是v-model:prop
// 此时,父组件就可以实现对prop的双向数据绑定。
emit("update:planeName", "长城1号");
};
let updatePlanePrice = () => {
emit("update:planePrice", 200);
};
let updatePlaneAddress = () => {
emit("update:planeAddress", "中国");
};
return {
updatePlaneName,
updatePlanePrice,
updatePlaneAddress,
};
},
};
四、异步组件
suspense内置组件:用于在渲染异步组件时,添加Loading效果。
使用
注意:异步加载的组件可以用suspense,也可以不用。不用suspense组件,会失去异步的作用;但是,如果组件中setup的返回值是一个Promise对象,该组件必须要用suspense。
定义组件
Son4
- 商品名称:{{ goodsName }}
- 商品价格:{{ goodsPrice }}
-
import { ref } from "vue";
export default {
name: "Son4",
setup() {
let goodsName = ref("小米电视");
let goodsPrice = ref(2000);
//setup方法的返回值,可以是一个Promise对象
return new Promise((resolve,reject)=>{
setTimeout(() => {
resolve({
goodsName,
goodsPrice,
show
})
}, 2000);
})
// return {
// goodsName,
// goodsPrice,
// }
},
};
使用
App
Loading...
// defineAsyncComponent组合式API,用于定义异步组件
import {defineAsyncComponent} from 'vue'
// 异步导入组件
const Son4 = defineAsyncComponent(()=>import('./components/Son4.vue'))
五、teleport组件
Vue 3.0 新增了一个内置组件 teleport ,主要是为了解决以下场景:有时组件模板的一部分逻辑上属于该组件,而从技术角度来看,最好将模板的这一部分移动到 DOM 中 Vue app 之外的其他位置。
teleport组件:瞬移。通过to属性确定里面的元素移动到哪。to属性的属性值是指定的选择器。
例如:在下面的案例中,box盒子逻辑上属于son4盒子,但是为了使box盒子设置的相对定位,不受其他父级元素的影响,我们将box盒子瞬移到body下。
Son4
- 商品名称:{{ goodsName }}
- 商品价格:{{ goodsPrice }}
.box{
width: 200px;
height: 200px;
border: 1px solid black;
padding: 10px;
background: lightblue;
/* 绝对定位 */
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
使用teleport瞬移后,box盒子的结构是在body下,与#app平级。