探索Vue组件通信的秘密:打破隔阂,实现数据共享

一、Vue组件通信

  • 每个组件都有自己的数据, 提供在data中, 每个组件的数据是独立的, 组件数据无法互相直接访问 (合理的)
  • 但是如果需要跨组件访问数据, 就需要用到组件通信
    探索Vue组件通信的秘密:打破隔阂,实现数据共享_第1张图片
  • 要是有一万个商品????就要写一万个吗?探索Vue组件通信的秘密:打破隔阂,实现数据共享_第2张图片
  • 函数调用:看起来调用时用一个函数,执行结果效果都是不一样? 设置形参?在调用的时候传入实参?

特别函数:
1、设置组组件内所有特别,形参
2、组件调用的时候,传入所谓的实参?

(一)组件通信—父传子

1. 组件通信 - 父传子 props 传值

  • 父传子的基本语法:
  • ①、父组件通过给子组件加属性传值
<!-- 3.所谓调用函数:传实参 -->
<cpt-4 title="超级好吃的口水鸡" price="50" num="8"></cpt-4>
<cpt-4 title="泰国榴莲" price="288" num="6"></cpt-4>
  • ②、子组件中, 通过props属性接收
props:["title","price","num"]//1. 设置形参,语法固定
  • 创建components/04-cpt.vue子组件文件,子组件中, 通过props属性接收。
<template>
  <div class="box">
    
    <h3>标题:{{ title }}h3>
    <p>价格:{{price}}元p>
    <p>开业大酬宾,全场{{num}}折p>
  div>
template>
<script>
export default {
    // 特别封装:如何设置所谓的形参
    props:["title","price","num"]//1. 设置形参,语法固定
}
script>
<style scoped>
    .box{
        border:1px solid black;
    }
style>
  • App.vue父组件里面调用cpt4子组件,父组件通过给子组件加属性传值。
<template>
  <div>
    <h1>超市商品列表:h1>
    
    <cpt-4 title="超级好吃的口水鸡" price="50" num="8">cpt-4>
    <cpt-4 title="泰国榴莲" price="288" num="6">cpt-4>
  div>
template>
<script>
import cpt4 from "./components/04-cpt.vue"
export default {
  components:{
    cpt4,
  }
}
script>

探索Vue组件通信的秘密:打破隔阂,实现数据共享_第3张图片

  • 在data里面传递数据,通过实参来传递形参的值。
<template>
  <div>
    <h1>超市商品列表:h1>
    
    <cpt-4 :title="title" :price="price" :num="num">cpt-4>
  div>
template>
<script>
import cpt4 from "./components/04-cpt.vue"
export default {
  components:{
    cpt4,
  },
  data(){
    return{
      title:"火鸡面",
      price:10,
      num:5
    }
  }
}
script>

探索Vue组件通信的秘密:打破隔阂,实现数据共享_第4张图片探索Vue组件通信的秘密:打破隔阂,实现数据共享_第5张图片

  • 利用父传子,可以往子组件传递数据。
  • 父传子的基本步骤是什么?
    父组件内, 给子组件添加属性的方式传值
    子组件内, 通过 props 接收

2. v-for 遍历展示组件练习

  • 以后的数据,都是从后端来的,那如何渲染的呢? 我们可以循环的使用组件吗?要是可以使用,那又如何往组件里面传值呢?
  • 需求: 遍历展示商品列表
  • ①、假定, 发送请求回来的商品数据,
list:[
	{id:1,title:"good-1",price:10,num:8},
	{id:2,title:"good-2",price:88,num:8},
	{id:3,title:"good-3",price:99,num:8},
]
  • ②、v-for 遍历展示
<template>
  <div>
    <h1>超市商品列表:h1>
    
    <cpt-4 v-for="item in list" :key="item.id" :title="item.title" :price="item.price" :num="item.num">cpt-4>
  div>
template>
<script>
import cpt4 from "./components/04-cpt.vue"
export default {
  components:{
    cpt4,
  },
  data(){
    return{
      title:"火鸡面",
      price:10,
      num:5,
      list:[
			{id:1,title:"good-1",price:10,num:8},
			{id:2,title:"good-2",price:88,num:8},
			{id:3,title:"good-3",price:99,num:8},
		]
    }
  }
}
script>

探索Vue组件通信的秘密:打破隔阂,实现数据共享_第6张图片探索Vue组件通信的秘密:打破隔阂,实现数据共享_第7张图片

