vue组件父传子、子传父、兄弟组件之间传值
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue组件父传子、子传父、兄弟组件之间传值相关的知识,希望对你有一定的参考价值。
参考技术A 1、在父组件中传入子组件child32、传入时,使用v-bind指令绑定2个属性parameValue和parameValue2
2、在子组件child3中使用props接收(接收一个数组,数组中分别为父组件传递过来的属性parameValue和parameValue2,类型为字符串,也可以接收一个对象,键为传递过来的属性,值为字符串String),
3、将传递过来的属性在DOM中以变量的形式渲染
子传父需要事件触发
1、在子组件child4中,在方法中使用$emit函数传递,第一个参数为监听的事件,第二个参数为要传递的值
2、在父组件child4中,使用传递的事件进行监听,监听到后调用函数fn
3、函数接收一个参数,这个参数就是子组件child4传递的参数
VUE_03 组件化思想全局|局部注册组件之间传值(父传子子传父兄弟传兄弟)匿名|具名|作用域插槽
①. 组件化思想
-
①. 所谓组件化,就是把页面拆分成多个组件,每个组件自己管理所依赖的 CSS、JS、模板、图片等资源
-
②. 组件与组件之间通过特定的规则进行数据传递、就会行成树状结构
②. 全局注册
-
①. Vue.component(‘组件名称’, { }) 第1个参数是标签名称,第2个参数是一个选项对象
-
②. 注意事项:
- data必须是一个函数
- 组件模板必须是单个根元素(下面这个是错误的,没有根元素)
- 组件模板的内容可以是模板字符串
- ③. 组件命名规则
- 如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件
- 但是在普通的标签模板中,必须使用短横线的方式使用组件
- ④. 案列演示
<body>
<div id="app">
<!--你可以将组件进行任意次数的复用:因为data中返回的是一个对象所以每个组件中的数据是私有的-->
<button-count></button-count>
<button-count></button-count>
<!--必须使用短横线的方式使用组件-->
<button-count></button-count>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.component('button-count',{
//1. data必须是一个函数
data:function(){
return{
count:0
}
},
//2. 组件模板必须是单个根元素(下面这个是错误的,没有根元素)
//template:'<button @click="handle()">已经点击了{{count}}次了</button><button></button>',
//3. 组件模板的内容可以是模板字符串
//template:'<button @click="handle()">已经点击了{{count}}次了</button>',
template:`
<button @click="handle()">已经点击了{{count}}次了</button>
`,
methods:{
handle(){
this.count+=2
}
}
});
var vm=new Vue({
el:'#app',
data:{
}
});
</script>
</body>
</html>
③. 局部注册
-
①. 只能在当前注册它的vue实例中使用
-
②. 注意:局部注册的组件、指令、过滤器等、都只能在父组件(它的实例)中使用
-
③. 代码展示
<div id="app">
<hello-word></hello-word>
</div>
<script src="../js/vue.js"></script>
<script>
/*
局部组件(局部组件只能在注册他的父组件中使用)
*/
var HelloWorld={
data:function(){
return{
msg:'xiaozhi'
}
},
template:'<div>{{msg}}</div>'
};
var vm=new Vue({
el:'#app',
data:{
},
components:{
'hello-word':HelloWorld
}
});
</script>
</body>
</html>
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
④. 父组件向子组件传值
-
①. 父组件发送的形式是以属性的形式绑定值到子组件身上
-
②. 然后子组件用属性props接收
-
③. 在props中使用驼峰形式,模板中需要使用短横线的形式字符串形式的模板中没有这个限制
-
④. 数值与布尔值要通过v-bind动态获取、否则静态的是字符串
<body>
<div id="app">
<!-- 注意:p-number 和 p-boolean 如果前面不加v-bind绑定的话,类型是字符串类型 -->
<menu-titile :pstring='pString' :pnumber='2' :pboolean=true :pfriut='pFruit' :pobject='pObject'></menu-titile>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.component('menu-titile',{
props:['pstring','pnumber','pboolean','pfriut','pobject'],
template:`
<div>
<div>{{pstring}}</div>
<div>{{typeof pnumber}}</div>
<div>{{typeof pboolean}}</div>
<ul>
<li :key="index" v-for="(item,index) in pfriut">{{item}}</li>
</ul>
<ul>
<li :key="index" v-for="(value,key,index) in pobject">{{key+"----"+value+"-----"+index}}</li>
</ul>
</div>
`
});
var vm=new Vue({
el:'#app',
data:{
pString:'xiaozhi',
pFruit:['香蕉','葡萄','苹果'],
pObject:{"name":"xiaozhi","age":24,"gender":"male"}
}
});
</script>
</body>
</html>
⑤. 子组件向父组件传值
-
①. 子组件用$emit()触发事件
-
②. $emit() 第一个参数为 自定义的事件名称 第二个参数为需要传递的数据
-
③. 父组件用v-on 监听子组件的事件
-
④. 如果父组件获取子组件的值还可以通过: this.$refs.menuRef.的方式获取子组件中prop定义的内容
<div id="app">
<div :style='{fontSize: fontSize + "px"}'>{{pmsg}}</div>
<!-- 2 父组件用v-on 监听子组件的事件
这里 enlarge-text 是从 $emit 中的第一个参数对应 handle 为对应的事件处理函数
-->
<menu-item ref=“menuRef” :parr='parr' @enlarge-text='handle($event)'></menu-item>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
子组件向父组件传值-携带参数
*/
Vue.component('menu-item', {
props: ['parr'],
template: `
<div>
<ul>
<li :key='index' v-for='(item,index) in parr'>{{item}}</li>
</ul>
### 1、子组件用$emit()触发事件
### 第一个参数为 自定义的事件名称 第二个参数为需要传递的数据
<button @click='$emit("enlarge-text", 5)'>扩大父组件中字体大小</button>
<button @click='$emit("enlarge-text", 10)'>扩大父组件中字体大小</button>
</div>
`
});
var vm = new Vue({
el: '#app',
data: {
pmsg: '父组件中内容',
parr: ['apple','orange','banana'],
fontSize: 10
},
methods: {
handle: function(val){
// 扩大字体大小
this.fontSize += val;
}
}
});
</script>
⑥. 兄弟之间的传递
-
①. 兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据
提供事件中心 var hub = new Vue() -
②. 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)
-
③. 接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
-
④. 销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
<div id="app">
<div>父组件</div>
<div>
<button @click='handle'>销毁事件</button>
</div>
<test-tom></test-tom>
<test-jerry></test-jerry>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
兄弟组件之间数据传递
*/
//1、 提供事件中心
var hub = new Vue();
Vue.component('test-tom', {
data: function(){
return {
num: 0
}
},
template: `
<div>
<div>TOM:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function(){
//2、传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据) 触发兄弟组件的事件
hub.$emit('jerry-event', 2);
}
},
mounted: function() {
// 3、接收数据方,通过mounted(){} 钩子中 触发hub.$on(方法名
hub.$on('tom-event',val=> this.num += val);
}
});
Vue.component('test-jerry', {
data: function(){
return {
num: 0
}
},
template: `
<div>
<div>JERRY:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function(){
//2、传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据) 触发兄弟组件的事件
hub.$emit('tom-event', 1);
}
},
mounted: function() {
// 3、接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
hub.$on('jerry-event', val => this.num += val);
}
});
var vm = new Vue({
el: '#app',
data: {
},
methods: {
handle: function(){
//4、销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据
hub.$off('tom-event');
hub.$off('jerry-event');
}
}
});
</script>
⑦. 匿名插槽
-
①. slot接收父组件开始与闭合中间的内容
-
②. 使用该组件时:组件标签中间写的内容会传递到中
-
③. 如果没有传递内容:solt中可自定义内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<!--
slot接收父组件开始与闭合中间的内容、
使用该组件时:组件标签中间写的内容会传递到中
如果没有传递内容:solt中可自定义内容
-->
<body>
<div id="app">
<!-- 这里的所有组件标签中嵌套的内容会替换掉slot,如果不传值则使用slot中的默认值(slot接收父组件开始与闭合中间的内容) -->
<alert-box>出现bug了</alert-box>
<!-- 使用该组件时:组件标签中间写的内容会传递到中 -->
<alert-box>出现了一个警告</alert-box>
<!-- 如果没有传递内容:solt中可自定义内容 -->
<alert-box></alert-box>
</div>
<script src="../js/vue.js"></script>
<script>
Vue.component('alert-box', {
//当组件渲染的时候,这个 <slot> 元素将会被替换为"组件标签中嵌套的内容"
//插槽内可以包含任何模板代码,包括 HTML
template: `
<div>
<span>ERROR</span>
<slot>默认内容</slot>
</div>
`
});
var vm = new Vue({
el: '#app',
data: {
}
});
</script>
</body>
</html>
⑧. 具名插槽
- ①. 具有名字的插槽,使用中的"name"属性绑定元素
<div id="app">
<base-layout>
<!-- 2、 通过slot属性来指定, 这个slot的值必须和下面slot组件得name值对应上
如果没有匹配到 则放到匿名的插槽中 -->
<p slot='header'>标题信息</p>
<p>主要内容1</p>
<p>主要内容2</p>
<p slot='footer'>底部信息信息</p>
</base-layout>
<base-layout>
<!-- 注意点:template临时的包裹标签最终不会渲染到页面上 -->
<template slot='header'>
<p>标题信息1</p>
<p>标题信息2</p>
</template>
<p>主要内容1</p>
<p>主要内容2</p>
<template slot='footer'>
<p>底部信息信息1</p>
<p>底部信息信息2</p>
</template>
</base-layout>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
/*
具名插槽
*/
Vue.component('base-layout', {
template: `
<div>
<header>
### 1、 使用 <slot> 中的 "name" 属性绑定元素 指定当前插槽的名字
<slot name='header'></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
### 注意点:
### 具名插槽的渲染顺序,完全取决于模板,而不是取决于父组件中元素的顺序
<slot name='footer'></slot>
</footer>
</div>
`
});
var vm = new Vue({
el: '#app',
data: {
}
});
</script>
</body>
</html>
⑨. 作用域插槽
-
①. 父组件对子组件加工处理
-
②. 既可以复用子组件的slot,又可以使slot内容不一致
<body>
<div id="app">
<fruit-list :list='list'>
<!-- 父组件中使用了<template>元素,而且包含scope="slotProps",
slotProps在这里只是临时变量 -->
<!-- 2、在父组件中通过slot-scope中的自定义值(slotProps)去接收solt传递过来的属性 -->
<template slot-scope='slotProps'>
<!-- 3、使用使用自定义属性去调用slot中接收过的数据、然后做操作 -->
<strong class="current" v-if='slotProps.info.id==3'> {{slotProps.info.name}}</strong>
<span v-else> {{slotProps.info.name}}</span>
</template>
</fruit-list>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
以上是关于vue组件父传子、子传父、兄弟组件之间传值的主要内容,如果未能解决你的问题,请参考以下文章
VUE_03 组件化思想全局|局部注册组件之间传值(父传子子传父兄弟传兄弟)匿名|具名|作用域插槽