Vue 之组件通信、页面刷新

主要记录在工作中对于父子组件之间的传值和刷新。
知识点我总是模糊,记录下来方便自己查看,欢迎大家给建议。
👉我的个人博客👈

组件通信

       这里我主要整理父子组件之间的通信,父子只是一个比喻,只要是存在组件的嵌套统称理解为父子组件,其实我更喜欢叫它们嵌套组件之间的传值。如果是子组件和子组件通信,好像 Vue 中并没有一个直接的传递方法,建议是把两个组件合并起来,一面后面造成不必要的麻烦,其实也可以使用状态管理工具 Vuex,可以很方便实现组件之间的参数传递,但是说实在的 Vuex 这个东西能不用咱就不使用,为什么呢?我师傅告诉我的。

父组件向子组件传值

       父组件向子组件传值还算是简单,我们把想要子组件接收的值动态绑定到子组件就可以了,子组件通过props进行接收。

父组件:

<template>
	<Son :msg="msg"></Son>
</template>
<script>
    export default {
        name:'Parent',
        data () {
            msg:'父组件传过来的信息'
        }
    }
</script>

子组件:

<template>
	<div>
        父组件传递过来的数据:{{ msg }}
    </div>
</template>
<script>
    export default {
        name:'Son',
        props:['msg']
    }
</script>

::: details 扩展

我在使用 Element 的 Dialog 组件时,在向上面这种操作的时候,控制台报错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: "chooseTable"大概的意思是我们子组件修改了父组件的值。

解决办法:

  • 通过prop传递过来的数据,不要直接在子组件中修改,既然是prop传递来的,父组件一定是在data中写好的属性。所以,监听data中的值(dialogVisible)也可以达到一样的效果 。

  • 在子组件中使用计算属性监听父组件传递的值。

    computed:{
        SonValue:{  // 使用 SonValue
            get(){
    			return this.msg
            }
            set(newValue){
    			return this.$emit('自定义事件',newValue)
            }
        }
    }
    

虽然是一个警告⚠️,但是瞅着就是难受😣

:::

子组件向父组件传值

​ 主要注意的一个点是 this.$emit(‘自定义事件’,<传递的值>),书写的时候 <>不写,我是为了方便看。

### .sync 使用

使用 sync 父组件就不需要去出发自定义函数了。

父组件:

<template>
	<Son :msg.sync="msg"></Son>
</template>
<script>
    export default {
        name:'Parent',
        data () {
            msg:'父组件传过来的信息'
        }
    }
</script>

子组件:

当我们点击 Button 按钮时,{{ msg }} 就变为:这是回传给父组件的值

<template>
	<div>
        父组件传递过来的数据:{{ msg }}
    </div>
	<Button @click="passValue">传递值给父组件</Button>
</template>
<script>
    export default {
        name:'Son',
        props:['msg'],
        methods:{
            passValue(){
                this.$emit('update:msg','这是回传给父组件的值')
            }
        }
    }
</script>

::: tip

​ 对于组件间的通信我觉得完好这两点暂时就可以了,下边说一说 Vue 页面刷新的问题。

:::

页面刷新

概念介绍

刚开始接触的时候,只是百度了一下拿来用用,最近在工作中踩了个坑,今天就来梳理一下。

我们在开发 Vue 项目的时候会有这么个需求,比如在删除或者增加一条记录的时候希望当前页面可以重新刷新: 这里我也是以刚才说的父子组件为例。

ref

ref被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向该子组件实例。

  • 在自身组件中使用则为获取这个 DOM 元素。

    • 调用使用 this.$refs.myDiv

      <div ref="myDiv">这是一个 div 盒子</div>
      
  • 在当前组件的子组件中使用,则可以调用子组件中的方法。

    • 调用使用this.$ref.组件 ref 定义的名字.组件定义的方法名

provide 和 inject

这里我只记录百度上常用的,也是最推荐的。

简单用法,刷新不需要参数:

​ 比如当我们打开一个 Dialog 后,我们添加完一条数据,我们想要列表刷新成一个最新的状态。

父组件:

<template>
  <div class="parent">
    <!-- 假如这是一个信息列表,当我们 dialog 确认后我们要刷新这个列表重新获取数据 -->
    <el-table :data="data"></el-table>
    <Son :dialogValue.sync="dialogValue" ></Son>
  </div>
</template>

<script>
import Son from './Son.vue'
export default {
  name:'Parent',
  data() {
    return {
      dialogValue:false
    }
  },
  provide:{   // 注入依赖
    return {
	  getListApi:this.getListApi
    }
  }
  methods:{
	// 模拟一个请求后台数据接口的方法
    async getListApi(){
   	  const tableList = await this.$axios({
          url:"http://xxx.xxxx.xxx",
          method:'GET'
      })
      this.data = tableList
    }
  },
  components:{
    Son
  }
}
</script>

子组件:

<template>
  <div class="son">
  <el-dialog
  title="提示"
  :visible.sync="dialogVisibleShow"
  width="30%"
  :before-close="handleClose">
    <span>这是一段信息</span>
    <span slot="footer" class="dialog-footer">
      <el-button @click="dialogVisible = false">取 消</el-button>
      <el-button type="primary" @click="insertData">确 定</el-button>
    </span>
  </el-dialog>
  </div>
</template>

<script>
export default {
  name:'Son',
  props:['dialogValue'],
  inject:['getListApi'], // 当 dialog 点击确定后,我们调用这个函数
  computed: {           // 使用计算属性,防止子组件直接修改父组件变量,这样只是通知
    dialogVisibleShow:{
      get(){
        return this.dialogValue
      }
      set(newValue){
        return this.$emit('update:dialogValue', false)
      }
    }
  },
  methods:{
    insertData(){
      // 执行 axios 成功后,我们刷新页面 
      this.getListApi() // 自动去调用父组件的获取数据的那个函数
      this.$emit('update:dialogValue', false)
    }
  },
  components:{
    Son
  }
}
</script>

复杂用法:刷新带参数

其实也不是很复杂,需要我们提前把参数保存下来。

​ 比如 有 A 组件,B 组件,C 组件。他们之间的关系是,A 是 B 的父组件,B 是 C 的父组件。
像这种情况,我们一般把 A 组件作为一个中介,A 组件来通知哪个组件需要做什么动作。

例如: B 是 A 的一个 Dialog,B 中每一个 item 有一个编辑,当点击编辑 弹出 C Dialog,当 C 中点击确定后成功插入数据后,重新获取 B 的列表数据。具体做法如下:

  1. 当点击 B 中点击编辑后,我们通过 this.$emit(‘自定义事件’,item) 让 A 触发,存储在 A 组件 data 的一个变量中(定义一个方法)。
  2. 我们在 A 中进行 provide 依赖注入,在 A 中再定义一个方法,内容为 this.$refs.<ref名字>.方法名(data中存储的那个item)
  3. B 则为我们需要刷新的列表,我们定义一个方法用来获取数据(名字为第二步中调用的方法名)
  4. 在 C 中 inject[‘A中注入的方法名’],当我们点击确定按钮时,我们调用 inject 中的方法,A 则会调用 B 的获取列表的方法,B 则会重新获取数据。

::: tip

因为结构有点复杂,这里我采用文字说明,虽然不能一目了然,但是你可以细细的品尝,总有一天会明白的。

:::

posted @ 2021-09-25 21:49  ayong6  阅读(241)  评论(0)    收藏  举报