一、$emit传值:用于子组件向父组件传值,但是只能传数据,不能传方法
<style>
*{
margin: 0;
padding: 0;
list-style: none;
}
.list{
margin: 10px;
}
.counter{
display: flex;
align-items: center;
margin: 5px;
}
.counter .label{
font-size: 14px;
margin-right: 5px;
}
.counter .btns{
display: flex;
}
.counter .btns button{
width: 20px;
}
.counter .btns .text{
width: 40px;
text-align: center;
outline: none;
margin: 0 4px;
}
</style>
<div id="app">
<ul class="list">
<li v-for="(item,index) in list" :key="index">{{item.label}}--{{item.count}}</li>
</ul>
<b-counter v-for="(item,index) in list" :key="index" :label="item.label"
// 2.触发的自定义事件synccount,会执行一个方法synccount,通过$event来接收子组件传出的数值
:count="item.count" @synccount="synccount(index,$event)"></b-counter>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
Vue.config.productionTip = false
new Vue({
el:'#app',
data:{
list:[
{
label:'衣服',
count:5
},
{
label:'裤子',
count:8
},
{
label:'鞋子',
count:3
},
{
label:'袜子',
count:10
}
]
},
methods: {
//3.父组件接收到子组件传过来的参数,用以更改数据,渲染页面
synccount(index,e){
// 更新数据
this.list[index].count = e
}
},
//定义组件
components:{
'b-counter':{
template:`
<div class="counter">
<div class="label">{{label}}</div>
<div class="btns">
<button @click="myCount--" :disabled="myCount===minCount">-</button>
<input readonly class="text" type="text" :value="myCount">
<button @click="myCount++" :disabled="myCount===maxCount">+</button>
</div>
</div>
`,
//props选项,用于定义组件的属性,有两种方式:1.定义数组,2.定义对象
//注意:props是只读的,不能修改
// props:['label','count']
props:{
//文本
label:{
type:String,
//允许为空
required:false,
},
//数量
count:{
type:Number,
//非空
required:true
},
//最大值
maxCount:{
type:Number,
default:999
},
//最小值
minCount:{
type:Number,
default:1
}
},
//定义数据
data() {
return {
//将props接收到的count,中转给myCount
myCount:this.count
}
},
//监听器
watch:{
myCount(val){
//1.监听myCount,如果发生变化会 触发一个自定义事件,事件名称是synccount,将count的最新值作为事件对象传出去
// 注意:自定义事件名称不能使用大写
this.$emit('synccount',val)
}
}
}
}
})
</script>
二、通过$parent传值(子组件获取父组件数据)
适用于父组件给子组件传值
<div id='app'>
<b-box ></b-box>
</div>
<script src='https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js'></script>
<script>
// 子组件
Vue.component('b-box', {
template: `
<div class=box>
// 通过$parent返回的是父组件对象
<h2>{{$parent.house.house}}</h2>
<p>{{$parent.house.size}}</p>
<childson></childson>
</div>`,
props: [],
data() {
return {}
}
})
Vue.config.productionTip = false
// 父组件
let vm = new Vue({
el: '#app',
data() {
return {
house:{
house:'房产信息',
size:'150平方'
},
car: {
car:'车辆信息',
name:'奔驰大G'
},
money:{
name:'存款信息',
cash:'200万现金'
}
};
}
})
</script>
三、通过$root传值(后代组件获取祖先组件数据)
<div id='app'>
<b-box ></b-box>
</div>
<script src='https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js'></script>
<script>
// 子组件
Vue.component('b-box', {
template: `
<div class=box>
<h2>{{$parent.house.house}}</h2>
<p>{{$parent.house.size}}</p>
<childson></childson>
</div>`,
props: [],
data() {
return {}
}
})
// 后代组件
Vue.component('childson', {
template: `
<div class=box>
<h2>{{$parent.$parent.car.car}}</h2>
<p>{{$parent.$parent.car.name}}</p>
// $root获取根组件对象
<p>{{$root.car.name}}</p>
</div>`,
props: [],
data() {
return {}
},
mounted() {
},
})
Vue.config.productionTip = false
let vm = new Vue({
el: '#app',
data() {
return {
house:{
house:'房产信息',
size:'150平方'
},
car: {
car:'车辆信息',
name:'奔驰大G'
},
money:{
name:'存款信息',
cash:'200万现金'
}
};
}
})
</script>
四、通过$children传值(父组件获取子组件数据)
<div id='app'>
<b-box ></b-box>
{{son}}
</div>
<script src='https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js'></script>
<script>
// 子组件
Vue.component('b-box', {
template: `
<div class=box>
<h2>{{$parent.house.house}}</h2>
<p>{{$parent.house.size}}</p>
<childson></childson>
</div>`,
props: [],
data() {
return {
name:'张三',
age:18
}
}
})
Vue.config.productionTip = false
let vm = new Vue({
el: '#app',
data() {
return {
house:{
house:'房产信息',
size:'150平方'
},
car: {
car:'车辆信息',
name:'奔驰大G'
},
money:{
name:'存款信息',
cash:'200万现金'
},
son:{
name:'',
age:0
}
};
},
mounted() {
// 注意:在父子级的mounted生命周期函数内,才能获取到$children信息
// $children返回的是所有子组件对象的数组
console.log(this.$children);
this.son.name=this.$children[0].name
this.son.age=this.$children[0].age
},
})
</script>
五、children:返回的是所有子组件对象的数组,再通过下标获取指定的子组件。当组件顺序不会发生变化时,用refs。注意:
$refs:返回的是一个对象,对象中包含所有带有ref属性的子组件。 注意:不是只有组件才可以添加ref属性,任何标签都可以加ref属性 。
注意:在父组件创建完成到挂载完成之间,包含完整的子组件的生命周期。父级组件在mounted生命周期函数内,才能获取到$children信息;在子组件的created生命周期函数中,可以获取到父组件的数据。顺序:父级created => 子级1created => 子级2created => => 子级1mounted => 子级2mounted => 父级mounted
<style>
*{
margin: 0;
padding: 0;
}
#app{
border: 1px solid #ccc;
padding: 10px;
margin: 10px;
}
.child1{
border: 1px solid red;
padding: 10px;
}
.child2{
border: 1px solid green;
padding: 10px;
margin: 10px 0;
}
.child3{
border: 1px solid orange;
padding: 10px;
}
.son{
margin: 10px 0;
padding: 10px;
border: 1px solid #eee;
}
.childSon{
border: 1px solid purple;
padding: 10px;
}
</style>
<div id="app">
<!-- 给组件标签,添加ref属性,可以通过$refs对象获取 -->
<Child1 ref="son1"></Child1>
<Child2 ref="son2"></Child2>
<Child3 ref="son3"></Child3>
<div class="son">
<h3>大儿子</h3>
<p>姓名:{{son1.name}}</p>
<p>年龄:{{son1.age}}</p>
</div>
<div class="son">
<h3>二儿子</h3>
<p>姓名:{{son2.name}}</p>
<p>年龄:{{son2.age}}</p>
</div>
<div class="son">
<h3>小儿子</h3>
<p>姓名:{{son3.name}}</p>
<p>年龄:{{son3.age}}</p>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
<script>
Vue.config.productionTip = false
// Child1组件
Vue.component('Child1', {
// 通过$parent返回的是父组件对象
template:`
<div class="child1">
<h3>房产信息</h3>
<p>{{$parent.house.address}}</p>
<p>{{$parent.house.size}}</p>
<Childson></Childson>
</div>
`,
// 组件中的数据,必须是一个函数,由函数返回一个对象
data() {
return {
name:'张杰',
age:25
}
},
mounted() {
console.log('子级1mounted');
},
created() {
console.log('子级1created');
},
})
// childSon组件
Vue.component('Childson',{
// $parent获取父组件对象
// $root获取根组件对象
template:`
<div class="childSon">
<h3>房产信息</h3>
<p>{{$parent.$parent.house.address}}</p>
<p>{{$parent.$parent.house.size}}</p>
<hr>
<p>{{$root.house.address}}</p>
<p>{{$root.house.size}}</p>
</div>
`
})
// Child2组件
Vue.component('Child2', {
template:`
<div class="child2">
<h3>汽车信息</h3>
<p>{{$parent.car.name}}</p>
<p>{{$parent.car.color}}</p>
</div>
`,
data() {
return {
name:'张飞',
age:23
}
},
mounted() {
console.log('子级2mounted');
},
created() {
console.log('子级2created');
},
})
Vue.component('Child3', {
template:`
<div class="child3">
<h3>存款信息</h3>
<p>{{$parent.money.value}}</p>
<p>{{$parent.money.bank}}</p>
</div>
`,
data() {
return {
name:'张强',
age:20
}
},
mounted() {
console.log('子级3mounted');
},
created() {
console.log('子级3created');
},
})
// 暂且将#app对应的内容当成根组件
new Vue({
el:'#app',
//数据
data:{
house:{
address:'名城世家3栋1单元1101室',
size:'150平米'
},
car:{
name:'奔驰S400',
color:'黑色'
},
money:{
value:'150W',
bank:'中国建设银行'
},
//接收子组件的数据的对象
son1:{
name:'',
age:0
},
son2:{
name:'',
age:0
},
son3:{
name:'',
age:0
}
},
mounted() {
console.log('父级mounted');
// 注意:在父子级的mounted生命周期函数内,才能获取到$children信息
// $children返回的是所有子组件对象的数组
// console.log(this.$children);
/* this.son1.name = this.$children[0].name
this.son1.age = this.$children[0].age
this.son2.name = this.$children[1].name
this.son2.age = this.$children[1].age
this.son3.name = this.$children[2].name
this.son3.age = this.$children[2].age */
// $refs返回的是一个对象,对象中包含所有带有ref属性的组件
console.log(this.$refs);
this.son1.name = this.$refs.son1.name
this.son1.age = this.$refs.son1.age
this.son2.name = this.$refs.son2.name
this.son2.age = this.$refs.son2.age
this.son3.name = this.$refs.son3.name
this.son3.age = this.$refs.son3.age
},
created() {
console.log('父级created');
},
})
</script>