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>