问题:
当对话框 (Dialog)中包含子组件时,我们使用 this.$refs 试图获取该组件的 dom 并操作时,发现获取的 dom 为 undefined 导致后续的方法报错;
<template> <div> <el-dialog :visible.sync="propertyDialog" width="60%" center> <lineChart ref="chart" :xAxisArr="xAxisArr" :yAxisArr="yAxisArr" ></lineChart> </el-dialog> </div> </template> <script> import lineChart from "@/components/lineChart.vue"; export default { data() { return { xAxisArr: [], yAxisArr: [], propertyDialog: false, }; }, components: { lineChart, }, methods: { showCharts() { this.propertyDialog = true; console.log(this.$refs.chart); this.$refs.chart.drawLineChart(); }, }, }; </script>
解决:
因为自己之前用过 refs 来调用子组件方法,但是没有遇到过这种问题,很是无奈加之彷徨。
后来在度娘怀里遨游一番,发现和 element-ui 框架有关系,总之什么关系呢,我也说不清啦。
提示1: Dialog 的内容是懒渲染的,即在第一次被打开之前,传入的默认 slot 不会被渲染到 DOM 上。 因此,如果需要执行 DOM 操作,或通过 ref 获取相应组件,请在 open 事件回调中进行。 提示2: 如果 visible 属性绑定的变量位于 Vuex 的 store 内,那么 .sync 不会正常工作。 此时需要去除 .sync 修饰符,同时监听 Dialog 的 open 和 close 事件, 在事件回调中执行 Vuex 中对应的 mutation 更新 visible 属性绑定的变量的值。
加上一个 this.$nextTick 就可以啦,这个回调函数的意思呢?
官方的用法说明:将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。
它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。
其实简单理解就是:等所有的DOM元素节点都渲染完成以后才执行其里面的方法。
具体什么意思呢, 请参考:Vue中 $nextTick() 与 Vue.nextTick() 原理及使用
showCharts(params) { this.propertyDialog = true; this.$nextTick(()=>{ console.log(this.$refs.chart); this.$refs.chart.drawLineChart(); }) },