Vue组件间通信-03

201710day03


一、组件间通信(父组件传值给子组件)(props down)

通常父组件中包含子组件,父组件要正向地向子组件传递数据或者参数,子组件接收后根据参数不同来渲染不同内容或执行不同操作。这个过程用props来从上至下实现,口诀props down。
在子组件中,使用选项props来声明从父级接收的数据,props值可以是两种。一种是字符串数组,一种是对象。

这是第一种方法字符串数组
①父组件在调用子组件传值

<child-component myValue="123" warning-text="警告" :msg="msg"></child-component>

②在子组件中 获取父组件传来的值

Vue.component('child-component', {
  props: ['myValue', 'warningText', 'msg'],
  data: ()=>{
    return {
      value: this.myValue
    }
  },
  template: ''
})

这是第一种方法对象
①父组件在调用子组件传值

<child-component myValue="123" warning-text="警告" :msg="msg"></child-component>

②在子组件中 获取父组件传来的值

Vue.component('child-component', {
  props: {
    myValue: String,
    warningText: Number,
    msg: Object,
  },
  data: () => {
    return {
      value: this.myValue
    }
  },
  template: ''
})

注:
1)由于HTML不区分大小写,当使用DOM模板时,驼峰命名的props名称要改为短横分隔命名
2)接受的数据可以是来自父级的动态数据
3)子组件可以将父组件传递来的初始值保存起来在自己的作用域下随意使用

以下是html文件的简单完整例子

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
</head>
<body>

<div id="container">
    <parent-component></parent-component>
</div>

<script>
    Vue.component('parent-component',{
        data: () {
            return {
                gift:'传家宝'
            }
        },
        template:`
        <div>
            <h1>这是父组件</h1>
            <hr/>
            <child-component :myValue="gift"></child-component>
            <child-component myValue="money"></child-component>
        </div>
        `
    })
    Vue.component('child-component',{
        props:['myValue'],
        template:`
        <div>
            <h1>这是子组件</h1>
            <p>{{"老爹给的礼物:"+myValue}}</p>
        </div>
        `
    })

    new Vue({
        el: '#container',
        data: {
            msg: 'Hello Vue'
        }
    })
</script>

</body>
</html>

但是大多数情况下,我们在进行项目开发时是用vue-cli的方式开发,如果是这样的话,以下给出了完整例子,下面是parentComponent.vue中的代码

<template>
  <div>
    <h1>这是父组件</h1>
    <hr/>
    <child-component :myValue="gift"></child-component>
    <child-component myValue="money"></child-component>
  </div>
</template>

<script>
import childComponent from '../childComponent/childComponent'
export default {
  name: 'parentComponent',
  components: {
    'child-component': childComponent
  },
  data () {
    return {
      gift: '传家宝'
    }
  }
}
</script>

以下是childComponent.vue的代码

<template>
  <div>
    <h1>这是子组件</h1>
    <p>{{"老爹给的礼物:"+myValue}}</p>
  </div>
</template>

<script>
export default {
  name: 'childComponent',
  props: ['myValue'],
  data () {
    return {
    }
  }
}
</script>

执行结果:


练习:登录窗口
创建4个组件,分别是my-label my-input my-button my-login(复合组件)

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title></title>
</head>
<body>

<div id="container">
    <my-login></my-login>
</div>

<script>

    Vue.component('my-label',{
        props:['labelName'],
        template:'<label>{{labelName}}</label>'
    })
    Vue.component('my-input',{
        props:['tips'],
        template:'<input type="text" :placeholder="tips"/>'
    })
    Vue.component('my-button',{
        props:['btnName'],
        template:'<button>{{btnName}}</button>'
    })

    Vue.component('my-login',{
        template:`
        <form>
            <my-label labelName="用户名"></my-label>
            <my-input tips="请输入用户名"></my-input>
            <br/>
            <my-label labelName="密码"></my-label>
            <my-input tips="请输入密码"></my-input>
            <br/>
            <my-button btnName="登录"></my-button>
            <my-button btnName="注册"></my-button>
        </form>
        `
    })


    new Vue({
        el: '#container',
        data: {
            msg: 'Hello Vue'
        }
    })
</script>

</body>
</html>

执行结果:


二、组件间通信(子组件传值给父组件)(events up)

①在父组件中 定义一个方法,用来接收子组件所通过事件传来的值

methods:{
 recvMsg:function(msg){
      //参数msg就是子组件通过事件出来的数据
     }
}

②绑定事件处理函数,事件一般情况 都是自定义事件

<child-component @myEvent="recvMsg"></child-component>

③在子组件触发事件

this.$emit('myEvent',myPhone)
//触发一个叫做myEvent的事件,同时把第二个参数数据传递给事件对应的处理函数

