Vue学习10--父子组件通信

Vue学习10–父子组件通信

父子组件

是指一个A组件把另外一个B组件引入并使用,把A称为父组件,把B称为子组件。

父组件向子组件传数据

使用标签的属性来传递
原理:props

形式:
父组件里: <子组件名 :属性名=“值”>
子组件里:需要在js里用props属性接收父组件传递过来的属性数据

子组件里每个接收的变量的属性:

type:指定数据类型,(Array、Object、String、Number、Boolean)
若类型不匹配也会报错:[Vue warn]: Invalid prop: type check failed for prop “amount”. Expected 期待类型 with value 9908, got 传的类型 with value “9908”.

required:是一个布尔属性,用于指定是否为必传属性
若没传这个必传参数,报错:[Vue warn]: Missing required prop: “amount” (必传参数xxx没有传递)

default:默认值,当指定的数据类型为Array 或者Object 时,default必须使用工厂函数
若Array 或者Object没用工厂函数则报错:[Vue warn]: Invalid default value for prop “item”: Props with type Object/Array must use a factory function to return the default value.

示例:

这是父组件文件

<template>
    <div>
        <ul>
          
            <!-- <item-node v-for="item in list" :name="item.name" :amount="item.amount + ''" :key="item.id"/> -->
            <item-node v-for="item in list" :name="item.name" :amount="item.amount" :key="item.id"/>
            <hr/>
            <!-- <item-node v-for="item in list" :name="item.name" :key="item.id"/> -->
          
            <!-- 如果一个属性没有添加v-bind:指令,表示这个属性的值为字符串 -->
            <!-- [Vue warn]: Invalid prop: type check failed for prop "item". Expected Object, got String with value "". -->
            <!-- <item-node v-for="item in list" :name="item.name" :amount="item.amount" item="" :key="item.id"/> -->
        </ul>
    </div>
</template>

<script>
    import ItemNode from './Item'

    export default {
        components: {
            ItemNode
        },
        data() {
            return {
                list: Array.from(Array(10), (_, i) => ({id: '张三0' + i, name: '张三0' + i, amount: Math.ceil(Math.random() * 5000 + 7000)}) )
            }
        }
    }
</script>

这是子组件文件

<template>
    <li>
        <span>{{name}}</span>
        的工资是:
        <i>{{amount}}</i>
        <!-- <i :class="[{'normal': }]"></i> -->
    </li>
</template>

<script>
    export default {
        // 使用props接收父组件传递过来的属性数据
        props: {
            name: '',
            amount: {
                // 可以定义数据类型
                type: Number,
                // 使用定义当前变量为必传参数
                required: true
            },
            item: {
                type: Object,
                // 设置默认值
                default: function() {
                    return { amount: 10000 }
                }
            }
        }
    }
</script>

<style scoped>
    i {
        font-size: 1.6rem;
        font-style: normal;
    }
    i.normal {
        color: green;
    }
    i.low {
        color: wheat;
    }
    i.high {
        color: red;
    }
</style>

子组件向父组件传数据

它利用事件机制,父组件绑定一个事件,然后子组件在适当的时机触发这个事件,然后把数据通过事件触发传递出去;
原理:$emit

$emit方法接口解析:

emit 触发、发送一个事件 $emit(event: string, …args: any[])

event: string 事件名字
…args: any[]** **传递多个参数 ( any[]定义为一个数组,它的每一个数据项为任意数据类型 => [‘fds’, 1, true, {}, []] )

js的事件只能触发原生的dom 事件,可以添加一个修饰符来指定事件触发的机制 .native

事件的修饰符除了native之外,.stop 阻止冒泡,.prevent 阻止默认事件,.once 只触发一次
注:所有的修饰符只能使用一个,否则会失效

示例:

这是父组件文件