3. 单向数据流

探索Vue组件通信的秘密:打破隔阂,实现数据共享_第8张图片

  • 在vue中需要遵循单向数据流原则: (从父到子的单向数据流动, 叫单向数据流)
 在vue中需要遵循单向数据流原则
 1. 父组件的数据发生了改变,子组件会自动跟着变
 2. 子组件不能直接修改父组件传递过来的props  props是只读的
  • 如果父组件传给子组件的是一个对象,子组件修改对象的属性,是不会报错的,,,,也应该避免

(二)组件通信—子传父

  • 创建components/04-cpt.vue子组件文件。
<template>
  <div class="box">
    
    <h3>标题:{{ title }}h3>
    <p>价格:{{price}}元p>
    <p>开业大酬宾,全场{{num}}折p>
    <h4>库存:{{ kc }}件h4>
    <button @click="kc--">卖一件button>
  div>
template>
<script>
export default {
    props:["title","price","num","kc"]//1.设置形参,语法固定
}
script>
<style scoped>
    .box{
        border:1px solid black;
    }
style>
  • App.vue父组件里面调用cpt4子组件,父组件通过给子组件加属性传值。
<template>
  <div>
    <h1>超市商品列表:h1>
    
    <p v-for="item in list" :key="item.id" >{{ item.title }} 库存:{{ item.kc }}p>
    <hr>
    <cpt-4 
      v-for="item in list"  :key="item.id"  :title="item.title"  :price="item.price"  :num="item.num" :kc="item.kc">cpt-4>
  div>
template>
<script>
import cpt4 from "./components/04-cpt.vue";
export default {
  components:{
    cpt4,
    cpt5,
  },
  data(){
    return{
      title:"火鸡面",
      price:10,
      num:5,
      list:[
        {id:1,title:"good-1",price:10,num:8,kc:10,},
        {id:2,title:"good-2",price:88,num:8,kc:33,},
        {id:3,title:"good-3",price:99,num:8,kc:66,},
      ]
    }
  }
}
script>

探索Vue组件通信的秘密:打破隔阂,实现数据共享_第9张图片探索Vue组件通信的秘密:打破隔阂,实现数据共享_第10张图片

  • 卖一件:
    ①、子组件自己kc- -
    ②、报错:数据是父级给的,如果要修改数据,应该是让父级去修改数据
    规定:子组件不能直接去修改父组件传入的数据!不然会造成数据紊乱!

