Vue组件之间如何进行通信

vue组件之间的传值大致分为三种:父组件给子组件传值,子组件给父组件传值,兄弟组件之间传值
vue组件之间简单的数据传递,如果组件之间传递的数据比较复杂,建议使用vue的状态管理模式 vuex

父组件给子组件传值

1.父组件通过props给子组件传值
props 就是父组件给子组件标签上定义的属性,用来接收父组件传递的数据,props 的值可以是字符串数组,也可以是各自的名称和类型,用法和 data 中的数据用法一样,在子组件中只能使用该值,不能修改

2.父组件通过$ref给子组件传值
ref 用于给元素或子组件注册引用信息,引用信息将会注册在父组件的 refs 对象上,父组件通过refs对象上,父组件通过ref 获取到在子组件里定义的属性和方法,通过调用方法给子组件传递数据

3.父组件通过$children给子组件传值

children为当前组件的直接子组件,是一个无序的数组,父组件通过 children 访问子组件并传递数据,$ children 并不保证顺序,也不是响应式的,如果能清楚的知道子组件的顺序,可以使用下标来操作对应的子组件

4.父组件通过provide/inject给子孙组件传值
provide/inject 组合以允许一个祖先组件向其所有子孙后代组件注入一个依赖(属性和方法),不论组件层次有多深,并在其上下游关系成立的时间里始终生效,从而实现跨级父子组件通信,主要在开发高阶插件/组件库时使用

props和 r e f 和 ref和 refchildren和provide/inject的主要区别:

1.props 侧重于数据的传递,并不能获取子组件里的属性和方法,适用于自定义内容的使用场景

2.$ref 侧重于获取子组件里的属性和方法,并不是太适合传递数据,并且 ref 常用于获取dom元素,起到选择器的作用

3.$children 侧重于获取所有的直接子组件,得到的是一个无序的数组,并不太适合向多个子组件传递数据
4.provide/inject 侧重于在开发高阶插件/组件库时使用,并不推荐用于普通应用程序代码中

子组件给父组件传值
1.子组件通过触发$emit事件给父组件传值
$emit 的第一个参数为自定义的事件,第二个参数为要传递给父组件的值,父组件在子组件标签上绑定自定义事件来接收子组件传递的数据

2.子组件通过$parent给父组件传值
$parent 可以用来从一个子组件访问父组件并传递数据

兄弟组件之间传值
兄弟之间传值通过eventBus
eventBus 就是一个vue实例来作为全局的事件总线,兄弟组件之间通过 eventBus. on 和 eventBus.on和eventBus.emit 注册触发事件来传递数据

(1)props / $emit 适用 父子组件通信

(2)ref 与 $parent / $children 适用 父子组件通信
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
$parent / $children:访问父 / 子实例

(3)EventBus ($emit / $on) 适用于 父子、隔代、兄弟组件通信
这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。

(4)$attrs/$listeners 适用于 隔代组件通信

$attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。
当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),

并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。

l i s t e n e r s : 包 含 了 父 作 用 域 中 的 ( 不 含 . n a t i v e 修 饰 器 的 ) v − o n 事 件 监 听 器 。 它 可 以 通 过 v − o n = " listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=" listeners(.native)vonvon="listeners" 传入内部组件

(5)provide / inject 适用于 隔代组件通信
祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。

(6)Vuex 适用于 父子、隔代、兄弟组件通信
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。

props$emit + v-on

通过 props 将数据在组件树中进行⾃上⽽下的传递;

通过 $emitv-on 来作信息的向上传递。

EventBus

可通过 EventBus 进⾏信息的发布与订阅。

Vuex

全局状态管理库。可通过它来进行全局数据流的管理。

