vue 之 数据传递(子传父,父传子,非父子通信<事件总线>,父取子<ref,$refs>,插槽,provide和inject数据传递)
一.父传子
传递: 通过在子组件:属性 = 变量 来传递
接收:在子控件内部,props 来接收
第一种:传递基本数据类型
问题:不能直接被用作子组件的v-model双向绑定的变量,否则报错
解决:可以在data中定一个新的变量,把这个值给这个新的变量
第二种:传递对象Object
问题:可以将obj.属性作为子组件的v-model双向绑定的变量,修改时不报错,但是这样做了以后会污染父组件的obj对象,所以需要避免这个情况
解决:可以通过浅拷贝和深拷贝来处理,这样就可以避免污染父组件数据
说明:在通过拷贝时,在created,beforeMount,mounted三个生命周期都有写, 注意,计算属性不要和双向绑定混合使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | app.vue <template> <div id= "app" > <HelloWorld :msg= "msg" :person= "person" keys= "默认key值" @iptFn1= "iptFn1" /> </div> </template> <script> import HelloWorld from "./components/HelloWorld.vue" ; export default { name: "App" , data() { return { msg: "这是父传子" , person: { name: "张三" , age: 18, }, }; }, components: { HelloWorld, }, methods: { iptFn1() { console.log( this .person); }, }, }; </script> <style></style> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | hellow.vue<br><br><template> <div class = "hello" > <!-- msg的值 --> {{ msg }} <input type= "text" v-model= "msg1" @input= "iptFn" /> <hr /> <!-- 对象属性 传过来的重新给person1 --> <input type= "text" v-model= "person1.name" @input= "iptFn1" /> <hr /> <!-- 对象属性 浅拷贝额对象created,beforeMount,mount --> <input type= "text" v-model= "person2.name" @input= "iptFn2" /> {{ "person2:" + person2.name }} <hr /> <!-- 对象属性 计算属性中拷贝 --> <input type= "text" v-model= "person3.name" @input= "iptFn3" /> {{ "person3:" + JSON.stringify(person3) }} <hr /> <!-- person的内容 --> {{ person }} <hr /> <!-- keys的值 --> {{ keys }} </div> </template> <script> import $ from "jquery" ; export default { name: "HelloWorld" , props: { msg: { type: String, default : "消息" , require: true , }, person: { type: Object, default : function() { return {}; }, }, keys: { type: String, }, }, data() { return { msg1: this .msg, person1: this .person, person2: {}, }; }, computed: { // person3() { // return $.extend(false, this.person); //当被用作双向绑定时,会出现无法 // }, }, created() { // this.person2 = $.extend(false, this.person); }, beforeMount() { // this.person2 = $.extend(false, this.person); }, mounted() { this .person2 = $.extend( false , this .person); }, methods: { iptFn() { console.log( this .msg1); }, iptFn1() { this .person1.age = 20; this .$emit( "iptFn1" ); }, iptFn2() { console.log( this .person2.name); // this.$emit("iptFn1"); }, iptFn3() { console.log( this .person3.name); // this.$emit("iptFn1"); }, }, }; </script> <style scoped></style> |
二.子传父
传递:在子组件内部写,this.$emit('事件名',参数1[,参数2...])
接收:在父组件中的子组件上写 @事件名 = 事件名,同时在父组件methods上定一个接收参数的方法
三.非父子间的通信(事件总线)
请参考vue 之 事件总线(订阅者模式,非父子间的数据传递)
建议:多熟悉一下事件总线的使用,可以发现事件总线可以替代 孙-->子-->父的这种通$emit形式来处理的方案.
语法:
1 2 3 4 5 6 7 8 9 | //在main.js 定义一个bus const bus = new Vue() Vue.prototype.bus = bus //发布 this .bus.$emit( 'key' ,参数) //参数可以是基础数据类型或者复杂数据类型 //接收 建议: 在created,beforeMount,mounted生命周期去使用 this .bus.$ on ( 'key' ,(res)=>{ //res是从发布传过来的值 }) |
四.父拿取子的数据
ref 和 $refs 来通过 父读取子的数据
注意点:
1.$refs一定是属于父的
参考网站: Vue中ref和$refs的介绍及使用
五.可以通过插槽父取子 (仅仅局限所在的插槽内部使用)
六.provide 和 inject (数据传递)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | parent.vue export default { data(){ return { name: '张三' , age:18 } }, provide(){ return { name: this .name } },<br> components:{<br> son<br> } } |
1 2 3 4 5 6 7 8 9 10 11 | son.vue <div>{{ name }}</div> export default { inject:[ 'name' ], components:{ Grandson } } |
1 2 3 4 5 6 7 8 | grandson <div>{{ name }}</div> export default { inject:[ 'name' ] } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现