一、vue组件通信
-
-
子组件通过props接收父组件数据,通过自定义属性的属性名
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<child_temp v-bind:child_msg="parent_msg" :chlid_movies="parent_movies"></child_temp>
</div>
<template id="child_temp">
<div>
<ul>
<li v-for="item in chlid_movies">{{item}}</li>
</ul>
<p>{{child_msg}}</p>
<p>{{chlid_movies}}</p>
<p>{{myname}}</p>
<!--<button @click="child_btn">子按钮</button>-->
</div>
</template>
</body>
<script src="../../js/vue.js"></script>
<script>
const child_temp = {
template:'#child_temp',
/*props:['chlid_movies','child_msg'],*/
props:{
//props的扩展,包括类型,默认值,是否必须等
//1类型限制
/*chlid_movies:Array,
child_msg:String*/
//2.提供默认值,扩展
chlid_movies:{
type:Array,
default() {
return [];
}
},
child_msg: {
type: String,
required: true,
default() {
//如果把child_temp模板里的v-bind:child_msg="parent_msg"去掉,页面就会显示这里的值
return ["子_我是子组件默认值,当使用父组件data里的属性值得时候,如果没有用v-bind绑定,会取到我这一串值"];
}
}/*,
methods:{
child_btn(){
alert("我是子组件的方法")
}
}*/
},
data(){
return {
myname:"子_我是子属性自己的值,我使用的是自己组件里的data的属性值"
}
}
}
var vm = new Vue({
el:"#app",
data:{
parent_msg:"父_我是父组件里的信息,传到了子组件",
parent_movies:['父_火影','父_海贼王','父_柯南']
},
components:{
child_temp
}
})
</script>
</html>
效果:
props:定义需要从父组件中接收的属性
-
items:是要接收的属性名称
-
type:限定父组件传递来的必须是数组
-
default:默认值
-
required:是否必须
验证支持的数据类型
-
String
-
Number
-
Boolean
-
Array
-
Object
-
Date
-
Function
-
Symbol
动态静态传递
给 prop 传入一个静态的值:
<temp child_msg="大家好,我是组件"/>
给 prop 传入一个动态的值: (通过v-bind从数据模型中,获取title的值)
<temp :child_msg="parent_msg"/>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--父组件模板-->
<div id="app">
<!--监听子组件发射出的btn_child_click事件,find_parent_click要在父组件里定义methods-->
<chlid_temp v-on:btn_child_click="find_parent_click"></chlid_temp>
</div>
<!--子组件模板-->
<template id="chlid_temp">
<div>
<button v-for="item in movies"
@click="btn_ckik(item)">
{{item.id}}-{{item.name}}
</button>
</div>
</template>
</body>
<script src="../../js/vue.js"></script>
<script>
//子组件
const chlid_temp = {
template:"#chlid_temp",
data(){
return{
movies:[
{id:"1",name:"火影"},
{id:"2",name:"海贼"},
{id:"3",name:"七大罪"},
{id:"4",name:"菜鸟java是怎么炼成的"},
{id:"5",name:"菜鸟是怎么变菜的"},
]
}
},
methods:{
btn_ckik(ev){
//自定义事件
this.$emit("btn_child_click",ev)
}
}
}
//父组件
var vm = new Vue({
el:"#app",
data:{
msg:"我是父组件的信息-msg"
},
components:{
chlid_temp
},
methods:{
find_parent_click(ev){
console.log(ev)
console.log(ev.id +" "+ev.name)
}
}
});
</script>
</html>
效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<temp :c_num1="p_num1"
:c_num2="p_num2"
@data_cnum1_change="parent_cnum1_change"
@data_cnum2_change="parent_cnum2_change"
></temp>
</div>
<template id="temp">
<div>
<h3>props:{{c_num1}}</h3>
<h3>data:{{data_cnum1}}</h3>
<!--<input type="text" v-model="data_cnum1">-->
input1:<input type="text" :value="data_cnum1" @input="num1_input">
<h3>props:{{c_num2}}</h3>
<h3>data:{{data_cnum2}}</h3>
<!--<input type="text" v-model="data_cnum2">-->
<!--<input type="text" :value="data_cnum2" @input="data_cnum2=$event.target.value">-->
input2:<input type="text" :value="data_cnum2" @input="num2_input">
</div>
</template>
</body>
<script src="../../js/vue.js"></script>
<script>
const temp={
template:"#temp",
props:{
c_num1:Number,
c_num2:Number
},
data(){
return{
data_cnum1:this.c_num1,
data_cnum2:this.c_num2
}
},
methods:{
num1_input(e){
//1 将input的value赋值到data_cnum1上
this.data_cnum1 = e.target.value;
//2 为了让父组件可以改值,发出一个事件
this.$emit("data_cnum1_change",this.data_cnum1);
//3 同事修改data_cnum2的值(data_cnum2的值是data_cnum1的100倍)
this.data_cnum2 = this.data_cnum1 * 100;
this.$emit("data_cnum2_change",this.data_cnum2)
},
num2_input(e){
this.data_cnum2 = e.target.value;
this.$emit("data_cnum2_change",this.data_cnum2);
//(data_cnum2的值是data_cnum1的100分之一倍)
this.data_cnum1 = this.data_cnum2 / 100;
this.$emit("data_cnum1_change",this.data_cnum1)
}
}
}
var vm = new Vue({
el:"#app",
data:{
p_num1:1,
p_num2:0
},
components:{
temp
},
methods:{
parent_cnum1_change(data_cnum1){
//默认传过来的是Strnig类型,需要转换成number
console.log(typeof data_cnum1)
this.p_num1 = parseInt(data_cnum1);
},
parent_cnum2_change(data_cnum2){
this.p_num2 = parseInt(data_cnum2);
}
}
})
</script>
</html>
-
父访问子使用使用
$children或$refs
$children的缺陷:通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs$refs的使用:$refs和ref指令通常是一起使用的。首先,我们通过ref给某一个子组件绑定一个特定的ID。其次,通过this.$refs.ID就可以访问到该组件了。
例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
<cpn ref="ref_name"></cpn>
<button @click="btnClick">按钮</button>
{{message}}
</div>
<template id="cpn">
<div>我是子组件</div>
</template>
<script src="../../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '你好啊'
},
methods: {
btnClick() {
// 1.$children
console.log(this.$children);
for (let v of this.$children) {
console.log(v.child_name);
v.childMessage();
this.message = v.child_name;
}
console.log(this.$children[3].child_name+'================');
/*console.log(this.$children[4].child_name+'++++++++++++');*/
// 2.$refs => 对象类型, 默认是一个空的对象 ref='ref-name'
console.log(this.$refs.ref_name.child_name+"----------");
}
},
components: {
cpn: {
template: '#cpn',
data() {
return {
child_name: '我是子组件的name哈哈'
}
},
methods: {
childMessage() {
console.log('childMessage');
}
}
},
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<button @click="rootclik()">根组件按钮</button>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>我是cpn组件</h2>
<ccpn></ccpn>
</div>
</template>
<template id="ccpn">
<div>
<h2>我是子组件</h2>
<button @click="btnClick">按钮</button>
</div>
</template>
<script src="../../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '我是ccpn组件的根组件的name'
},
methods: {
rootclik(){
console.log("我是根组件root的事件")
}
},
components: {
cpn: {
template: '#cpn',
data() {
return {
name: '我是ccpn组件的父组件的name'
}
},
methods: {
parentclik(){
console.log("我是父组件parent的事件")
}
},
components: {
ccpn: {
template: '#ccpn',
methods: {
btnClick() {
// 1.访问父组件$parent
console.log("======parent start============")
console.log(this.$parent);
console.log(this.$parent.name);
console.log(this.$parent.parentclik());
console.log("======parent end============")
// 2.访问根组件$root
console.log("======root start============")
console.log(this.$root);
console.log(this.$root.message);
console.log(this.$root.rootclik());
console.log("======root end============")
}
}
}
}
}
}
})
</script>
</body>
</html>