当前位置: 首页 > Web前端 > vue.js

vue组件之间的传值方式

时间:2023-03-31 14:55:54 vue.js

我们都知道Vue是一个轻量级的前端框架,其核心是组件开发。Vue是由一个个组件组成的。组件化是其本质,也是最强大的功能之一。组件实例的范围是相互独立的,这意味着不同组件之间的数据不能相互引用。但是在实际的项目开发过程中,我们需要访问其他组件的数据,所以就存在组件通信的问题。Vue中组件之间的关系是:父子、兄弟、世代间隔。对于不同的关系,如何实现数据传递就是接下来要讲的内容。1、父组件给子组件传值,即父组件通过属性给子组件传值,子组件通过props接收。在父组件的子组件标签中绑定自定义属性//父组件exportdefault{components:{UserDetail}......}在子组件中使用props(它可以是一个数组或一个对象)只是接收它。可以传递多个属性。//Subcomponentexportdefault{props:['myName']}/*props:{myName:String}//这里指定传入的类型,如果类型不对,会警告props:{myName:[String,Number]}//多种可能的类型prosp:{myName:{type:String,requires:true}}//需要的字符串props:{childMsg:{type:Array,default:()=>[]}}//默认指定默认值。如果道具验证失败,将在控制台中发出警告。*/子组件接受的父组件的值分为引用类型和普通类型两种:普通类型:字符串(String)、数字(Number)、布尔(Boolean)、空(Null)引用类型:数组(Array)、对象(Object)是基于Vue的单向数据流,即组件之间的数据是单向流的,子组件不允许直接修改从父组件传过来的值,所以这种直接修改父组件传递的值的操作应该避免,否则控制台会报错。如果传递的值是简单数据类型,可以在子组件中修改,不会影响其他兄弟组件中也调用的来自父组件的值。具体操作是将传递的值重新赋值给data中的一个变量,然后改变那个变量。//子组件exportdefault{props:['myName'],data(){return{name:this.myName//将传递的值赋给一个新变量}},watch:{myName(newVal){this.name=newVal//监听从父组件传过来的值,如果改变了,也会改变子组件内部的值}},methods:{changeName(){this.name='Lily'//这里修改的是只是如果不使用watch监听父组件传过来的myName值,子组件中的name值不会随着父组件的myName值而变化,因为name:this.myName中的数据只是定义了一个初始值。如果在子组件中修改了引用类型的值,那么父组件也会被修改,因为数据是公开的,其他同样引用该值的子组件也会被修改。可以这样理解,从父组件传递给子组件的值,相当于复制了一个副本,这个副本的指针仍然指向父组件中的那个,即共享同一个引用。所以除非有特殊需要,不要轻易修改。2.子组件给父组件传值1.子组件绑定一个事件,通过this.$emit()触发子组件中绑定一个事件,并为这个事件定义一个函数//子组件更改父组件的名称exportdefault{methods:{//子组件的事件changeParentName:function(){this.$emit('handleChange','Jack')//触发handleChange父组件中的事件并传递参数Jack//注意:这里的事件名称必须与父组件中绑定的事件名称一致}}}定义并绑定父组件中的handleChange事件//父组件methods:{changeName(name){//name参数为子组件中传入的值Jackthis.name=name}}2.先在父组件中定义一个通过回调函数回调函数,并将回调函数传递给//父组件methods:{callback:function(name){this.name=name}}在子组件中接收,并执行回调函数//子组件更改父组件的名称props:{callback:Function,}3.通过$parent/$children或$refs访问组件实例这两个都是直接获取组件实例,使用后可以直接调用组件的方法或访问数据。//subcomponentexportdefault{data(){return{title:'subcomponent'}},methods:{sayHello(){console.log('Hello');}}}//父组件注意:这种组件通信方式不能跨级。4.$attrs/$listeners单击此处了解详细信息。三、兄弟组件间传值1、在父组件中通过$emit和props的组合,绑定要传给两个兄弟组件的变量。并定义事件//父组件exportdefault{data(){return{name:'John'}},components:{'child-a':ChildA,'child-b':ChildB,},methods:{editName(name){this.name=name},}}接收变量和Binding触发事件//child-bcomponent

Name:{{myName}}

修改名称//child-a组件

name:{{newName}}

即:子组件B通过$emit()触发父组件的事件函数editName时,父组件的变量name的值为改变了,父组件也可以通过props将改变后的值传递给子组件A,从而实现兄弟组件之间的数据传递2.通过一个空vue实例创建一个EventBus.js文件,暴露一个vue实例importVuefrom'Vue'exportdefaultnewVue()在要传递的文件中导入这个空vue实例,绑定事件并通过$emit触发器事件函数(也可以在main.js中全局引入js文件,我一般在需要用到的组件中引入)在接收传值的组件中同样导入vue实例,通过$on监听回调,回调函数接收事件触发时传入的所有参数import{EventBus}from"../EventBus.js"导出default{data(){return{name:''}},created(){EventBus.$on('editName',(name)=>{this.name=name})}}这是通过创建一个空的vue实例的方式相当于创建了一个事件中心或者中转站,用于传递和接收这种接收事件的方式同样适用于任何组件之间的通信,包括父子、兄弟、跨级。对于通信需求简单的项目来说比较方便,但是对于比较复杂的情况,或者项目比较大的时候,可以使用Vue提供更复杂的状态管理模式Vuex来处理。3.使用vuex(省略,开头单独说)4.多层父子组件通信有时候需要通信的两个组件不是直接的父子组件,而是爷孙,或者父子跨越更多层次的组件。在这种情况下,不可能从子组件逐级往上传递参数,尤其是当组件层级很深、嵌套很深时,需要传递的事件和属性非常多,会导致代码非常混乱.这时候就需要用到vue提供的高阶方法:provide/inject。这对选项需要一起使用,才能让一个祖先组件向它的所有子孙组件注入依赖,无论组件层级有多深,只要建立了上下游关系,它就会一直生效。查看官网provide/inject:简单来说就是在父组件中通过provider提供变量,然后在子组件中通过inject注入变量。无论组件层级有多深,在父组件的生命周期内,这个变量都会一直起作用。父组件:exportdefault{provide:{//它的作用是为它所有的子组件提供变量**name**。name:'Jack'}}Subcomponent:exportdefault{inject:['name'],//注入父组件mounted提供的name变量(){console.log(this.name);//Jack}}注意:提供和注入绑定不是响应式的。即父组件名称改变后,子组件不会相应改变。如果要实现provide和inject数据响应,有两种方法:1.提供一个祖先组件的实例,然后在子孙组件中注入依赖,这样就可以直接修改祖先组件实例的属性在后代组件中,但是this方法的缺点是在这个实例上挂载了很多不必要的东西,比如props和methods
后代组件中的值:注意:这种方式在函数式组件中比较常用。函数式组件,即无状态(无响应数据)、无实例化(无this上下文)、内部无生命周期处理方法,因此渲染性能高,更适合依赖于外部数据传输和传输的组件改变。2.使用Vue.observable优化响应式提供。如果我不熟悉它,我不会谈论它。可以查看→官方文档总结一下亲子通信:parent通过props向child传输数据,child通过$emit向parent传输数据;通过$parent/$children沟通;$ref也可以访问组件实例;提供/注入;$attrs/$listeners;兄弟通讯方式:Bus;Vuex跨层通信:Bus;浏览器;提供/注入;$attrs/$listeners;