以下是一个完整例子,在子组件中 放上一个input,点击按钮 把用户输入的内容发给父组件

//demo03_child_to_parent.html
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title></title>
</head>
<body>

<div id="container">
    <parent-component></parent-component>
</div>

<script>

    Vue.component('parent-component',{
        data: function () {
          return {
              sonMsg:''
          }
        },
        methods:{
            recvMsg: function (msg) {
                console.log('父组件接收子组件触发的事件了:'+msg);
                this.sonMsg = msg;
            }
        },
        template:`
        <div>
            <h1>这是父组件</h1>
            <p>子组件传来的数据为:{{sonMsg}}</p>
            <hr/>
            <child-component @customEvent="recvMsg">
            </child-component>
        </div>
        `
    })

    Vue.component('child-component',{
        data: function () {
            return {
                myMsg:''
            }
        },
        methods:{
            sendMsgToFather: function () {
                //触发'绑定给子组件的自定义事件'
                this.$emit(
                        'customEvent',
                        this.myMsg
                );
            }
        },
        template:`
        <div>
            <p>这是子组件</p>
            <input type="text" v-model="myMsg"/>
            <br/>
            <button @click="sendMsgToFather">sendToFather</button>
        </div>
        `
    })

    new Vue({
        el: '#container',
        data: {
            msg: 'Hello Vue'
        }
    })
</script>

</body>
</html>

下面是vue-cli的开发方式写的代码parentComponent中的代码

<template>
  <div>
    <h1>这是父组件</h1>
    <p>子组件传来的数据为:{{sonMsg}}</p>
    <hr/>
    <child-component @customEvent="recvMsg"></child-component>
  </div>
</template>
<script>
import childComponent from '../childComponent/childComponent'
export default {
  name: 'parentComponent',
  components: {
    'child-component': childComponent
  },
  data () {
    return {
      sonMsg: ''
    }
  },
  methods: {
    recvMsg: function (msg) {
      console.log('父组件接收子组件触发的事件了:' + msg)
      this.sonMsg = msg
    }
  }
}
</script>

以下是vue-cli开发方式中childComponent中的写法

<template>
  <div>
    <p>这是子组件</p>
    <input type="text" v-model="myMsg" />
    <br/>
    <button @click="sendMsgToFather">sendToFather</button>
  </div>
</template>

<script>
export default {
  name: 'childComponent',
  data () {
    return {
      myMsg: ''
    }
  },
  methods: {
    sendMsgToFather: function () {
    // 触发'绑定给子组件的自定义事件'
      this.$emit('customEvent', this.myMsg);
    }
  }
}
</script>

练习:
有两个组件,分别是main-component,header-component.
main-component是由header-component和一个列表(有5条数据 [100,200,300,400,500]),
header-component是由一个h1的标签:'这是页头',有一个数据isUserLogin:true

在渲染main-component时候,读取header-component在挂载完毕之后通过事件传递来的数据(isUserLogin),根据该数据的真假来决定列表是否显示

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title></title>
</head>
<body>

<div id="container">
    <main-component></main-component>
</div>

<script>

    Vue.component('main-component',{
        data: function () {
            return {
                productList:[100,200,300,400,500],
                isUserLogin:true
            }
        },
        methods:{
            recvUserLogin: function (msg) {
                console.log('接收到事件的值:'+msg)
                this.isUserLogin = msg;
            }
        },
        template:`
        <div>
            <header-component
            @checkUserLoginEvent="recvUserLogin"></header-component>
            <ul v-if="isUserLogin">
                <li v-for="tmp in productList">
                    {{tmp}}
                </li>
            </ul>
        </div>
        `
    })

   //组件的生命周期:create/mount/update/destroy
    Vue.component('header-component',{
        data: function () {
            return {
                isLogin:false
            }
        },
        template:`
            <h1> 这是页头 </h1>
        `,
        mounted: function () {
            //挂载完毕之后 触发自定义事件checkUserLoginEvent
            this.$emit('checkUserLoginEvent',this.isLogin);
        }
    })

    new Vue({
        el: '#container',
        data: {
            msg: 'Hello Vue'
        }
    })
</script>

</body>
</html>

三、组件间通信($parent $refs)

父组件要想获取子组件的数据:

①在调用子组件的时候,指定ref属性

<child-component ref="mySon"></child-component>

②根据指定的引用的名字 找到子组件的实例对象

this.$refs.mySon
子组件要想获取父组件的数据:

①直接读取

this.$parent

以下是一个完整例子,小头爸爸和大头儿子的通信

// demo05_父子组件通信.html
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title></title>
</head>
<body>

<div id="container">
    <xiaotoubaba></xiaotoubaba>
</div>

