vue子组件给父组件传值,即父组件监听子组件($emit)

本文详细介绍如何在Vue项目中实现子组件向父组件的数据传递过程,包括定义子组件、添加状态值与点击事件、使用$emit触发事件及父组件接收处理等步骤。

1、准备:cdn引入vue框架,画一个页面渲染区域,实例化一个vue并指定渲染区域。

<!-- 引入vue框架 -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<div id="app">
              
    </div>
let app = new Vue({
        el: "#app",//最大的组件 根组件
        data: {
            
        },
})

2、定义一个子组件,引用子组件。

// 自定义一个全局组件
    // 第一个参数-组件名称 (名字不能是小驼峰,是小写字母-小写字母)
    // 第二个参数-配置
    Vue.component("button-component", {
        // 状态值:要求状态对应一个组件的实例
        data(){
            return {
                
            }
        },
        // 组件的模板:必须要用一个div包括起来
        template:`<div>
            
        </div>`,
    })
<div id="app">
        <!-- 在根组件里使用自定义组件 -->
        <button-component></button-component>      
    </div>

3、在子组件状态值data里面添加要传递的值,并在模板里添加一个按钮绑定点击事件用来触发值传递事件。

data(){
            return {
                name:"hehe",
            }
        }
 template:`<div>
            {{name}}
            <button @click="toParent">传值</button>
        </div>`

4、在子组件的方法中写子组件模板中按钮绑定的事件内容-即使用$emit方法把值传递给父组件。注意这里的this指的是子组件,传递事件是changenum(自定义名字,不能驼峰命名)。

methods: {
            // 子组件通过$emit调用父组件中的方法
            // $emit只能在子组件中使用
            // 将组件中的count传递到父组件中
            toParent() {
                // 触发changenum事件,传递count值
                this.$emit("changenum",this.name)
            }
        }

5、在引用子组件标签中添加@changenum="changeInfo"把changenum事件传递出去,changeInfo是父组件中定义来接值的方法。

<button-component @changenum="changeInfo"></button-component>

6、在父组件的状态值中定义一个状态值,并在方法中定义changeInfo方法去处理传递的值。

data: {
            appname:''
        }
methods: {
            // 响应子组件触发的changenum事件
            // 参数:分别接受子组件中$emit传递过来的参数
            changeInfo(val1){
                this.appname=val1;
            }
        }

7、在父组件中引用状态值appname,运行看效果。

<p>传的名字:{{appName}}</p>

 

 

 

 

 

### Vue子组件父组件并修改的解决方案 在 Vue 的开发过程中,遵循单向数据流的原则是非常重要的。官方文档明确指出,在子组件中不应该直接修改由父组件递下来的 `prop` [^1]。然而,在实际项目中可能会遇到需要子组件通知父组件更改某些状态的情况。 #### 问题分析 当子组件尝试直接修改父组件递的 `prop` 时,Vue 会抛出警告或错误,因为这违反了单向数据流的设计原则。这种行为可能导致不可预测的状态变化以及潜在的渲染问题[^1]。 为了正确实现子组件之间的交互,推荐的方式是通过事件机制 (`$emit`) 或者 Vuex/Pinia 等全局状态管理工具来协调数据流动。 --- #### 解决方案一:使用 `$emit` 实现子组件通信 子组件可以通过触发自定义事件将数据发送给父组件父组件监听该事件并对数据进行更新。以下是具体实现: ##### 子组件代码 ```vue <template> <button @click="sendDataToParent">点击按钮</button> </template> <script> export default { methods: { sendDataToParent() { this.$emit('update-parent-data', '新数据'); // 向父组件发送数据 } } }; </script> ``` ##### 父组件代码 ```vue <template> <div> <p>当前数据:{{ parentData }}</p> <child-component @update-parent-data="handleUpdate"></child-component> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentData: '初始数据' }; }, methods: { handleUpdate(newData) { this.parentData = newData; // 更新父组件的数据 } } }; </script> ``` 这种方式完全符合 Vue 的设计哲学,即子组件不直接修改父组件的数据,而是通过事件通知父组件自行决定如何处理这些数据[^3]。 --- #### 解决方案二:使用 `.sync` 修改器 (适用于 Vue 2) `.sync` 是一种语法糖,用于简化父子组件间的双向绑定逻辑。它本质上仍然是基于 `$emit` 来工作的。 ##### 使用方法 在父组件中声明一个带有 `.sync` 的属性,并将其递给子组件子组件通过 `$emit` 更新这个属性即可。 ###### 父组件代码 ```vue <template> <div> <p>当前数据:{{ parentData }}</p> <child-component :data.sync="parentData"></child-component> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentData: '初始数据' }; } }; </script> ``` ###### 子组件代码 ```vue <template> <button @click="updateSyncedValue">点击按钮</button> </template> <script> export default { props: ['data'], methods: { updateSyncedValue() { this.$emit('update:data', '新数据'); // 触发 sync 修饰符的行为 } } }; </script> ``` 需要注意的是,`.sync` 已经被废弃于 Vue 3 中,因此建议优先考虑其他更现代的方法。 --- #### 解决方案三:利用 `v-model` 自定义输入输出 (推荐)Vue 2.2 开始支持自定义组件上的 `v-model` 功能,允许开发者创建具有特定语义的双向绑定接口。 ##### 父组件代码 ```vue <template> <div> <p>当前数据:{{ parentData }}</p> <custom-input v-model="parentData"></custom-input> </div> </template> <script> import CustomInput from './CustomInput.vue'; export default { components: { CustomInput }, data() { return { parentData: '初始数据' }; } }; </script> ``` ##### 子组件代码 ```vue <template> <input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /> </template> <script> export default { props: ['modelValue'] }; </script> ``` 此模式不仅简洁明了,还能够很好地兼容未来版本升级需求[^3]。 --- #### 解决方案四:延迟加载子组件以避免异步问题 如果存在异步场景下父组件尚未准备好就试图访问其数据,则可能引发异常。此时可以在父组件中动态控制子组件的渲染时机,确保只有当所需资源准备完毕后才实例化子组件[^2]。 示例见引用[2]: ```vue <template> <child-component v-if="dataReady" :data="parentData"></child-component> </template> <script setup> import { ref } from 'vue'; const dataReady = ref(false); setTimeout(() => { dataReady.value = true; }, 2000); </script> ``` 这种方法特别适合涉及 API 请求或其他耗时操作的应用程序结构优化。 --- ### 总结 针对 Vue子组件父组件后发生错误的问题,最佳实践包括但不限于采用 `$emit`、`.sync`(仅限 Vue 2)、`v-model` 及合理安排组件生命周期等方式加以规避。每种策略各有优劣,请依据实际情况灵活选用最合适的手段解决问题。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值