前言

父子组件间的通信,组件可以说是一个具有独立功能的整体,但是当我们要将这些组件拼接在一起时,这些组件相互之间要建立联系,这个联系我们就称之为通信

一、简单案例

html

<body>
    <div id="app">
        <Scholar></Scholar>
    </div>

    <!-- 初学者模板 -->
    <template id="scholar">
        <div>
          <h3> 初学者 </h3>
          <h3> 技术回应到: {{show}} </h3>
          <hr>
          <!-- 父组件传参 :参数='值' ,@responses是子组件定义的 response自己定义的方法-->
          <technology :language='language' @responses='response'/>
        </div>
    </template>

    <!-- 学习语言 -->
    <template id='technology'>
        <div>
          <h3> 初学者要学的技术语言 {{language}}</h3>
          <button @click="responses">回应</button>
        </div>
    </template>
</body>

script

<script>
        // 父组件
        Vue.component('scholar',{
            template: '#scholar',
            data () {
                return {
                    // 参数
                    language: ['Java','前端','PHP'],
                    // 接收响应渲染
                    show: ''
                }
            },
            methods: {
                // 接收语言响应
                response (data) {
                    this.show=data
                }
            }
          })
        // 子组件
        Vue.component('technology',{
            template: '#technology',
            // 子组件接收参数
            props: {
                // 接收父组件参数名
                language: []
            },
            methods: {
                // 回应的单击事件
                responses () {
                   // 将数据传回父组件
                   this.$emit('responses','你就这样,先别急于求成,先学前端吧')
                }
            }
            
        })
        
          new Vue({
            
          }).$mount('#app')
        
        </script>

这是用 props 实现的

测试效果

在这里插入图片描述

在这里插入图片描述

二、项目实践案例(只提供部分代码)

需求

在开发中常用到搜索功能,搜索功能页面几乎都是一样的,需要将搜索单独的剥离,从而提高代码的复用性和扩展性。
在这里插入图片描述
在这里插入图片描述

父组件

<template>
<!-- @search='search'指接收子组件事件, selectOptions下拉框参数,selectValue下拉框默认参数 -->
<selectAndDateSearch @search='search' :selectOptions='selectOptions' :selectValue='selectValue'></selectAndDateSearch>
</template>
import selectAndDateSearch from '@/components/SelectAndDateSearch'

export default {
  // 子组件
  components: {
    selectAndDateSearch
  },
  data () {
    return {
      // 将参数传给子组件
      selectOptions: ['传感器id', '医院id', '医院id2'],
      selectValue: '传感器id',
      searchValue: ''
    }
  },
  methods: {
      search (data) {
      //子组件传参响应
      }
  }
  }

子组件

<template>
  <div class = "device-list-main">
    <div class ="header">
      <div class="header_title">
        <cube-select v-model="selectChildValue" :options="selectOptions" ></cube-select>
      </div>
      <div class="header_input">
        <cube-input v-model="searchValue" placeholder="请输入搜索值" :maxlength=30 ></cube-input>
        <div class="header_input_btn" @click="clickGetDeviceInfo()">
          <img src="../../static/img/search.png">
        </div>
      </div>
    </div>
    <div class="header">
      <cube-input v-on:focus="showMinPicker('startTime')" v-model="startTime" placeholder="开始时间" :maxlength=30 style="width: 50%;"></cube-input>
      <span></span>
      <cube-input v-on:focus="showMinPicker('endTime')" v-model="endTime" placeholder="结束时间" :maxlength=30 style="width: 50%;"></cube-input>
    </div>
  </div>
</template>
<script>
import datwTimeUtil from '@/utils/dateTimeUtil'
import emptyUtil from '@/utils/emptyUtil'
export default {
  data () {
    return {
      // 避免和父组件传的值冲突,爆:父组件传的值传进子组件就被修改 违反了vue的数据流
      selectChildValue: this.selectValue,
      // 填写的值
      searchValue: '',
      // 开始时间
      startTime: '',
      // 结束时间
      endTime: '',
      // 时间标识
      timeIdentifying: '',
      pageable: {
        // 
        sensorImei: '',
        // 
        hospitalName: '',
        // 
        saleChanelName: '',
        // 开始时间
        startTime: '',
        // 结束时间
        endTime: '',
        // 下拉框标识
        selectValue: ''
      }
    }
  },
  // 接收父组件传的参数
  props: {
    // 父组件传参(选择的value数组)
    selectOptions: [],
    // 父组件传参(默认选择)
    selectValue: String
  },
  methods: {
    // 点击搜索事件
    clickGetDeviceInfo () {
      if (emptyUtil.stringIsNotBlank(this.selectChildValue)) {
        this.pageable.selectValue = this.selectChildValue
        this.pageable.sensorImei = (this.selectChildValue === '传感器id' ? this.searchValue : '')
        this.pageable.hospitalName = (this.selectChildValue === '医院id' ? this.searchValue : '')
        this.pageable.saleChanelName = (this.selectChildValue === '医院id2' ? this.searchValue : '')
      }
      console.log('this.pageable:', this.pageable)
      // 向父组件传参
      this.$emit('search', this.pageable)
    },
    // 监听出发选择时间
    showMinPicker (time) {
      if (!this.minPicker) {
        this.minPicker = this.$createDatePicker({
          title: '选择时间',
          visible: true,
          min: new Date(2000, 0, 1),
          max: new Date(2099, 12, 1),
          value: new Date(),
          format: {
            year: 'YYYY',
            month: 'MM',
            date: 'DD'
          },
          columnCount: 3,
          onSelect: this.selectHandler,
          onCancel: this.cancelHandler
        })
      }
      // 选择时间标识
      this.timeIdentifying = time
      this.minPicker.show()
    },
    selectHandler (selectedTime, selectedText, formatedTime) {
      let date = datwTimeUtil.getFormatDate(selectedTime)
      if (this.timeIdentifying === 'startTime') {
        this.startTime = date
        this.pageable.startTime = date
      } else if (this.timeIdentifying === 'endTime') {
        this.endTime = date
        this.pageable.endTime = date
      }
    },
    // 取消事件
    cancelHandler () {
      if (this.timeIdentifying === 'startTime') {
        this.startTime = ''
        this.pageable.startTime = ''
      } else if (this.timeIdentifying === 'endTime') {
        this.endTime = ''
        this.pageable.endTime = ''
      }
    }
  }
}
</script>

4.效果展示

在这里插入图片描述

问题

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: "selectValue"

大概报错意思:父组件传的值传进子组件就被修改 违反了vue的数据流

解决

将父组件传过来的值赋给另一个值v-model绑定,这样就不会影响到父组件传过来的值(类似在java中类似值传递,拷贝时,两个变量互不干扰。
例子:

<!-- selectChildValue下拉框数组,selectOptions显示的值 -->
<cube-select v-model="selectChildValue" :options="selectOptions" ></cube-select>
data () {
    return {
      // 重点: 避免和父组件传的值冲突,爆:父组件传的值传进子组件就被修改 违反了vue的数据流
      selectChildValue: this.selectValue,
      },
  props: {
    // 父组件传参(选择的value数组)
    selectOptions: [],
    // 父组件传参(默认选择)
    selectValue: String
  },
}
Logo

前往低代码交流专区

更多推荐