<script>

    Vue.component('xiaotoubaba',{
        data: function () {
          return {
              money:10000
          }
        },
        methods:{
            getSonMsg: function () {
                //要通过$refs得到指定的引用所对应的组件的实例对象
                console.log(this.$refs.mySon.name);
            }
        },
        template:`
        <div>
            <h1>这是父组件</h1>
            <button @click="getSonMsg">获取子组件的数据</button>
            <hr/>
            <datouerzi ref="mySon"></datouerzi>
        </div>
        `
    })

    Vue.component('datouerzi',{
        data: function () {
            return {
                name:'大头儿子'
            }
        },
        template:`
            <h1>这是子组件</h1>
        `,
        created: function () {
            //在子组件中 获取父组件中的数据
            console.log("子组件拿到的父组件的数据为:"+
            this.$parent.money);
        }
    })

    new Vue({
        el: '#container',
        data: {
            msg: 'Hello Vue'
        }
    })
</script>

</body>
</html>

大头儿子小头爸爸的vue-cli的通信方式,以下是xiaotoubab.vue的代码

<template>
  <div>
    <h1>这是父组件</h1>
    <button @click="getSonMsg">获取子组件的数据</button>
    <hr/>
    <datouerzi ref="mySon"></datouerzi>
  </div>
</template>

<script>
import datouerzi from '../datouerzi/datouerzi'
export default {
  name: 'parentComponent',
  components: {
    'datouerzi': datouerzi
  },
  data () {
    return {
     money:10000
    }
  },
  methods: {
    getSonMsg: function () {
      //要通过$refs得到指定的引用所对应的组件的实例对象
      console.log(this.$refs.mySon.name);
    }
  }
}
</script>

以下是datouerzi的代码

<template>
  <div>
    <h1>这是子组件</h1>
  </div>
</template>

<script>
export default {
  name: 'datouerzi',
  data () {
    return {
      name:'大头儿子'
    }
  },
  created: function () {
    //在子组件中 获取父组件中的数据
    console.log("子组件拿到的父组件的数据为:" +
      this.$parent.money);
  },
}
</script>
<style scoped>
</style>

四、兄弟组件间通信(event)

借助于一个公共的Vue的实例对象,不同的组件可以通过该对象完成事件的绑定和触发

var bus = new Vue();

bus.$emit()
bus.$on()

熊大想要发消息给熊二,接收方(熊二):事件绑定

    bus.$on('customEvent',function(msg){
        //msg就是通过事件 传递来的数据
    })

发送方(熊大):触发事件

    bus.$emit('customEvent',123);

练习:在熊二中 加上一个button,点击按钮时告诉熊大:'快跑!'

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title></title>
</head>
<body>

<div id="container">
    <xiong-da></xiong-da>
    <hr/>
    <xiong-er></xiong-er>
</div>

<script>

    //这是一个对象,兄弟间的通信
    // 要通过它的事件的绑定和触发来实现
    var bus = new Vue();

    Vue.component('xiong-da',{
        methods:{
            sendToXiongEr: function () {
                //给熊二发消息
                bus.$emit('msgToXiongEr','光头强又来偷木头了!');
            }
        },
        template:`
            <div>
                <h1>我是熊大</h1>
                <button @click="sendToXiongEr">clickMe</button>
            </div>
        `,
        mounted: function () {
            //绑定一个自定义的事件 和 对应的处理函数
            bus.$on('msgToXiongDa', function (msg) {
                console.log('熊二传来的数据为'+msg);
            })
        }
        
    })

    Vue.component('xiong-er',{
        methods:{
            sendToXiongDa: function () {
                //触发熊大组件 绑定的事件对应的处理函数
                bus.$emit('msgToXiongDa','快跑!');
            }
        },
        template:`
        <div>
            <h1>我是熊二</h1>
            <button @click="sendToXiongDa">给熊大发消息</button>
        </div>
        `,
        mounted: function () {
            //给该组件 绑定一个自定义事件 和 对应的处理函数
            bus.$on('msgToXiongEr', function (msg) {
                console.log('自定义的事件被触发了,接收到的数据为'+msg);
            })
        }
    })

    new Vue({
        el: '#container',
        data: {
            msg: 'Hello Vue'
        }
    })
</script>

</body>
</html>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Vue组件是Vue的一个重要组成部分,所以掌握Vue组件间的通信是十分重要的,一共分三种情况:父组件向子组件传值、...
    Darsoon阅读 1,137评论 0 0
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 6,646评论 0 6
  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 10,454评论 0 29
  • 组件间通信 父组件与子组件通信: props down 子组件与父组件通信:events up 若父组件要想获取子...
    JSL_FS阅读 3,388评论 0 0
  • 雨娃爸爸是个做事有计划的人,我看书上说,爸爸需要为孩子未来做些规划性的引导。在这方面,爸爸的确做的很好。 雨娃的幼...
    雨娃妈妈阅读 3,408评论 12 4