前言
Vue3新出的setup让它有质的飞跃,vue3用起来也比vue2要爽很多,但是两者之间很多写法是不兼容的,例如父子通信就有很大变化,不仅如此,vue3.0跟vue3.2之间也有一些变化会让你报错
vue3中使用defineProps来接受父组件传过来的prop, 使用defineEmit来给父组件传递信息
父传子
父组件通过prop给子组件传值
定义的子组件myMap,如果你用了v-model:并且传的值是对象或数组,那么子组件可以通过Update :modelValue修改你父组件传入的prop,下面代码传递是String类型值,Update的用法与使用案例在下面的子向父传值中有讲解。
<myMap
v-model:lat="form.lat"
v-model:lon="form.lon"
></myMap>
子组件接受
<script setup>
import { defineEmits, defineProps,toRefs } from "vue";
const props = defineProps({
//子组件接收父组件传递过来的值
lat: Number||String,
lon: Number||String,
});
//使用父组件传递过来的值
const { lat,lon } = toRefs(props);
</script>
这里可以看到我直接在script里面写了setup,这和之前的写一个setup函数有什么区别呢?
Vue3.2带来的setup语法糖
用过的人都说好
- 我们不需要想之前一样什么都得return了,直接写直接用,他会为我们默认暴露
- 我们注册组件时也是,直接import就可以了,不需要在去声明
- hooks(自定义函数)用起来也更加丝滑
- defineExpose可以帮我们向父组件暴露子组件的属性
方法:
//子组件代码
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref('1')
//主动暴露组件属性
defineExpose({
a,
b
})
</script>
//父组件代码
<template>
<div>父组件</div>
<Child ref='childRef' />
<button @click='getChildData'>通过ref获取子组件的属性 </button>
</template>
<script setup>
import {ref} from 'vue'
import Child from './child.vue'
const childRef= ref() //注册响应数据
const getChildData =()=>{
//子组件接收暴露出来得值
console.log(childRef.value.a) //1
console.log(childRef.value.b) //''1 响应式数据
}
</script>
子组件向父组件传值
正常情况下,我们不能直接修改父组件传的值,但是如果我们让子组件把值传给父,父组件调用一个函数就可以帮我们实现功能
子组件写法
<template>
<div id="map">
map
<div class="getD">
<el-button @click="updateLatAndLon" type="success" size="small"
>获取经纬度</el-button
>
</div>
</div>
</template>
<script setup>
import { defineEmits } from "vue";
// 使用defineEmits创建名称,接受一个数组
const emit = defineEmits(["update:latAndLon"]);
const updateLatAndLon = () => {
console.log(lat,lon);
let param = {
lat: "22.11",
lon: "11.33",
};
//传递给父组件
emit("update:latAndLon", param);
};
</script>
可以看到代码中emit里的update:latAndLon就是上面提到的子组件可以通过Update :modelValue修改你父组件传入的prop,要知道我们的父组件并没有设置show的自定义事件 但是你父组件show的值却更新了 这就是同步更新的好处 不需要你再手动来添加自定义事件
父组件接受与使用
template部分:
<myMap
@update:latAndLon="onUpdateLatAndLon"
></myMap>
script部分:
const onUpdateLatAndLon = (latAndLon) => {
// 更新form中的lat和lon值
form.lat = latAndLon.lat;
form.lon = latAndLon.lon;
},
你可能遇到的bug
原因其实是vue3.2的一次改动,浏览器会跟你报错说它不认识emit
这个问题是因为你vue3的一些依赖包版本过低导致的,所以我们需要更新
vue
版本,或者升级@vue/compiler-sfc
yarn upgrade vue@3.2.36
# 更新到vue指定版本
yarn upgrade @vue/compiler-sfc@3.2.36
如果你执行了上面的还不管用,可以先删除node——modules和package.lock.json文件,可以用rimraf来帮你删除