组件传值—父传子
父组件通过属性给子组件传值: 子组件的props接受数据
在页面模板中 使用变量名:属性 data 计算属性(重点)
注意:属性传值是单向的,只能父到子
App.vue
<template>
<div>
<Box
v-for="(item, index) in arr"
:title="item.title"
:price="item.price"
:count="item.count"
:key="item.id"
>
</Box>
<button>总价:{{ total }}</button>
</div>
</template>
<script>
import Box from "./Box.vue";
export default {
data() {
return {
arr: [
{
title: "肉丝1",
price: 14,
count: 5,
},
{
title: "肉丝2",
price: 15,
count: 9,
},
{
title: "肉丝3",
price: 13,
count: 1,
},
{
title: "肉丝4",
price: 19,
count: 3,
},
{
title: "肉丝5",
price: 20,
count: 2,
},
],
};
},
components: {
Box,
},
computed: {
total() {
return this.arr.reduce((n1, n2) => {
return n1 + n2.price * n2.count;
}, 0);
},
},
};
</script>
<style scoped="scoped" lang="scss">
</style>
Box.vue
<template>
<div>
<div>{{title}}----{{price}}元
数量:
<button>-</button>
<span>{{count}} </span>
<button @click="add">+</button>
</div>
</div>
</template>
<script>
export default {
props: ["title", "price", "count"],
methods:{
add(){
console.log(this.count)
this.count++
}
}
}
</script>
<style>
</style>
这就是单向传值
组件传值—子传父emit
组件通过调用父组件的方法给父组件传值:子组件的自定义事件中,用$emit触发事件调用父组件方法给父组件传值
因为通过属性传值是单向的,但有时候我们需要子组件的data 数据需要交给父组件使用通过在子组件上定义自定义事件,在子组件中通过$emit 来触发事件;子组件的事件被触并传参,事件处理函数可以接收到子组件的数据;事件绑定的事件处理函数在父节点上,故可在事件处理函数中用到子组件的数据值来修改父节点的数据
App.vue
<template>
<div>
<Box @mycountincrement="countin" v-for="(item,i) in arr"
:title="item.title"
:price="item.price"
:count="item.count"
:key="item.id"
:index="i"
>
</Box>
<button>总价:{{total}}</button>
<button @click="change1">父组件修改数据</button>
</div>
</template>
<script>
import Box from "./Box.vue"
export default {
data() {
return {
arr: [
{
title: "肉丝1",
price: 14,
count: 5,
},
{
title: "肉丝2",
price: 15,
count: 9,
},
{
title: "肉丝3",
price: 13,
count: 1,
},
{
title: "肉丝4",
price: 19,
count: 3,
},
{
title: "肉丝5",
price: 20,
count: 2,
},
],
}
},
methods:{
countin(arg,index){
console.log(arg,1234,index)
this.arr[index].count=arg
this.$set(this.arr,index,this.arr[index])
},
change1(){
this.arr[0].count=100
this.$set(this.arr,0,this.arr[0])
}
},
components:{
Box
},
computed:{
total(){
return this.arr.reduce((n1,n2)=>{
return n1+n2.price*n2.count
},0)
}
}
}
</script>
<style scoped="scoped" lang="scss">
</style>
Box.vue
<template>
<div>
<div>{{title}}----{{price}}元
数量:
<button>-</button>
<span>{{count}} </span>
<button @click="add">+</button>
</div>
</div>
</template>
<script>
export default {
props: ["title", "price", "count","index"],
methods:{
add(){
//触发事件 并传值
let n=this.count+1
this.$emit("mycountincrement",n,this.index)
}
}
}
</script>
<style>
</style>
Box组件循环遍历,有多少个数据就循环多少次出来,给自定义事件mycountincrement变得一个方法countin,一旦触发方法就会通过点击的元素下标改变父元素里面的值
父元素通过属性将值传给了子元素,子元素通过button的点击事件触发来增加值并且触发mycountincrement事件,这个事件触发就会调用countin函数执行,就能够该值,实现双向传值了
组件传值—子传父sync
App.vue
<template>
<div class="app">
<h1>app组件--msg-{{msg}}--{{msg2}}</h1>
<Box :a1.sync="msg"></Box>
<Box :a1.sync="msg" :a2.sync="msg2"></Box>
<Box :a1.sync="msg" :a2.sync="msg2"></Box>
</div>
</template>
<script>
import Box from "./Box.vue"
export default {
data() {
return {
msg: "app的数据",
msg2:"app的数据2"
}
},
components: {
Box
},
}
</script>
<style scoped="scoped" lang="scss">
.app {
width: 600px;
height: 400px;
background-color: darkgray;
margin: 20px;
}
</style>
Box.vue
<template>
<div class="box">
<h2>box组件---a1-{{a1}}--{{a2}}</h2>
<button @click="change1">修改a1中的数据</button>
<button @click="change2">修改a2中的数据</button>
</div>
</template>
<script>
export default {
props:["a1","a2"],
methods:{
change1(){
this.$emit("update:a1","box修改了a1的值")
},
change2(){
this.$emit("update:a2","66666")
}
}
}
</script>
<style scoped="scoped" lang="scss">
.box{
width: 400px;
height: 200px;
background-color: cornflowerblue;
margin: 20px;
}
</style>
比上面简便的写法,就是改为下面这两行,分别是两个.vue文件的
<Box :a1.sync="msg" :a2.sync="msg2"></Box>
this.$emit("update:a2","66666")
本质都是一样的
组件传值—子传父v-model
App.vue
<template>
<div class="app">
<p>app--{{msg}}</p>
<Box v-model="msg"></Box>
</div>
</template>
<script>
import Box from "./Box.vue"
export default {
data() {
return {
msg:"app666"
}
},
components: {
Box
},
methods:{
}
}
</script>
<style scoped="scoped" lang="scss">
.app {
width: 600px;
height: 400px;
background-color: darkgray;
margin: 20px;
}
</style>
Box.vue
<template>
<div class="box">
<h2>box--{{value}}</h2>
<button @click="change1">chaneg1</button>
</div>
</template>
<script>
export default {
props:["value"],
methods:{
change1(){
this.$emit("input","1235454375687")
}
}
}
</script>
<style scoped="scoped" lang="scss">
.box{
width: 400px;
height: 200px;
background-color: cornflowerblue;
margin: 20px;
}
</style>
v-model 不仅可以input的双向传值绑定,也可以组件的双向传值绑定
<Box v-model="msg"></Box>
但是要注意这里要改为input,因为本质还是input和value
this.$emit("input","12354")