Vue3学习(组合式API——父、子组件间通信详解)
目录
一、组合式API下的父组件传子组件。(自定义属性)
(1)基本思想。
(2)核心注意点。(defineProps)
(3)传递简单类型数据。
(4)传递对象类型数据。(v-bind="对象类型数据")
(5)传递响应式类型数据。(:属性="响应式数据")
(6)defineProps原理简要分析。
二、组合式API下的子组件传父组件。(自定义事件)
(1)基本思想。
(2)核心注意点。
<1>事件驱动通信。
<2>单向数据流原则。
<3>核心实现步骤。
(3)页面渲染时子组件立即向父组件传递数据。
(4)基于子组件的事件函数向父组件传递数据。
三、Vue3组合式API中的父、子组件间通信小结。
一、组合式API下的父组件传子组件。(自定义属性)
(1)基本思想。
- 父组件中给子组件绑定属性。(propsXXX)
- 子组件内部通过props选项(setup中使用defineProps:“编译器宏”)接收。
(2)核心注意点。(defineProps)
- 单向数据流:数据从父组件流向子组件,子组件不直接修改父组件数据。
- 声明式接收:子组件通过 defineProps 声明要接收的属性(props),明确数据类型和校验规则。
- 响应式绑定:父组件通过 ref 或 reactive 创建响应式数据。用 ":" 动态绑定到子组件属性,数据变化时子组件自动更新。
(3)传递简单类型数据。
- 父组件代码示例。
<script setup> //局部子组件(导入就能使用) import Son from "./components/Son.vue";</script><template><div><h2>我是父组件</h2><Son propsCar="宝马5系" /></div> </template><style scoped> </style>
- 子组件代码示例。
<script setup> //因为写在setup中,无法直接配置props选项 //借助于“编译器宏"函数接收子组件传递的数据 const props = defineProps({propsCar : String }) console.log('子组件获取:',props) //脚本中获取属性需要通过props.xxx获取 console.log('子组件获取属性值:',props.propsCar) </script><template> <!-- 对于模版中,可以直接使用props传递的值 --><div class="son">我是子组件------{{propsCar}}</div> </template><style scoped> .son{border: 1px solid #000;padding: 30px; } </style>
- 页面渲染效果。
(4)传递对象类型数据。(v-bind="对象类型数据")
- 父组件代码示例。
<script setup> //局部子组件(导入就能使用) import Son from "./components/Son.vue"; const data = {name: "张三",age: 18 } </script><template><div><h2>我是父组件</h2><Son v-bind="data" /> <!-- 第2种写法也可以 <Son :="data" />--></div> </template><style scoped> </style>
- 子组件代码示例。
<script setup> //因为写在setup中,无法直接配置props选项 //借助于“编译器宏"函数接收子组件传递的数据 const props = defineProps({name: String,age : Number }) console.log('子组件获取:',props) //脚本中获取属性需要通过props.xxx获取 console.log('子组件获取属性值:',props.name) console.log('子组件获取属性值:',props.age) </script><template> <!-- 对于模版中,可以直接使用props传递的值 --><div class="son">我是子组件------{{name}}------{{age}}</div> </template><style scoped> .son{border: 1px solid #000;padding: 30px; } </style>
- 页面渲染效果。
(5)传递响应式类型数据。(:属性="响应式数据")
- 父组件代码示例。
<script setup> //局部子组件(导入就能使用) import Son from "./components/Son.vue"; import {ref} from "vue"; const money = ref(100) const addMoney = () =>{money.value++ } </script><template><div><h2>我是父组件---当前父组件money:{{money}}<button @click="addMoney">money++</button></h2><Son :propsMoney="money" /></div> </template><style scoped> </style>
- 子组件代码示例。
<script setup> //因为写在setup中,无法直接配置props选项 //借助于“编译器宏"函数接收子组件传递的数据 import {watch} from "vue";const props = defineProps(['propsMoney']) console.log('页面首页渲染子组件获取:',props) //脚本中获取属性需要通过props.xxx获取 //监听父组件传递的响应式数据是否变化 watch(() => props.propsMoney, (newValue) => {//每变化一次就打印一次console.log('子组件获取更新的money值:',newValue) }) </script><template> <!-- 对于模版中,可以直接使用props传递的值 --><div class="son">我是子组件------父组件传递的money:{{propsMoney}}</div> </template><style scoped> .son{border: 1px solid #000;padding: 30px; } </style>
- 页面渲染效果。
(6)defineProps原理简要分析。
- 本质上是编译阶段的一个标识。实际当编译器解析时,遇到后会进行编译转换。
二、组合式API下的子组件传父组件。(自定义事件)
(1)基本思想。
- 父组件中给子组件通过@绑定事件。
- 子组件内部通过emit方法触发事件。
(2)核心注意点。
<1>事件驱动通信。
- 子组件通过自定义事件向父组件发送数据。父组件监听这些事件并处理数据。
- 子组件使用defineEmits声明可触发的事件。通过emit触发事件并传递参数。
<2>单向数据流原则。
- 子组件不直接修改父组件数据,而是通过事件通知父组件自行更新。
<3>核心实现步骤。
- 子组件步骤。
- 声明事件:const emit = defineEmits(['事件名',...,])。
- 触发事件:emit ('需触发的事件名',{需携带的参数...})。
- 父组件步骤。
- 监听事件:子组件标签<Xxx @子组件触发的事件名="父组件中处理事件的方法">。
- 处理事件:在对应的方法中更新自身状态。
(3)页面渲染时子组件立即向父组件传递数据。
- 父组件页面初始渲染效果。
<script setup> //局部子组件(导入就能使用) import Son from "./components/Son.vue"; import {reactive} from "vue"; const data = reactive({name:'张三',addr:'湖南长沙' })</script><template><div><h2>我是父组件---当前父组件响应式数据:姓名:{{data.name}} 地址:{{data.addr}}</h2><Son /></div> </template><style scoped> </style>
- 子组件自定义事件向父组件传递新值。
<script setup>//通过defineEmits编译器宏声明事件、emit方法 const emit = defineEmits(['changeValue']) //页面渲染时直接触发自定义的事件并进行传参 emit('changeValue',{name : '李四',addr : '湖北武汉' }) </script><template><div class="son">我是子组件</div> </template><style scoped> .son{border: 1px solid #000;padding: 30px; } </style>
- 父组件监听子组件(自定义事件)传递的数据。
<script setup> //局部子组件(导入就能使用) import Son from "./components/Son.vue"; import {reactive} from "vue"; const data = reactive({name:'张三',addr:'湖南长沙' })const getValue = (res) => {console.log('子组件传递的数据:',res);data.name = res.name;data.addr = res.addr; };</script><template><div><h2>我是父组件---当前父组件响应式数据:姓名:{{data.name}} 地址:{{data.addr}}</h2> <!-- @后面跟的必须和子组件的事件名一致 --> <!-- getValue:处理子组件传递的数据,更新自身状态 --><Son @change-value="getValue" /></div> </template><style scoped> </style>
- 页面最终渲染效果。
(4)基于子组件的事件函数向父组件传递数据。
- 基本实现:当子组件输入框的内容并按钮提交(事件函数触发),通过自定义事件的触发将对应的参数通过子组件传递到父组件。
- 子组件代码示例。
<script setup>//通过defineEmits编译器宏声明事件、emit方法 import {ref} from "vue";const emit = defineEmits(['submitInput'])const inputValue = ref('') //在子组件的对应事件函数上触发子组件向父组件传值的自定义事件 const changeInput = () =>{emit('submitInput',{input: inputValue.value}) } </script><template><div class="son"><h3>我是子组件</h3><div style="padding: 10px"><input type="text" v-model="inputValue">输入框的值:{{inputValue}}<button @click="changeInput">提交(子传父)</button></div></div></template><style scoped> .son{border: 1px solid #000;padding: 30px; } </style>
- 父组件代码示例。
<script setup> //局部子组件(导入就能使用) import Son from "./components/Son.vue"; import {reactive} from "vue"; const data = reactive({value:'哈哈哈哈我是父组件的响应式', })const getInputValue = (res) => {console.log('子组件传递的数据:',res);data.value = res.input; };</script><template><div><h2>我是父组件---当前父组件响应式数据:{{data.value}}</h2> <!-- @后面跟的必须和子组件的事件名一致 --> <!-- getValue:处理子组件传递的数据,更新自身状态 --><Son @submitInput="getInputValue" /></div> </template><style scoped> </style>
- 页面渲染效果。
三、Vue3组合式API中的父、子组件间通信小结。
- 父传子过程中通过 defineProps({属性名:类型,...}) 方式接收props。
- setup语法糖中通过 const props=defineProps({属性名:类型,...})、props.xxx 使用父组件传递的数据。而在模版中可以直接通过属性名使用。
- 子传父过程中通过 defineEmits(['事件名',...]) 方式得到emit方法。
- 触发事件:emit('事件名',需传递的参数) 。父组件通过@事件名即可监听。