父组件向子组件传参
父组件代码:
<template>
<div>
<h1>这是父页面</h1>
// 父组件在调用子组件的时候,传入参数
<Son msg="这是父组件传到子页面的参数"></Son>
</div>
</template>
<script>
// 导入需要的子组件 import后面的Son可自定义
import Son from "./Son";
export default {
components:{
// 组件与标签的映射
Son,
},
}
</script>
子组件代码:
<template>
<div>
<h2>这是子页面</h2>
{{msg}}
</div>
</template>
<script>
export default {
// 在子组件中声明props属性,定义一些属性变量
props:['msg']
}
</script>
效果:
子组件向父组件传数据,并修改父组件传递的参数
子组件向父组件传数据和子组件修改父组件传递的参数类似,所以就写一起了。
这里为了展示更加复杂的项目逻辑,因而使用了Element 组件。
需要注意的是:
在Vue中,不推荐子组件直接修改父组件的参数。例如:把一个布尔值传递给子组件,然后在子组件中修改该值,会报错:
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders
原因:
父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。
Prop 是单向绑定的:
当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解。
所以为了实现子组件修改父组件的效果,需要将修改过后的值传到父组件中,由父组件重新赋值即可。
父组件代码:
<template>
<div>
<h1>这是父页面</h1>
<!-- 点击事件将dialogVisible的值改为true,使得:dialogVisible=true,展示子组件的弹窗-->
<el-button type="primary" @click="dialogVisible=true">新建</el-button>
<!-- 在父组件调用子组件时,定义一个接收事件,putDialogVisible就是定义好的一个事件-->
<Son :dialogVisible="dialogVisible" @putDialogVisible="putDialogVisible"></Son>
</div>
</template>
<script>
import Son from "./Son";
export default {
components:{
// 映射组件
Son,
},
data(){return{
dialogVisible:false,
}},
methods:{
// 父组件接收经过子组件传递的参数,这个参数是由父组件传到子组件的并经过子组件修改的
// 重新对dialogVisible进行赋值,以达到子组件修改父组件传递的参数的目的
putDialogVisible(data){
this.dialogVisible = data
}
},
}
</script>
子组件代码:
<template>
<div>
<h2>这是子页面</h2>
<el-dialog title="创建用户" :visible.sync="dialogVisible" width="50%">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="用户名">
<el-input v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="form.password"></el-input>
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="form.phone"></el-input>
</el-form-item>
<div>
<el-button type="primary" @click="onSubmit">创建</el-button>
<el-button @click="cancel">取消</el-button>
</div>
</el-form>
</el-dialog>
</div>
</template>
<script>
export default {
// 在子组件中声明props属性,定义一些属性变量,接收父组件传递的参数dialogVisible
// 此时dialogVisible = true
props:['dialogVisible'],
data(){
return {
form:{
username:"",
password:"",
phone:"",
},
role_list:[{"id":"1","name":"管理员"},{"id":2,"name":"普通用户"}]
}
},
methods:{
onSubmit(){
alert('添加')
},
cancel(){
// 点击取消按钮,定义一个新变量,值为false
let data = false
// 子组件触发事件并传递数据将新变量传递给父组件,达到修改参数的目的
this.$emit('putDialogVisible',data)
}
},
}
</script>
效果:
点击新建按钮(点击‘取消’后弹窗消失):
上面的解决办法是指传递的参数只应用于一个子组件,并不满足应用多个子组件时的情况,当应用于多个子组件时,使用以下方法:
子组件不能修改父组件传递过来的值的原因,就是因为vue的单向数据流限制,当然,这个限制是很有必要的,我们假设一个场景,父组件有多个子组件,都用到了某个传递的参数,其中一个子组件修改了父组件传递过来的值,那么其他的子组件接收到的也会是改变后的值,这样显然是不合理的。
既然不能直接修改,那么,我们不妨在子组件定义一个副本,用来接收父组件传递过来的值,子组件定义的每个参数,其作用域都只局限于当前组件,所以,直接修改副本,并不会影响其他子组件。