Vue组件通讯全记录

Vue Component 相比React受控组件的概念,Vue组件之间的“通讯”特征则表现的更强。javascript

这种“通讯”特性表如今,组件内部拥有一套本身的状态管理,对外只表现为信息的传递,而不须要外部组件特地作出什么行为(例如受控组件的状态彻底是由控制者决定,受控组件状态的改变必需要求控制者作出响应的行为)vue

除了常见的父子级别通讯,还有兄弟级、跨级,到总线和Vuex。不得不说Vue组件通讯的方式要更丰富一些。java

父组件给子组件传消息

1. 属性props

 最基础的父传子手段。vuex

// child指定props
export default {
  props: {
    msg: String
  }
}

// parent传递消息
<child msg='msg' />
复制代码

2. 引用refchildren

直接获取子组件引用来设置子组件的内部值。children是一个数组,装着全部自定义子组件,但多个子组件状况下排列不能保证顺序。因此更可靠的仍是子组件制定ref,父组件使用$refs获取子组件引用。数组

// child
export default {
  data() {
    return {
      // parent msg by $refs
      // or
      // parent msg by $children
      current: ''
    }
  }
}

// parent
<child ref="child">
export default {
  methods: {
    handleChange1() {
      this.$refs.child.current = 'parent msg by $refs'
    },
    handleChange2() {
      this.$children[0].current = 'parent msg by $children'
    }
  },
  mounted() {
    // this.handleChange1()
    // or
    // this.handleChange2() 
  }
}
复制代码

子组件给父组件传消息

1. 自定义事件

最核心的向上传递消息的手段markdown

// child
<button @click="sendMsg" />
export default {
  methods: {
    sendMsg() {
      this.$emit('sendMsg', { msg: 'msg' })
    }
  }
}

// parent
<child @send-msg="receiveMsg" />
export default {
  methods: {
    receiveMsg(param) {
      console.log(param) // { msg: 'msg' } 
    }
  }
}
复制代码

v-model.sync的本质也是props➕自定义事件的组合数据结构

祖先组件给后代组件传消息

1. 特性$attr

传递那些子组件没有设定在props里面的值,一般在子组件中使用inheritAttrs: false来取消非props值在根组件上的继承。不过$attrs特殊的是,能够在“族谱”中一直向后传递信息:每一个成员使用v-bind="$attrs"均可以将祖先的非props属性传递下去。ide

// grandson
export default {
 mounted() {
   console.log(this.$attrs.attr) // attr
 }
}

// child
<grandson v-bing="$attrs" />
export default {
  props: {
    msg: String
  },
  mounted() {
    console.log(this.msg, this.$attrs.attr) // props, attr
  }
}

// parent传递props消息和attrs消息
<child msg="prop" attr="attr" />
复制代码

2. 提供和注入provide/inject

一个祖先向全部后代提供消息的手段,没必要由每一代传递消息oop

// grandson
export default {
  inject: ['msg'],
  mounted() {
    console.log(this.msg) // 'msg'
  }
}

// child
<grandson />

// parent
<child />
export default {
  provide() {
    return {
      msg: 'msg'
    }
  }
}
复制代码

后代组件给祖先组件传消息

1. 监听器$listeners

$listeners能够一直向后传递事件(普通事件和自定义事件),由某一后代触发事件,实现向祖先传递消息ui

// grandson
<button @click="sendMsg">触发祖先的自定义事件</button>
export default {
  methods: {
    sendMsg() {
      this.$listeners['on-send']({ grandson: 'grandson' })
    }
  }
}

// child
<grandson v-on="$listeners"/>

// parent
<child @on-send="receiveMsg" />
export default {
  methods: {
    receiveMsg(param) {
      console.log(param) // { grandson: 'grandson' }
    }
  }
}
复制代码

兄弟组件传消息

1. 借助共同父代或祖先

// brother-send
export default {
  mounted() {
    this.$parent.$emit('parent-msg', { msg: 'msg by parent' })
    this.$root.$emit('root-msg', { msg: 'msg by root' })
  }
}

// brother-receive
export default {
  created() {
    this.$parent.$on('parent-msg', (param) => {
      console.log(param) // { msg: 'msg by parent' }
    })
    this.$root.$on('root-msg', (param) => {
      console.log(param) // { msg: 'msg by root' }
    })
  },
  destroyed() {
    this.$parent.$off('parent-msg')
    this.$root.$off('root-msg')
  }
}

// parent
<div>
  <brother-send />
  <brother-receive />
</div>
复制代码

无规律跨级通讯

1. 事件总线Bus

能够直接借助一个空Vue对象,自带$on $emit $off的API

// bus.js
export default new Vue()
复制代码

也能够本身构造

// bus.js
class Bus {
  constructor() {
    this.callbacks = {}
  }
  $on(name, fn) {
    this.callbacks[name] = this.callbacks[name] || []
    this.callbacks[name].push(fn)
  }
  $emit(name, ...args) {
    if (this.callbacks[name]) {
      this.callbacks[name].forEach(cb => cb(...args))
    }
  }
  $off(name) {
    this.callbacks[name] = null
    Reflect.deleteProperty(this.callbacks, name)
  }
}
export default new Bus()
复制代码

状态管理

Vuex

Vuex能解决全部组件之间的通讯问题,但实际上Vuex更像是一个状态管理的“库”。Vuex相对比较重,可是能保存全部须要的数据结构,而且全部组件均可以访问到。是否使用Vuex仍是取决于项目规模,或者说是数据规模。

相关文章
相关标签/搜索