<template>
    <div>
        <ul>
            <!-- click事件只能触发原生的dom click事件,可以添加一个修饰符来指定事件触发的机制 .native --
            <!-- <item-node v-for="item in list" :name="item.name" :amount="item.amount" @click.native.once="testClick" @myClick="testClick" :item="item" :key="item.id"/> -->
            <item-node v-for="item in list" :name="item.name" :amount="item.amount" @click.native="testClick" @myClick="testClick" :item="item" :key="item.id"/>
        </ul>
    </div>
</template>
<script>
    import ItemNode from './Item'
    export default {
        components: {
            ItemNode
        },
        data() {
            return {
               list: Array.from(Array(10), (_, i) => ({id: '张三0' + i, name: '张三0' + i, amount: Math.ceil(Math.random() * 5000 + 7000)}) )
            }
        },
        methods: {
            testClick() {
                console.log(arguments)
            }
        }
    }
</script>

这是子组件文件

<template>
    <li>
        <span>{{name}}</span>
        的工资是:
        <i>{{amount}}</i>
        <i :class="[{'normal': item.amount > 9000 && item.amount < 11000}, {'low': item.amount <= 9000}]" @click.once="clickEvt(item.id)"> -- {{amount}}</i>
    </li>
</template>

<script>
    export default {
        // 使用props接收父组件传递过来的属性数据
        props: {
            name: '',
            // amount: 0
            amount: {
                type: Number,
                required: true
            },
            item: {
                type: Object,
                default: function() {
                    return { amount: 10000 }
                }
            }
        },

        methods: {
            clickEvt(id) {
                // click 自定义事件
                // myClick 自定义事件
                // 如果使用.native 这个事件就不能触发
                this.$emit('click', id, 'fds', 1, true, {}, [])
                this.$emit('myClick', id, 'fds', 1, true, {}, [])
            }
        }
    }
</script>

<style scoped>
    i {
        font-size: 1.6rem;
        font-style: normal;
        cursor: pointer;
    }
    i.normal {
        color: green;
    }
    i.low {
        color: wheat;
    }
    i.high {
        color: red;
    }
</style>

事件捕获有几个阶段?捕获、目标、冒泡三个阶段

数据传值之事件总线

在Vue1.x 版本时候有一个广播对象,可以实现全局的数据传递,在需要传递数据的地方发起一个广播消息,然后在需要使用消息的地方来接消息。

需要先监听,然后在发送

广播机制是基于 事件机制:

以下的 VueInstance 代表Vue实例

触发机制 -> VueInstance.$emit === onclick/onmyclick
监听机制 -> VueInstance.$on === addEventListener

$on方法接口解析:

VueInstance.$on(event :{string | Array}, callback:Function)
监听当前实例上的自定义事件。事件可以由 VueInstance.$emit 触发。

event :事件的名字,String类型的数据或者数组
callback:回调函数 ,会接收所有传入事件触发函数的额外参数(arguments)。

示例:

index.js文件里设置全局监听广播

import Vue from 'vue'
import App from './views'

new Vue({
    // 在全局的地方定义一个vue实例对象变量
    data() {
        return {
            eventBus: new Vue()
        }
    },
    render: ce => ce(App),
    created() {
      // 用全局的vue实例对象来监听一个名字固定的广播,
        this.eventBus.$on('importantMsg', function() {
            console.log(arguments)
        })
    }
}).$mount('#app')

自定义Button组件的文件

<template>
    <button @click="clickEvt">
        {{text}}
    </button>
</template>

<script>
    export default {
        props: {
            text: {
                type: String,
                required: true
            }
        },
        methods: {
            clickEvt() {
                // 先获取index.js vue实例对象中的eventBus对象,用来发送全局广播
                // console.log(this)
                this.$root.eventBus.$emit('importantMsg', 'haha', 123)
            }
        }
    }
</script>

这个Button组件不管放在哪个组件或者页面里,都可以发送全局广播

在vue2.x有一个全局 **事件总线 **机制可以实现vue1.x的事件广播机制

事件总线问题:
全局,性能不好,全局事件污染。
必须要先监听。
广播出去的数据不会有缓存,一旦完成事件触发,数据没有接收到,就永远丢失。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值