4.vue组件通信

梁柱 2020-04-01 01:50:13
原文地址:https://segmentfault.com/a/1190000021906516

1. 父组件给子组件传值

父组件给子组件通信的步骤:

1.父组件调用子组件的时候绑定动态属性。

<v-header :title="title"></v-header>

2、在子组件里面通过props接收父组件传过来的数据。

//两种方式
props:['title']

props:{
    'title':String      
}

父组件给子组件通信的形式:

  1. 父组件给子组件传值。
  2. 父组件给子组件传方法。
  3. 父组件把整个实例传给子组件。

注意:

  1. 不要使得父子组件中的属性/方法重复了。当重复时,会使用父组件的属性/方法。
  2. prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。

示例:

> Home.vue(父组件)

<template>
    <div>
        <p class="first">我是Home组件:{{msg}}</p>
        <hr>
        <v-info v-bind:homeTitle="title" :homeRun="run" :homeThis="this"></v-info>
    </div>
</template>

<script>
    import Info from "./Info";

    export default {
        name: "Home",
        components: {
            "v-info": Info,
        },
        data() {
            return {
                msg: "我是Home组件",
                title: "首页"
            }
        },
        methods: {
            run: function (data) {
                alert("这是Home组件的方法" + data);
            }
        },

    }
</script>

<style scoped>
    p {
        color: #42b983;
    }
</style>

> Info.vue(子组件)

<template>
    <div id="info">
        <p>我是Home的子组件info</p>
        <button @click="getTitle">获取父组件的title</button>
        <button @click="getParentRun(123)">调用父组件的run方法</button>
        <button @click="getHome">父组件通过this把整个实例传给子组件</button>
    </div>
</template>

<script>
    export default {
        name: "Info",
        data() {
            return {

            }
        },
        methods: {
            getTitle: function () {
                alert(this.homeTitle);
            },
            getHome: function () {
                alert(this.homeThis.msg);
            },
            getParentRun: function (data) {
                this.homeRun(data);
            }
        },
        props: {
            "homeTitle": {
                type: String,
                required: true,
                default: "HomeA"
            },
            "homeRun": {
                type: Function,
                required: true,
            },
            "homeThis": {
                type: Object,
                required: true,
            },
        }
        //props: ["homeTitle", "homeRun", "homeThis"],
    }
</script>

Prop 验证

组件可以为 props 指定验证要求。
为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。
例如:

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
type 可以是下面原生构造器:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

type 也可以是一个自定义构造器,使用 instanceof 检测。

2.父子组件主动通信

父组件主动获取子组件的数据和方法:

1.调用子组件的时候定义一个ref

<v-header ref="header"></v-header>

2.在父组件里面通过

this.$refs.header.属性
this.$refs.header.方法

备注:在任一组件中,通过设置 ref 的方法可以获取该标签的DOM节点。

子组件主动获取父组件的数据和方法:

this.$parent.数据
this.$parent.方法

示例:

> Home.vue

<template>
    <div>
        <p class="first">我是Home组件:{{msg}}</p>
        <button @click="getChildMsg">获取子组件Info的msg</button>
        <button @click="getChildRun">获取子组件Info的run()</button>
        <hr>
        <v-info ref="info" v-bind:homeTitle="title" :homeRun="run" :homeThis="this"></v-info>
    </div>
</template>

<script>
    import Info from "./Info";

    export default {
        name: "Home",
        components: {
            "v-info": Info,
        },
        data() {
            return {
                msg: "我是Home组件",
                title: "首页",
                color: "red",
            }
        },
        methods: {
            run: function (data) {
                alert("这是Home组件的方法" + data);
            },
            getChildMsg: function () {
                alert(this.$refs.info.msg);
            },
            getChildRun: function () {
                this.$refs.info.run();
            }
        },

    }
</script>

> Info.vue

<template>
    <div id="info">
        <p>我是Home的子组件info</p>
        <button @click="autoGetParent">子组件主动获取父组件的数据和方法</button>
    </div>
</template>

<script>
    export default {
        name: "Info",
        data() {
            return {
                msg:"我是Home的子组件info",
            }
        },
        methods: {
            run:function(){
                alert("我是子组件info的方法");
            },
            autoGetParent:function(){
                alert(this.$parent.color);
                this.$parent.run('123');
            }
        },
    }
</script>

非父子组件传值

> 使用 \$on(eventName) 监听事件
> 使用 \$emit(eventName) 触发事件

1、新建一个js文件,然后引入vue,实例化vue,最后暴露这个实例。

> VueEvent.js

import Vue from "vue";

const VueEvent = new Vue();
export default VueEvent;

2、在要广播的文件中引入刚才定义的实例。并在 methods:{}中,通过 VueEmit.$emit('名称','数据') 进行广播。
3、在接收收数据的文件mounted(){}中通过 VueEmit.$on('名称',function(){}) 接收广播的数据。

> Home.vue

<template>
    <div>
        <p>我是Home组件</p>
        <button @click="emitNews">点击给News传消息</button>
    </div>
</template>

<script>
    import VueEvent from "../../model/VueEvent"

    export default {
        name: "Home",
        data() {
            return {
                msg: "我是Home组件",
            }
        },
        methods: {
            emitNews: function () {
                VueEvent.$emit("to-news", this.msg);
            }
        },
        mounted() {
            VueEvent.$on("to-home", (data) => {
                alert(data);
            })
        }
    }
</script>

News.vue

<template>
    <div id="news">
        <p>我是新闻组件</p>
        <button @click="emitHome">点击给home传消息</button>
    </div>
</template>

<script>
    //引入vue实例
    import VueEvent from "../../model/VueEvent"
    export default {
        name: "News",
        data(){
            return {
                msg:"我是新闻组件"
            }
        },
        methods:{
            emitHome:function(){
                VueEvent.$emit("to-home",this.msg);
            }
        },
        mounted() {
            VueEvent.$on("to-news",(data)=>{
                alert(data);
            })
        }
    }
</script>

声明:该文章系转载,转载该文章的目的在于更广泛的传递信息,并不代表本网站赞同其观点,文章内容仅供参考。

本站是一个个人学习和交流平台,网站上部分文章为网站管理员和网友从相关媒体转载而来,并不用于任何商业目的,内容为作者个人观点, 并不代表本网站赞同其观点和对其真实性负责。

我们已经尽可能的对作者和来源进行了通告,但是可能由于能力有限或疏忽,导致作者和来源有误,亦可能您并不期望您的作品在我们的网站上发布。我们为这些问题向您致歉,如果您在我站上发现此类问题,请及时联系我们,我们将根据您的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。