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 的列表数据。具体做法如下:
- 当点击 B 中点击编辑后,我们通过 this.$emit(‘自定义事件’,item) 让 A 触发,存储在 A 组件 data 的一个变量中(定义一个方法)。
- 我们在 A 中进行 provide 依赖注入,在 A 中再定义一个方法,内容为 this.$refs.<ref名字>.方法名(data中存储的那个item)
- B 则为我们需要刷新的列表,我们定义一个方法用来获取数据(名字为第二步中调用的方法名)
- 在 C 中 inject[‘A中注入的方法名’],当我们点击确定按钮时,我们调用 inject 中的方法,A 则会调用 B 的获取列表的方法,B 则会重新获取数据。
::: tip
因为结构有点复杂,这里我采用文字说明,虽然不能一目了然,但是你可以细细的品尝,总有一天会明白的。
:::

浙公网安备 33010602011771号