常规使用
{
state:{userInfo:""}     // this.$store.state.userInfo
mutations:{
   // this.$store.commit("setUserInfo",参数值)
   setUserInfo(state,value){
      state.userInfo=value
      this.commit('setXxx',value值)
   },
   setXxx(state,value){
   state.userInfo=value
   }
},
actions:{
    // 调用actions方法  this.$store.dispatch("refreshUserInfo",参数值)
    refreshUserInfo(store,value){
        setTimeout(()=>{
       // 通过actions调用mutations     
         store.commit("setUserInfo",参数值)   
        },2000)
    }
}
    // 常规结合map使用
    import {mapState,mapMutations} from 'vuex'
    computed:{
        ...mapState(["userInfo"])
         ...mapState({
             userInfoxxx:'userInfo'
         })
    },
        methods:{
            // actions与mutations一样的  
            ...mapMutations(['setUserInfo]),
         ...mapState({
             setUserInfoxxx:'setUserInfo'
         })
        }
}

// 模块化的使用
import login from 'login地址'
import my from 'my地址'
{
    modules:{
        login,
        my
    }
}


// login
export default {
    namespaced:true,  // 命名空间
    // state加不加namespaced都一样
    // state使用:this.$store.state.模块名(login).属性名(loginState)
    state:{
        loginState:false
    },
    // mutations如果不加namespaced和常规使用一样的  this.$store.commit('方法名',参数值)
    // mutations加namespaced    this.$store.commit('模块名/方法名',参数值)
    
    mutations:{
        setLoginState(state,value){
            state.loginState=value
            // mutations调用其它模块的mutations方法   this.commit("模块名(有命名空间就加)/方法名",参数,{root:true})
        }
    },
    actions:{
     // actions如果不加namespaced和常规使用一样的  this.$store.dispatch('方法名',参数值)
    // actions加namespaced    this.$store.dispatc('模块名/方法名',参数值)
        refreshLoginState(store,value){
            setTimeout(()=>{                
     // actions调用其它模块的actions方法   store.dispatch("模块名(有命名空间就加)/方法名",参数,{root:true})
    // actions调用其它模块的mutations方法   store.commit("模块名(有命名空间就加)/方法名",参数,{root:true})
            store.commit("setLoginState",true) 
            },2000)
        }
    }
}
// 模块化命名空间结合map使用
import {mapState,mapMutations,mapActions} from 'vuex'
computed:{
    ...mapState("有命名空间就加",["属性名"]),    // 使用  this.属性名
},
    methods:{
        ...mapMutations("有命名空间就加",['方法名'])   // 使用  this.方法名(参数值)
        ...mapMutations(['有命名空间就加/方法名'])   // 使用  this['有命名空间就加/方法名'](参数值)
        ...mapActions("有命名空间就加",['方法名'])   // 使用  this.方法名(参数值)
        ...mapActions(['有命名空间就加/方法名'])   // 使用  this['有命名空间就加/方法名'](参数值)
    }

$attrs$listeners

在 Vue 2.4 版本中加⼊的 $attrs$listeners 可以用来作为跨级组件之间的通信机制。

provideinject

传: provide(){
    return {
       abc:this[data属性与methods方法]
    }
  },
收:
   inject:["abc(属性名)"],
   inject:{
   cde:{
   from:"abc",
   default默认值(和props定义默认值一样,区分原始值与引用值)
   }
   }

一般只用于高阶组件向低阶组件传值,provide它的属性值不能直接调用

由于 provideinject 可以允许⼀个祖先组件向它的所有⼦孙组件注⼊⼀个依赖(不论组件层次有多深),并在其上下游关系成⽴的时间⾥始终⽣效,因此这种机制也就成为了一种跨组件通信的手段。

父子组件怎么传值

父组件向子组件传值
父组件在使用子组件的时候绑定一个自定义属性,属性值就是父组件的传递给子组件数据。子组件在通过props接收

子组件传给父组件
子组件通过this.$emit(“自定义事件名”,数据)给父组件传值,父组件通过这个自定义事件来接收参数

兄弟组件之间的传参 通过evenbus

父组件向子组件传值
1)子组件在props中创建一个属性,用来接收父组件传过来的值;
2)在父组件中注册子组件;
3)在子组件标签中添加子组件props中创建的属性;
4)把需要传给子组件的值赋给该属性

子组件向父组件传值
1)子组件中需要以某种方式(如点击事件)的方法来触发一个自定义
的事件;
2)将需要传的值作为$emit的第二个参数,该值将作为实参传给响应事
件的方法;
3)在父组件中注册子组件并在子组件标签上绑定自定义事件的监听。

VUE自定义组件的步骤
第一步:在components目录新建你的组件文件(indexPage.vue),script一定
要export default {}
第 二 步 : 在 需 要 用 的 页 面 ( 组 件 ) 中 导 入 : import indexPage from
‘@/components/indexPage.vue’
第三步:注入到vue的子组件的components属性上面,components:{indexPage}
第四步:在template视图view中使用
例如有indexPage命名,使用的时候则index-page

封装 vue 组件的过程
使用Vue.extend 方法创建一个组件,然后使用 Vue.component 方法注册组件。子组件需要数据,可
以在 props 中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit 方法、

VUE父子组件之间如何实现数据双向绑定
vm. e m i t 这 种 方 式 是 最 常 见 , 也 是 最 简 单 的 。 子 组 件 通 过 emit 这种方式是最常见,也是最简单的。子组件通过 emitemit函数触发一个方法给父组件,附加上回传的值。父组件做该方法监听即可得到子组件回传的值。
$emit方法 优点:简单易懂
缺点:代码多,需要父组件做方法绑定并监听
v-model指令
优点:父组件只要绑定一个变量即可
缺点:需要理解v-model的原理

v-model
在vue中,v-model是用来进行数据双向绑定的一个语法糖,比如说用在input上,输入框数据变化,v-model绑定的对应的值也会跟着变化,无需单独获取。
其实v-model还可以在自定义组件中使用,可以被拆解为props:value和event:input,也就是说组件必须接收一个value值以及名为input的自定义事件,就可以在自定义组件上使用v-model了。

你可能感兴趣的:(js)