1. 子传父组件通信

  • 子传父基本语法
  • ①、子组件可以通过 this.$emit('事件名', 参数1, 参数2, ...) 触发事件的同时传参的
  • 创建04-cpt.vue子组件,内置封装好方法emit发射this.$emit("通道名称,要发送的数据,...)
<template>
  <div class="box">
    <h3>标题:{{ title }}</h3>
    <p>价格:{{price}}</p>
    <p>开业大酬宾,全场{{num}}</p>
    <h4>库存:{{ kc }}</h4>
    <button @click="fn">卖一件</button>
  </div>
</template>

<script>
export default {
    // 特别封装:如何设置所谓的形参
    props:["title","price","num","kc","id"],//1.设置形参id
    //接受父级给的id、唯一标识、身份证
    //发信号给父级:告诉父级自己是挪个!
    methods:{
        fn(){
            // 2. 发送信号:内置封装好方法emit发射this.$emit("通道名称,要发送的数据,...)
            this.$emit("aaa",this.id);
        }
    }
}
</script>
<style scoped>
    .box{
        border:1px solid black;
    }
</style>
  • ②、父组件给子组件注册一个自定义事件、父组件可以给子组件设置相应的接受通道名称
<template>
  <div>
    <h1>超市商品列表:h1>
    
    <p v-for="item in list" :key="item.id" >{{ item.title }} 库存:{{ item.kc }}p>
    <hr>
    <cpt-4 
      v-for="item in list" 
      :key="item.id" 
      :title="item.title" 
      :price="item.price" 
      :num="item.num"
      :kc="item.kc"
      :id="item.id"

      @aaa="fnn"
    >cpt-4>
    
  div>
template>
  • ③、父组件并提供对应的函数接收参数
<script>
export default {
  methods:{
    fnn(id){
      //
      console.log(id);
    }
  },
}
script>
  • App.vue父组件里面调用cpt4子组件,父组件通过给子组件加属性传值。
<template>
  <div>
    <h1>超市商品列表:h1>
    
    <p v-for="item in list" :key="item.id" >{{ item.title }} 库存:{{ item.kc }}p>
    <hr>
    <cpt-4 
      v-for="item in list" 
      :key="item.id" 
      :title="item.title" 
      :price="item.price" 
      :num="item.num"
      :kc="item.kc"
      :id="item.id"

      @aaa="fnn"
    >cpt-4>
    
  div>
template>

<script>
import cpt4 from "./components/04-cpt.vue";
export default {
  components:{
    cpt4,
  },
  methods:{
    fnn(id){
      console.log(id);
      //业务:find把符合条件成员单独跳出来,新数组
      let i = this.list.findIndex(ele=>ele.id==id);
      this.list[i].kc--;//找到到对应对象库存-1
    }
  },
  data(){
    return{
      title:"火鸡面",
      price:10,
      num:5,
      list:[
        {id:1,title:"good-1",price:10,num:8,kc:10,},
        {id:2,title:"good-2",price:88,num:8,kc:33,},
        {id:3,title:"good-3",price:99,num:8,kc:66,},
      ]
    }
  }
}
script>

探索Vue组件通信的秘密:打破隔阂,实现数据共享_第11张图片

2. 形参和实参用同一个地址

  • 创建04-cptPlus.vue文件,形参一会要接受一个对象
<template>
  <div class="box">
    <h3>标题:{{ item.title }}h3>
    <p>价格:{{item.price}}元p>
    <p>开业大酬宾,全场{{item.num}}折p>
    <h4>库存:{{ item.kc }}件h4>
    <button @click="item.kc--">卖一件button>
  div>
template>
<script>
export default {
      //item:语义化知道,形参一会要接受一个对象
      props:["item"],
}
script>
<style scoped>
    .box{
        border:1px solid black;
    }
style>
  • App.vue里面直接调用
<template>
  <div>
    <h1>超市商品列表:h1>
    
    <p v-for="item in list" :key="item.id" >{{ item.title }} 库存:{{ item.kc }}p>
    <hr>
    <cptPlus-4 
      v-for="item in list" 
      :key="item.id" 
      :item="item"
    >cptPlus-4>
  div>
template>
<script>
import cptPlus4from "./components/04-cptPlus.vue";
export default {
  components:{
    cptPlus4,
  },
  methods:{
    fnn(id){
      //业务:find把符合条件成员单独跳出来,新数组
      let i = this.list.findIndex(ele=>ele.id==id);
      this.list[i].kc--;//找到到对应对象库存-1
    }
  },
  data(){
    return{
      title:"火鸡面",
      price:10,
      num:5,
      list:[
        {id:1,title:"good-1",price:10,num:8,kc:10,},
        {id:2,title:"good-2",price:88,num:8,kc:33,},
        {id:3,title:"good-3",price:99,num:8,kc:66,},
      ]
    }
  }
}
script>
  • 最后的效果也是一样的。!!!!

(三)props 校验

  • props 是父传子, 传递给子组件的数据, 为了提高 子组件被使用时 的稳定性, 可以进行props校验, 验证传递的数据是否符合要求。
  • 默认的数组形式, 不会进行校验, 如果希望校验, 需要提供对象形式的 props
  • 创建05-cpt.vue子组件,设置形参以及对象配置的要求。
<template>
  <div>
    <h1>数量:{{ num }}h1>
  div>
template>
<script>
export default {
  props:{
    //形参名称:对象配置有要求
    num:{
      type:Number,//数字类型
      require:true,//必传项
      default:100,//默认值
    }
  }
}
script>
  • App.vue父组件里面调用cpt5子组件,父组件通过给子组件加属性传值。
<template>
  <div>
    <h1>超市商品列表:h1>
    <cpt-5 num="800">cpt-5>
  div>
template>
<script>
import cpt5 from "./components/05-cpt.vue";
export default {
  components:{
    cpt5,
  },
}
script>

探索Vue组件通信的秘密:打破隔阂,实现数据共享_第12张图片探索Vue组件通信的秘密:打破隔阂,实现数据共享_第13张图片

  • props 提供了多种数据验证方案,例如:
  • 基础的类型检查 Number
  • 多个可能的类型 [String, Number]
  • 必填项校验 required: true
  • 默认值 default: 100
  • 自定义验证函数

你可能感兴趣的:(Vue,vue.js,前端,javascript)