说明:本篇文章是基于VUE2来进行分享的。
目录
前言:Vue中最常见的组件之间的通信方式有12种,分别为:props、$emit、sync、 v-model、 ref、$children / $parent、$attrs / $listeners、provide / inject、EventBus、 Vuex、 $root、 slot。今天我们会详细讲解父传子props方式和子传父¥emit以及非父子组件传值。
props声明:
父传子的实现方式就是通过props属性,子组件通过props属性接收从父组件传过来的值,而父组件传值的时候使用 v-bind 将子组件中预留的变量名绑定为data里面的数据即可
定义方式:
字符串:
- export default {
- props: ['foo'],
- created() {
- // props 会暴露到 `this` 上
- console.log(this.foo)
- }
- }
对象方式:
- export default {
- props: {
- title: String,
- likes: Number
- }
- }
举例:
父组件:
- <div id="app">
-
- <student id="002" name="李四" sex="男" age="18">student>
-
- <student id="003" name="王五" sex="女">student>
- div>
-
- <script>
-
- import student from "@/components/Student";
-
- export default {
- name: 'App',
- components: {
- student
- }
- }
- script>
子组件:
- <div>
- <h2 >学生ID:{{ id }}h2>
- <h2>学生姓名:{{ name }}h2>
- <h2>学生性别:{{ sex }}h2>
- <h2>学生年龄:{{ age }}h2>
- div>
-
- <script>
-
- export default {
- // eslint-disable-next-line vue/multi-word-component-names
- name: "student",
- data() {
- return {}
- },
- // 声明 接收app传递过来的数据
- props:['id','name','sex','age']
- /*methods:{
- up(){
- this.$props.name = '阿萨德';
- }
- },*/
- // 接收数据的时候限制数据的类型
- // props: {
- // id: String,
- // name: String,
- // sex: String,
- // age: Number
- // }
- // props:{
- // id: {
- // type:String,
- // required:true
- // },
- // name: {
- // type:String,
- // required:true
- // },
- // sex: {
- // type:String,
- // required:true
- // },
- // age: {
- // type:String, // 类型
- // default:'18', // 默认值
- // required:false, // 必要的 true false
- // validator: function (value) { //验证数据
- // return value >= 1;
- // }
- // }
- //
- // }
-
-
-
- }
- script>
-
- <style scoped>
-
- style>
效果图:
原理:所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。另外,每次父组件更新后,所有的子组件中的 props 都会被更新到最新值。(子组件中不能更待props值,会出现报错!)
父组件:
- <div>
-
-
- <Student @zhangsan="getStudentName">Student>
- <hr/>
- <Student ref="student">Student>
- div>
- <script>
- import Student from "@/components/Student";
-
- export default {
- name: 'App',
- data() {
- return {}
- }, components: {
- Student
- }, methods: {
- getStudentName(name) {
- console.log("获取到了学生的的信息" + name)
- }
- },mounted() {
- /* $on(eventName) 监听事件 */
- /* Vue 为每个窗口 都提供了一个 事件接口 Events interface */
- this.$refs.student.$on('zhangsan',this.getStudentName)
-
- }
-
- }
- script>
子组件:
- <div>
- <h2>学生姓名:{{ name }} h2>
- <h2>学生性别:{{ sex }} h2>
- <button @click="sendStudentName">点我传递学生信息button>
- div>
-
- <script>
- export default {
- // eslint-disable-next-line vue/multi-word-component-names
- name: "Student",
- data() {
- return {
- name: '张三',
- sex: '男'
- }
- },methods:{
- sendStudentName(){
- // $emit 触发事件 >>> $emit(eventName)
- this.$emit('zhangsan',this.name);
- // this.$emit('zhangsan',this.name,.,.,.,.,.,.);
-
- }
- }
- }
- script>
-
- <style scoped>
-
- style>
效果图:
兄弟组件之间的数据传递,通过 eventBus 来做中间的桥梁,传输方通过 Bus.$emit('自定义事件名', 数据)传数据,接收方通过 Bus.$on('自定义事件名', callback)接收数据,两者之间的自定义属性名保持一致
传值思想其实是一致的,先使用$on定义一个全局事件,后面写个回调函数,触发这个事件执行的方法,可以接参数bus.$on('msg',val=>{ }),msg就是全局事件,然后在想要获取这个全局事件里面的值就调用他,不过这时候不是 this.emit 而是 bus . emit 而是 bus.emit而是bus.emit
A组件:
- <div>
- A组件:
- <span>{{elementValue}}span>
- <input type="button" value="点击触发" @click="elementByValue">
- div>
- template>
- <script>
- // 引入公共的bug,来做为中间传达的工具
- import Bus from './bus.js'
- export default {
- data () {
- return {
- elementValue: 4
- }
- },
- methods: {
- elementByValue: function () {
- Bus.$emit('val', this.elementValue)
- }
- }
- }
- script>
B组件:
- <div>
- B组件:
- <input type="button" value="点击触发" @click="getData">
- <span>{{name}}span>
- div>
- template>
- <script>
- import Bus from './bus.js'
- export default {
- data () {
- return {
- name: 0
- }
- },
- mounted: function () {
- var vm = this
- // 用$on事件来接收参数
- Bus.$on('val', (data) => {
- console.log(data)
- vm.name = data
- })
- },
- methods: {
- getData: function () {
- this.name++
- }
- }
- }
- script>
组件中可以使用 $parent和 $children获取到父组件实例和子组件实例,进而获取数据$parent 当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
$children 当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。
父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息
最后的最后赋一张借鉴来的图供大家快速记忆: