组件之间的通信

组件之间的通信

props emit

问题:为什么组件里面的data选项是一个函数?

内部必须是一个函数返回对象的形式,这样的话就可以保证每一个组件里面用到的数据都是唯一的了。

一个组件的data必须是一个函数,因此可以让每个实例维护一份被返回对象的独立的拷贝

父子通信

父组件给子组件传递数据的时候,子组件需要利用props的属性来确定自己的预期数据

  • 中间有 - 需要写出驼峰的形式来接收
  • 如果子组件没有通过props属性接受传递过来的数据,则数据会以自定义属性的方式,放在子组件最外层的根元素上面**
<body>
    <div id="app">
        <father></father>
    </div>
   
      <!--父组件创建 -->
    <template id="father">
        <div>
            <p>父组件</p>
            <p>{{msg}}</p>
            <!--1.父组件调用子组件的时候,给子组件以绑定属性的方式传递-->
            <son :msg="msg"></son>
        </div>
    </template>

     <!-- 子组件创建-->
    <template id="son">
        <div>
            <p>子组件</p>
            <!-- 子组件,如何获取父组件的msg数据 -->
            <p>{{msg}}</p>
        </div>
    </template>
</body>
<script>
    Vue.component("father", {
        template: "#father",
        data() {
            return {
                msg: "父组件的内容"
            }
        },
        components:{
            son:{
                // 2.需要通过props属性来接收后使用
                props: ["msg"],
                template: "#son",
            }
        }
    })
    new Vue({
        el: "#app",
    })
</script>

子父通信

如下实例:父组件获取子组件的数据

通过属性绑定传递给子组件
<body>
    <div id="app">
        <father></father>
    </div>
    <!--父组件创建-->
    <template id="father">
        <div>
            <p>父组件 {{msg}}</p>
             <!--3.将更改自身数据的方法通过属性方式传递给子组件-->
            <son :Schange="change"></son>
        </div>
    </template>
    <!--子组件创建-->
    <template id="son">
        <div>
            <p>子组件{{Smsg}}</p>
            <p><button @click="say">点击</button></p>
        </div>
    </template>
</body>
<script>
    Vue.component("father", {
        template: "#father",
        data() {
            return {
                msg: "" // 1.父组件声明一条数据用来接收数据
            }
        },
        methods: {
            change(val){  //2.父组件需要写一个更改自身数据的方法
                this.msg=val  //6.父组件接收到子组件传递过来的数据,赋值给父组件的msg
            }
        }
    })
    Vue.component("son", {
        template: "#son",
        props: ["Schange"], // 4.子组件需要通过props来接受父组件传递来的属性
        data() {
            return {
                Smsg: "子组件的数据"
            }
        },
        methods:{
            say(){
            this.Schange(this.Smsg) // 5.在子组件中声明一个方法,当点击按钮的时候,执行此方法,把子组件的msg作为实参传给Schange
            }
        }
    })
    new Vue({
        el: "#app",
    })
</script>
通过自定义事件
<body>
    <div id="app">
        <father></father>
    </div>
    <template id="father">
        <div>
            <p>父组件 {{msg}}</p>
             <!--3.给子组件绑定一个自定义事件  @自定义事件名=父组件处理函数-->
            <son @schange="change"></son>
        </div>
    </template>
    <template id="son">
        <div>
            <p>子组件{{Smsg}}</p>
            <p><button @click="say">点击</button></p>
        </div>
    </template>
</body>
<script>
    Vue.component("father", {
        template: "#father",
        data() {
            return {
                msg: ""  1.父组件声明一条数据用来接收数据
            }
        },
        methods: {
            change(val){  //2.父组件需要写一个更改自身数据的方法
                this.msg=val
            }
        }
    })
    Vue.component("son", {
        template: "#son",
        data() {
            return {
                Smsg: "子组件的数据"
            }
        },
        methods:{
            say(){
                //4. 需要触发绑定在自身上面的change事件  <son @change="change"></son>
                // 通过this.$emit方法就可以触发@后面的自定义事件,第二个参数就是可以传递参数过去
            this.$emit("schange",this.Smsg)
            }
        }
    })
    new Vue({
        el: "#app",

    })
</script>

兄弟通信

组件间不仅可以用过$root/$parent/$children来获取对应关系的组件,

父组件还可以主动的通过ref为子组件做标记 也可以给dom做标记

也会形成ref链,也可以交互,

- viewmodel+ref链
<body>
    <div id="app">
        <sister></sister>
        <brother ref="bro"></brother>
    </div>
    <template id="sister">
        <div>
            <p>姐姐</p>
            <!--当点击hit时,让弟弟哭的行为显示出来-->
            <p><button @click="hit">点击</button></p>
        </div>
    </template>
    <template id="brother">
        <div>
            <p ref="style">弟弟</p>
            <p v-show="isShow">{{action}}</p>
        </div>
    </template>
</body>
<script>
    Vue.component("sister", {
        template: "#sister",
        data () {
            return {
                si:"姐姐"
            }
        },
        methods: {
            hit(){
                // 关系链
                // this.$parent.$children[1].isShow=true;
                // ref链
                this.$parent.$refs.bro.isShow=true;
                this.$parent.$refs.bro.$refs.style.style.color= "red"
            }
        }
    })
    Vue.component("brother", {
        template: "#brother",
        data () {
            return {
                isShow:false,
                bro:"弟弟",
                action:"哭"
            }
        }
    })
    new Vue({
        el: "#app",      
    })
</script>
event bus事件总线

angle.$on(事件名,执行的回调函数) angle.$emit(事件名,参数)

<body>
    <div id="app">
        <sister></sister>
        <brother ref="bro"></brother>
    </div>
    <template id="sister">
        <div>
            <p>姐姐</p>
            <p><button @click="hit">点击</button></p>
        </div>
    </template>
    <template id="brother">
        <div>
            <p ref="style">弟弟</p>
            <p v-show="isShow">{{action}}</p>
        </div>
    </template>
</body>
<script>
    let cry = new Vue() //1.创建了一个公共的vue的实例对象
    Vue.component("sister", {
        template: "#sister",
        data () {
            return {
                si:"姐姐"
            }
        },
        methods: {
            hit(){
                 //3.触发绑定的自定义事件
              cry.$emit("crying")  
            }
        }
    })
    Vue.component("brother", {
        template: "#brother",
        mounted () {
            //2.需要绑定一个事件,等待触发
          cry.$on("crying",this.crying)  
        },
        methods:{
            crying(){
                this.isShow = true
            }
        },
        data () {
            return {
                isShow:false,
                bro:"弟弟",
                action:"哭"
            }
        }
    })
    new Vue({
        el: "#app", 
    })
</script>
请用今天的努力,让明天没有遗憾。
原文地址:https://www.cnblogs.com/cupid10/p/15617697.html