vue组件通信_单向数据流
目标: props变量本身是只读不能重新赋值
目标:从父到子的数据流向,叫单向数据流
原因: 子组件修改, 不通知父级, 造成数据不一致性
如果第一个MyProduct.vue内自己修改商品价格为5.5, 但是App.vue里原来还记着18.8 - 数据 不一致了
所以: Vue规定props里的变量, 本身是只读的
父组件
<template>
<div>
<!--3. 使用组件 -->
<MyproDuct
v-for="item in list"
:key="item.id"
:title="item.proname"
:price="item.proprice"
:info="item.info"
></MyproDuct>
</div>
</template>
<script>
// 1.引入组件
import MyproDuct from './components/MyproDuct.vue'
export default {
data () {
return {
list: [
{ id: 1, proname: "超级好吃的棒棒糖", proprice: 18.8, info: '开业大酬宾, 全场8折' },
{ id: 2, proname: "超级好吃的大鸡腿", proprice: 34.2, info: '好吃不腻, 快来买啊' },
{ id: 3, proname: "超级无敌的冰激凌", proprice: 14.2, info: '炎热的夏天, 来个冰激凌了' },
],
}
},
//2. 注册组件
components: {
MyproDuct:MyproDuct
}
}
</script>
<style>
</style>
子组件
<template>
<div class="my-product">
<h3>标题: {{title}}</h3>
<p>价格: {{price}}</p>
<p>{{info}}</p>
<button @click="btn">是兄弟就来砍一刀</button>
</div>
</template>
<script>
export default {
methods: {
btn(){
// 💥浏览器报错 :避免直接改变属性,因为每当父组件重新渲染时,该值将被覆盖
this.price -= 1
}
},
// 声明变量。由父组件传值过来
props: ['title','price','info']
}
</script>
<style>
.my-product {
width: 400px;
padding: 20px;
border: 2px solid #000;
border-radius: 5px;
margin: 10px;
}
</style>
报错
总结: 所以props变量本身是不能重新赋值的
问题: 那我怎么才能修改子组件接收到的值呢? - 其实要影响父亲, 然后数据响应式来影响儿子们
vue组件通信_子向父
目标: 从子组件把值传出来给外面使用
需求: 课上例子, 砍价功能, 子组件点击实现随机砍价-1功能
语法:
- 父: @自定义事件名=“父methods函数”
- 子: this.$emit(“自定义事件名”, 传值) - 执行父methods里函数代码
父组件
<template>
<div>
<!--
目标:父(当前的 vue 文件) -> 子(MyproDuct.vue)分别传值进入
需求:每次组件显示不同的数据信息
步骤(口诀):
1.子组件 - props - 变量(准备接收)
2.父组件 - 传值进去 - 标签属性传值
目标2:子触发父组件的自定义事件,实现修改父组件数据
父组件:
@自定义事件 = "事件处理函数"
子组件:
this.$emit('自定义事件',值)
-->
<!--3. 使用组件 -->
<MyproDuct
v-for="(item,index) in list"
:key="item.id"
:title="item.proname"
:price="item.proprice"
:info="item.info"
:index ="index"
@kanPrice ="kanFn"
></MyproDuct>
</div>
</template>
<script>
// 1.引入组件
import MyproDuct from './components/MyproDuct.vue'
export default {
data () {
return {
list: [
{ id: 1, proname: "超级好吃的棒棒糖", proprice: 18.8, info: '开业大酬宾, 全场8折' },
{ id: 2, proname: "超级好吃的大鸡腿", proprice: 34.2, info: '好吃不腻, 快来买啊' },
{ id: 3, proname: "超级无敌的冰激凌", proprice: 14.2, info: '炎热的夏天, 来个冰激凌了' },
],
}
},
methods: {
// 自定义事件的处理函数
kanFn(index,price){
// 低于 1 块钱,就不给砍了
if(this.list[index].proprice < 1 ) return alert('再砍就凉凉了!')
// 根据索引减少价格
this.list[index].proprice = (this.list[index].proprice - price).toFixed(2)
}
},
//2. 注册组件
components: {
MyproDuct:MyproDuct
}
}
</script>
<style>
</style>
子组件:MyproDuct.vue
<template>
<div class="my-product">
<h3>标题: {{title}}</h3>
<p>价格: {{price}}</p>
<p>{{info}}</p>
<button @click="btn">是兄弟就来砍一刀</button>
</div>
</template>
<script>
export default {
methods: {
btn(){
// 💥浏览器报错 :避免直接改变属性,因为每当父组件重新渲染时,该值将被覆盖
// this.price -= 1
// 🔔 子组件通过自定义事件,触发对应的事件处理函数
this.$emit('kanPrice' , this.index , 1)
}
},
// 声明变量。由父组件传值过来
props: ['title','price','info','index']
}
</script>
<style>
.my-product {
width: 400px;
padding: 20px;
border: 2px solid #000;
border-radius: 5px;
margin: 10px;
}
</style>
总结: 父自定义事件和方法, 等待子组件触发事件给方法传值