1.1.1 父组件向子组件传值
-
父组件发送的形式 是以属性的形式 绑定值 到子组件身上。
-
然后子组件用属性props接收
-
在props中使用驼峰形式,模板中需要使用短横线的形式 。字符串形式的模板中 没有这个限制。
代码演示:
<div id="app">
<!-- 传值有两种方式,分别是静态传值,和动态传值 -->
<!-- 静态传值,在父组件视图层上写死一个数据 -->
<menu-item title="xiaoyu"></menu-item>
<br><br>
<!-- 动态传值,从父组件取数据,渲染到父组件自己的视图层,然后再将这个数据,传递给子组件 -->
<menu-item v-bind:title="ptitle" :content="pcontent" :subtitle="psubtitle">
<script src="./js/vue.js"></script>
<script>
//父组件向子组件传值
//全局(子)组件
Vue.component('menu-item',{
props:['title','content','subtitle'],
template:`#menu-item`,
data(){
return{
msg:'我是子组件中的msg'
}
},
mounted(){
console.log(this.title)
}
})
//根组件(父组件)
var vm=new Vue({
//模板选择器
el:'#app',
//数据中心
data(){
return{
ptitle:'亿缕阳光丨以爱报答爱',
pcontent:'善良的爱有千万种,最让人惊喜的便是以爱报答爱。',
psubtitle:'善良的爱有千万种'
}
},
methods:{
}
})
</script>
预览:
1.1.2 props命名规则
-
在props中使用驼峰形式,模板中需要使用短横线的形式
-
字符串的模板中没有这个限制
代码演示:
<div id="app">
<menu-item :mmsg="pmsg" :mnum="pnum" :marr="parr" :mobj="pobj" :mname="pobj.name" :mage="pobj.age"></menu-item>
<br><br>
</div>
<template id="menu-item">
<div>
<h1>{{msg}}</h1>
<hr>
<h1>
我接收到父组件的数据如下所示
</h1>
<h1>{{mmsg}}</h1>
<h1>{{mnum}}</h1>
<div>
<ul>
<li v-for="item in marr">{{item}}</li>
</ul>
</div>
<h1>{{mobj.name}}----{{mobj.age}}</h1>
<h1>{{mname}}</h1>
<h1>{{mage}}</h1>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
//父组件向子组件传值
//全局组件
Vue.component('menu-item',{
// 父组件向子组件传值-props属性值类型
props:['mmsg','mnum','marr','mobj','mname','mage'],
template:`#menu-item`,
data(){
return{
msg:'我是子组件中的msg'
}
},
mounted(){
}
})
//根组件(父组件)
var vm=new Vue({
//模板选择器
el:'#app',
//数据中心
data(){
return{
pmsg:'xiaoyu',
pnum:100,
parr:['apple','orange','banana'],
pobj:{
name:'hx',
age:20
}
}
},
methods:{
}
})
</script>
预览:
1.1.3 props属性值类型
props属性上定义的变量,可以接收到的数据的数据类型可以是:
-
字符串 String
-
数值 Number
-
布尔值 Boolean
-
数组 Array
-
对象 Object
props自定义属性,申明属性类型的写法:
代码演示:
<div id="app">
<menu-item :mage="age" :mtitle="title" :mlist="list"></menu-item>
</div>
<template id="menu-item">
<div>
<h1>
{{mage}}
</h1>
<h1>
{{mtitle}}
</h1>
<ul>
<li v-for="item in mlist">
{{item}}
</li>
</ul>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
//父组件向子组件传值
//全局组件
Vue.component('menu-item',{
// 父组件向子组件传值-props属性值类型
//声明属性,同时告知父组件属性数据类型
// props:{
// mage:Number,
// mtitle:String,
// mlist:Array,
// },
props:{
mage:{type:Number},
mtitle:{type:String},
mlist:{type:Array},
},
template:`#menu-item`,
data(){
return{
msg:'我是子组件中的msg'
}
},
mounted(){
}
})
//根组件(父组件)
var vm=new Vue({
//模板选择器
el:'#app',
//数据中心
data(){
return{
title:'小余你好',
age:20,
list:[100,200,300,400,500]
}
},
methods:{
}
})
</script>
预览:
1.1.4 子组件向父组件传值
-
子组件用
$emit()
触发事件 --- @click='$emit("enlarge-text", 5)' 你只要 单击click按钮,这个$emit()事件处理函数就被触发调用执行了。 -
$emit('','')
第一个参数为 自定义的事件名称 第二个参数为需要传递的数据 -
父组件用v-on 监听子组件的事件
代码演示:
<div id="app">
<h1 :style="{'font-size':fontSize+'px'}">
{{pmsg}}
</h1>
<menu-item @big="handle"></menu-item>
</div>
<template id="menu-item">
<div>
<h1>{{msg}}</h1>
<button @click="$emit('big',5)">扩大父组件中字体大小</button>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
//子组件向父组件传值
//全局组件
Vue.component('menu-item',{
template:`#menu-item`,
data(){
return{
msg:'我是子组件中的msg'
}
},
mounted(){
}
})
//根组件(父组件)
var vm=new Vue({
//模板选择器
el:'#app',
//数据中心
data(){
return{
pmsg:'小马过河',
fontSize:20
}
},
methods:{
handle(val){
console.log('子组件传递过来的值是:'+val);
this.fontSize=this.fontSize+val
}
}
})
</script>
预览:
注意:
在父子组件 通过 自定义事件 进行通信时,表示从子组件中传递出来的参数值。此时,$event的值就是5或者10(子组件传递过来的值),而不是前面的事件对象。
methods:{
handle(event){
//event从子组件中传递出来的参数值
console.log(event);
// //扩大字体大小
// this.fontSize = this.fontSize + event;
}
}
或者
methods:{
handle($event){
console.log($event);
// //扩大字体大小
this.fontSize = this.fontSize + $event;
}
}
1.1.5 兄弟之间的数据传递
兄弟组件之间的通信,我们又叫 非父子组件间通信 ,
又叫 中央事件总线(非父子组件间通信)。
-
兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据
-
提供事件中心 var hub = new Vue()
-
-
传递数据方,通过一个事件触发hub.$emit('自定义事件名',传递的数据)
-
接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
-
销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
代码演示:
一个组件向另一个组件 传递数据 (单向传递数据)
<div id="app">
<menu-list></menu-list>
<menu-item></menu-item>
</div>
<template id="menu-list">
<div>
<h1>我是menu-list组件</h1>
<button @click="handle">我要传递数据</button>
</div>
</template>
<template id="menu-item">
<div>
<h1>我是menu-item组件</h1>
</div>
</template>
<script src="./js/vue.js"></script>
<script>
//中间组件
let hub=new Vue();
// 传递数据方,通过一个事件触发hub.$emit(自定义事件名,传递的数据)
Vue.component('menu-list',{
template:`#menu-list`,
data(){
return{
}
},
methods:{
handle(){
hub.$emit('send',200)
}
}
})
// 接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
Vue.component('menu-item',{
template:`#menu-item`,
data(){
return{
num:0
}
},
mounted(){
hub.$on('send',function(val){
console.log('接收到兄弟组件传递过来的值是:'+val);
})
}
})
//根组件
var vm=new Vue({
//模板选择器
el:'#app',
//数据中心
data(){
return{
}
},
methods:{
}
})
</script>
预览:
一个组件向另一个组件 传递数据,另一个组件向这个组件传递数据(双向传递数据)
<div id="app">
<!-- <div>父组件</div> -->
<!-- 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据 -->
<!-- <button @click="handle">销毁</button> -->
<menu-list></menu-list>
<menu-item></menu-item>
</div>
<script src="js/vue.js"></script>
<script>
// 兄弟组件之间数据传递
// 中间组件
let hub = new Vue();
Vue.component('menu-list',{
template:`
<div>
<h1>我是menu-list组件</h1>
<p>我是menu-list组件中的num:{{num}}</p>
<button @click="handle">发送</button>
<br>
<p>menu-list组件,接收到兄弟组件传递过来的数据是:<b style="color:blue;font-size:20px;">{{y}}</b></p>
</div>
`,
data(){
return {
num:10,
y:null
}
},
// 生命周期钩子函数
mounted(){
// 监听事件
hub.$on('send-menu-list',(val)=>{
console.log(val);
// 1. 把接收到的数据,赋值给我数据中心的y去使用
this.y = val;
// 2. 把接收到的数据,让它参与num的计算
this.num += val;
})
},
methods:{
handle(){
// 1.自己组件内部数据变化
this.num++;
// 2.把数据 20 传递 走,送给兄弟组件去使用
hub.$emit('send-menu-item',20);
}
}
});
Vue.component('menu-item',{
template:`
<div>
<h1>我是menu-item组件</h1>
<p>我是menu-item组件里的num:{{num}}</p>
<button @click="handle">发送</button>
<br>
<p>menu-item组件,接收到兄弟组件传递过来的数据是:<b style="color:red;font-size:20px;">{{x}}</b></p>
</div>
`,
data(){
return {
num:0,
x:null
}
},
// 生命周期钩子函数
mounted(){
// 监听事件
hub.$on('send-menu-item',(val)=>{
console.log(val);
this.x = val;
})
},
methods:{
handle(){
// 触发兄弟组件的事件
// 把数据 10000 传递 走,送给兄弟组件去使用
this.num++;
hub.$emit('send-menu-list',10000);
}
}
});
// 根组件
let vm = new Vue({
el:'#app',
data:{
},
methods:{
handle(){
// // 销毁事件
// hub.$off('send-menu-item');
// hub.$off('send-menu-list');
}
}
})
</script>
预览:
总结:
(1)创建一个空实例(bus中央事件总线也可以叫中间组件)
//在vue上挂载一个$bus作为中央处理组件Vue.prototype.$bus = new Vue()
(2)利用$emit $on的触发和监听事件实现非父子组件的通信
//触发自定义事件传递数据this.$bus.$emit('自定义事件名','传递的数据')
(3)//监听自定义事件获取数据this.$bus.$on('自定义事件名',fn)
1.1.6 组件之间消息传递的常用方式
对于vue来说,组件之间的消息传递是非常重要的,下面是我对组件之间消息传递的常用方式的总结。
(1)props和$emit(常用)(2)中央事件总线(非父子组件间通信)
这两个 我们上面的课程,已经阐述过。大家都会使用了。
1.1.6.1 $parent和$children
接着,我们看下 $parent($root)和$children($refs和ref) 怎么进行 组件之间的消息传递(也就是我们说的 组件之间的通信)
组件是vue的核心,组件的通信是vue的核心的核心
$parent和$children 是用来描述 父子组件通信的。
通信:数据的“动态的实时的”传递
通信(访问)--- 一定是 能 拿到 对方的 东西(数据中心的数据,方法中心的方法,计算属性等等)
子组件 访问 父组件
$parent 获取父组件实例
在子组件created()中直接使用 this.$parent
我们通过 this.$parent 可以 在子实例(子组件)中 拿到 父实例(父组件)里的任何东西!!!
$parent
获取父组件
可以获取父元素对象,在子组件中修改 会 影响父组件
(注意这里的)
可以this.$parent链式调用取父组件之上的组件
<div id="app">
<parent></parent>
</div>
<script src="js/vue.js"></script>
<script>
// 子组件
let child = {
template:`
<div>
<h1>我是child子组件</h1>
</div>
`,
// 生命周期
created(){
// 子访父
console.log(this.$parent)
// 访问父组件中的数据中心data里的数据
console.log(this.$parent.msg);
// 访问父组件中的方法中心methods里的方法
console.log(this.$parent.run());
// 访问父组件中计算属性computed里的计算属性
console.log(this.$parent.total);
},
data(){
return {
}
}
}
let parent = {
template:`
<div>
<h1>我是parent父组件</h1>
<child></child>
</div>
`,
data(){
return {
msg:'xiaoyu',
num:10
}
},
computed:{
total(){
return this.num*this.num
}
},
components:{
child
},
methods:{
run(){
return "hx"
}
}
}
// 根组件
let vm = new Vue({
el:'#app',
data:{
},
methods:{
},
components:{
parent
}
})
</script>
优化后:
<div id="app">
<div>
<h1>我是parent父组件</h1>
</div>
<parent id="parent">
<child id="child">
<div>
<h1>我是child子组件</h1>
</div>
</child>
</parent>
</div>
// 子组件
let child = {
template:`#child`,
}
let parent = {
template:`#parent
`,
}
预览:
父组件 访问 子组件
$children ($children 的值是数组)
$children 获取"全部的"子组件
在父组件mounted()直接使用 this.$children
获取 当前组件的子组件,子组件会被放进数组[]里
获取子组件的下标后,操作和$parent一样
例如:
子组件的数组
this.$children
特别注意:
父访子,一定要在dom挂载后,我们调用生命周期钩子函数mounted(){}
<div id="app">
<parent></parent>
</div>
<script src="js/vue.js"></script>
<script>
// 子组件
let child = {
template:`
<div>
<h1>我是child子组件</h1>
</div>
`,
// 生命周期
created(){
},
data(){
return {
message:'我是子组件中的数据',
num:20
}
},
computed:{
count(){
return this.num + 100;
}
},
methods:{
move(){
return 'ok';
}
}
}
let parent = {
template:`
<div>
<h1>我是parent父组件</h1>
<child></child>
</div>
`,
data(){
return {
}
},
// 生命周期
mounted(){
// 父访子
console.log(this.$children);
// 访问子组件中的数据中心data里的数据
console.log(this.$children[0].message);
console.log(this.$children[0].num);
// 访问子组件中的方法中心methods里的方法
console.log(this.$children[0].move());
// 访问子组件中计算属性computed里的计算属性
console.log(this.$children[0].count);
},
computed:{
},
components:{
child
},
methods:{
}
}
// 根组件
let vm = new Vue({
el:'#app',
data:{
},
methods:{
},
components:{
parent
}
})
</script>
优化后:
<div id="app">
<div>
<h1>我是parent父组件</h1>
</div>
<parent id="parent">
<child id="child">
<div>
<h1>我是child子组件</h1>
</div>
</child>
</parent>
</div>
// 子组件
let child = {
template:`#child
`,
}
let parent = {
template:`#parent
`,
}
预览:
1.1.6.2 ref和$refs
ref 和$refs 父组件 和 子组件 (需要结合在一起使用)
父组件 访问 子组件
$refs 获取指定的子组件(常用)
例如:
获取:this.$refs.xxx获取子组件实例
<div id="app">
<parent></parent>
</div>
<script src="js/vue.js"></script>
<script>
//ref 和$refs
// 子组件
let child = {
template:`
<div>
<h1>我是child子组件</h1>
</div>
`,
// 生命周期
created(){
},
data(){
return {
message:'我是子组件中的数据',
num:20
}
},
computed:{
count(){
return this.num + 100;
}
},
methods:{
move(){
return 'ok';
}
}
}
let parent = {
template:`
<div>
<h1>我是parent父组件</h1>
<child ref="c1"></child>
</div>
`,
data(){
return {
}
},
// 生命周期
mounted(){
// 父访子
// 父组件 使用 $refs 获取 子组件,在视图层 要结合ref 一起使用。
// this.$refs.子组件名称 (视图层你定义的子组件的名字)
console.log(this.$refs.c1);
// 访问子组件中的数据中心data里的数据
console.log(this.$refs.c1.message);
console.log(this.$refs.c1.num);
// 访问子组件中的方法中心methods里的方法
console.log(this.$refs.c1.move());
// 访问子组件中计算属性computed里的计算属性
console.log(this.$refs.c1.count);
},
computed:{
},
components:{
child
},
methods:{
}
}
// 根组件
let vm = new Vue({
el:'#app',
data:{
},
methods:{
},
components:{
parent
}
})
</script>
预览: