vue+element-ui el-dialog嵌套table组件,ref问题,toggleRowSelection的undefined

设置El-Dialog中Table默认选中
本文介绍如何在Element UI的El-Dialog组件内,通过子组件V-Table实现Table组件默认选中行的功能。关键步骤包括:在V-Table组件中设置selectCheck方法,父组件传递选中行ID给子组件,使用$nextTick确保DOM加载完成后再调用selectCheck方法。

项目需求,返回数据的时候,el-dialog弹窗里面的table组件需要设置默认选中。

要设置选中,则要调用table组件默认的toggleRowSelection(row,true)方法,true默认选中。

问题:el-diaglog组件里面的table组件时自定义的组件。

<el-dialog title="选择用户"
               :width="dialogWidth"
               v-if="isDialog"
               :visible.sync="isDialog">
      <v-table ref="elTable"
               :data="resultData"
               :columns="columns"
               :checkbox="checkbox"
               :selectRow="selectRow"
               loading
               @handleCurrentChange="handleCurrentChange"
               @handleSelectionChange="handleSelectionChange">
      </v-table>
    </el-dialog>

这时候要设置默认选中

1、在v-table组件里面设置selectCheck方法。

<template>
  <div class="table-container">
    <el-table border
                  ref="multipleTable"
                  :data="data.records"
                  v-loading='$store.state.tableLoading'
                  @selection-change="handleSelectionChange">
          <el-table-column fixed
                           v-if="checkbox"
                           type="selection"
                           align="center"
                           width="50">
          </el-table-column>       

          <template v-for="(item, index) in columns">
            <slot :name='item.slot'
                  v-if='item.slot' />
            <component v-else-if="item.component"
                       :is="item.component"
                       :column="item"
                       :key="index" />

            <el-table-column :key="index"
                             v-bind="item"
                             v-else
                             align="center" />
          </template>
        </el-table>
  </div>
</template>

<script>
export default {
  name: 'v-table',
  props: {
    loading: {
      type: Boolean,
      default: false
    },
    checkbox: {
      type: Boolean,
      default: false
    },
    data: { // 父组件传递过来的table数据
      type: [Object, Array],
      default: () => { }
    },
    columns: {
      type: Array,
      default: () => []
    },
    height: {
      type: [String, Number],
      default: 0
    },
    selectRow: {  //父组件传递过来的要选中的行的id
      type: Array,
      default: null
    }
  },
  data () {
    return {
    }
  },
  created () {
  },
  mounted () {
  },
  methods: {
    selectCheck () {
      this.data.records.forEach(item => {
        for (let i in this.selectRow) {
          if (item.id === this.selectRow[i]) {
            this.$refs.multipleTable.toggleRowSelection(item, true)
          }
        }
      })
    },

    handleSelectionChange (val) {
      this.$emit('handleSelectionChange', val)
    }
  }
}
</script>
<style lang="scss" scoped>
</style>

2、父组件传递选中的行的id给子组件,父子组件传值,大家都知道就不多说了。

selectRow: []

3、父组件调用自组件的方法,在子组件上设置ref

这里在父组件调用子组件的selectCheck()方法

this.$refs.elTable.selectCheck()

注意,因为table组件在dialog弹框里,所以为了避免dialog显示时dom还没有加载完成,所以要使用this.$nextTick()

点击显示弹框的方法里:

this.isDialog = true
this.$nextTick(() => {
        this.$refs.elTable.selectCheck()
 })

4、获取表格中选中的行

handleSelectionChange (val) {
      this.values= val
    },

 

<think> 在Element UI中,`ref`并不是Element UI特有的属性,而是Vue.js框架提供的一个核心特性。Element UI组件可以使用`ref`属性,因为它是基于Vue构建的。`ref`被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的`$refs`对象上。 ### 1. `ref`的基本概念 - `ref` 被用来给元素或子组件注册一个引用标识 - 这个引用标识会添到父组件的 `$refs` 对象中 - 如果在普通的DOM元素上使用,引用指向的就是那个DOM元素 - 如果在子组件上使用,引用就指向组件实例 ### 2. 使用场景 1. **操作DOM元素**:当需要直接操作DOM时(如聚焦输入框、测量元素尺寸等) 2. **调用子组件方法**:父组件需要直接调用子组件的方法 3. **访问子组件数据**:父组件需要直接访问子组件的数据(虽然通常推荐使用props和events进行通信) ### 3. 在Element UI组件中使用`ref` 以下是一些常见的Element UI组件使用`ref`的例子: #### 示例1:表单验证 ```vue <template> <el-form ref="myForm" :model="formData" :rules="rules"> <el-form-item prop="name" label="姓名"> <el-input v-model="formData.name"></el-input> </el-form-item> <el-button @click="submitForm">提交</el-button> </el-form> </template> <script> export default { data() { return { formData: { name: '' }, rules: { name: [{ required: true, message: '请输入姓名', trigger: 'blur' }] } }; }, methods: { submitForm() { // 通过ref获取表单组件实例并调用验证方法 this.$refs.myForm.validate(valid => { if (valid) { alert('提交成功!'); } else { alert('表单验证失败!'); return false; } }); } } }; </script> ``` #### 示例2:操作对话框 ```vue <template> <div> <el-button @click="openDialog">打开对话框</el-button> <el-dialog ref="myDialog" title="提示" :visible.sync="dialogVisible"> 内容 <span slot="footer"> <el-button @click="closeDialog">关闭</el-button> </span> </el-dialog> </div> </template> <script> export default { data() { return { dialogVisible: false }; }, methods: { openDialog() { this.dialogVisible = true; // 通过ref获取对话框组件实例并调用其方法(如果有) // 例如:this.$refs.myDialog.someMethod(); }, closeDialog() { this.dialogVisible = false; } } }; </script> ``` ### 4. 需要注意的问题 1. **`ref` 不是响应式的**:`$refs` 对象不是响应式的,因此不应该在模板或计算属性中使用它们。 2. **渲染时机**:`ref` 本身是作为渲染结果被创建的,在初始渲染时不能访问它们(因为此时它们还不存在),需要在 `mounted` 生命周期之后才能访问。 3. **避免过度使用**:在大多数情况下,应该优先使用 props 和 events 进行父子组件通信,而不是依赖 `ref`。 ### 5. 访问 `$refs` 的时机 ```javascript export default { mounted() { // 此时组件已经挂载,可以访问refs console.log(this.$refs.myInput); // 如果存在的话 if (this.$refs.myInput) { this.$refs.myInput.focus(); } } }; ``` ### 6. 在列表中使用 `ref` 当在 `v-for` 中使用 `ref` 时,`$refs` 会得到一个数组(Vue 2.x)或一个包含DOM元素和组件实例的对象(Vue 3.x)。在Vue 2.x中: ```vue <template> <div> <div v-for="i in 3" :key="i" ref="items">{{ i }}</div> </div> </template> <script> export default { mounted() { // 在Vue 2.x中,$refs.items 是一个数组 console.log(this.$refs.items); // [div, div, div] } }; </script> ``` ### 7. 在Vue 3中的变化 在Vue 3中,当在 `v-for` 内部使用 `ref` 时,`$refs` 将不会自动创建数组。你需要使用函数形式的 `ref` 来手动处理(或者使用新的 `reactive` API)。 ### 总结 在Element UI组件中使用 `ref` 与在普通Vue组件中使用方式相同,主要用于: - 直接访问DOM元素 - 访问子组件实例并调用其方法 - 在需要时直接操作子组件 §§相关问题§§: 1. Vue.js中ref和reactive的区别是什么? 2. 如何在Vue 3的组合式API中使用ref? 3. Element UI中哪些组件的方法需要通过ref调用? 4. 为什么说过度使用ref是不好的实践? </think> # Element UIref 的深度解析 在 Vue.js 框架及其 UIElement UI 中,`ref` 是一个非常重要的特性,用于直接访问 DOM 元素或组件实例。以下是关于 `ref` 的全面解析。 ## ref 的基本概念 `ref` 是 Vue.js 提供的一个特殊属性,用于注册对 DOM 元素或子组件的引用。在 Element UI 中,它常用于访问组件实例以调用其方法或访问其属性。 ```vue <template> <el-button ref="myButton">点击我</el-button> </template> <script> export default { mounted() { // 通过ref访问Element UI按钮组件实例 console.log(this.$refs.myButton); // 调用Element UI按钮的方法 this.$refs.myButton.focus(); // 访问按钮的属性 console.log(this.$refs.myButton.size); } } </script> ``` ## Element UIref 的常见使用场景 ### 1. 表单验证 ```vue <template> <el-form ref="loginForm" :model="form" :rules="rules"> <el-form-item prop="username"> <el-input v-model="form.username"></el-input> </el-form-item> <el-button @click="submitForm">提交</el-button> </el-form> </template> <script> export default { data() { return { form: { username: '' }, rules: { username: [{ required: true, message: '请输入用户名', trigger: 'blur' }] } }; }, methods: { submitForm() { // 通过ref访问表单组件并调用验证方法 this.$refs.loginForm.validate(valid => { if (valid) { console.log('表单验证通过'); } else { console.log('表单验证失败'); return false; } }); } } }; </script> ``` ### 2. 访问对话框组件 ```vue <template> <div> <el-button @click="openDialog">打开对话框</el-button> <el-dialog ref="myDialog" title="提示" :visible.sync="dialogVisible"> 对话框内容 </el-dialog> </div> </template> <script> export default { data() { return { dialogVisible: false }; }, methods: { openDialog() { this.dialogVisible = true; // 访问对话框组件属性 console.log(this.$refs.myDialog.title); // 调用对话框方法(如果有) // this.$refs.myDialog.someMethod(); } } }; </script> ``` ### 3. 操作表格组件 ```vue <template> <el-table ref="dataTable" :data="tableData"> <el-table-column prop="date" label="日期"></el-table-column> <el-table-column prop="name" label="姓名"></el-table-column> </el-table> <el-button @click="clearSelection">清除选择</el-button> </template> <script> export default { data() { return { tableData: [ { date: '2023-01-01', name: '张三' }, { date: '2023-01-02', name: '李四' } ] }; }, methods: { clearSelection() { // 调用表格组件的clearSelection方法 this.$refs.dataTable.clearSelection(); } } }; </script> ``` ## ref 的工作原理 1. **注册引用**:当组件渲染时,Vue 会收集所有带有 `ref` 属性的元素或组件 2. **添到 $refs 对象**:这些引用被添到父组件的 `$refs` 对象中 3. **访问时机**:引用只能在组件挂载后访问(`mounted` 生命周期钩子之后) 4. **非响应式**:`$refs` 对象不是响应式的,不应在模板中使用 ```javascript // 访问 ref 的正确时机 export default { mounted() { // 此时可以安全访问 refs console.log(this.$refs.myElement); }, updated() { // 在更新后也可以访问 } } ``` ## ref 的高级用法 ### 在循环中使用 ref ```vue <template> <div v-for="item in items" :key="item.id"> <el-input :ref="`input_${item.id}`" v-model="item.value"></el-input> </div> </template> <script> export default { data() { return { items: [ { id: 1, value: '' }, { id: 2, value: '' } ] }; }, methods: { focusInput(id) { // 访问动态创建的 ref const refName = `input_${id}`; // 注意:在 v-for 中 ref 会返回数组 if (this.$refs[refName] && this.$refs[refName][0]) { this.$refs[refName][0].focus(); } } } }; </script> ``` ### 使用函数式 ref ```vue <template> <el-input :ref="setInputRef"></el-input> </template> <script> export default { data() { return { inputRef: null }; }, methods: { setInputRef(el) { // 当组件挂载/更新时调用 this.inputRef = el; if (el) { console.log('元素已挂载', el); } }, focusInput() { if (this.inputRef) { this.inputRef.focus(); } } } }; </script> ``` ## ref 使用的最佳实践 1. **避免过度使用**:只在必要时使用 ref,优先使用 props 和 events 2. **检查存在性**:访问前检查引用是否存在 `if (this.$refs.myRef)` 3. **考虑生命周期**:确保在组件挂载后访问 ref 4. **命名规范**:使用有意义且一致的命名(如 `formRef`, `tableRef`) 5. **避免直接操作 DOM**:优先使用组件方法和属性 ## refVue 3 Composition API 中的使用 ```vue <template> <el-input ref="inputRef"></el-input> </template> <script> import { ref, onMounted } from 'vue'; export default { setup() { const inputRef = ref(null); onMounted(() => { // 访问 DOM 元素或组件实例 console.log(inputRef.value); if (inputRef.value) { inputRef.value.focus(); } }); return { inputRef }; } }; </script> ``` ## 常见问题解决 ### ref 返回 undefined 的解决方法 ```javascript export default { methods: { handleClick() { // 使用 $nextTick 确保 DOM 已更新 this.$nextTick(() => { if (this.$refs.myElement) { this.$refs.myElement.doSomething(); } }); } } } ``` ### 访问嵌套组件 ```vue <template> <parent-component ref="parent"> <child-component ref="child"></child-component> </parent-component> </template> <script> export default { mounted() { // 访问父组件 console.log(this.$refs.parent); // 访问子组件(通过父组件的引用) console.log(this.$refs.parent.$refs.child); } }; </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LLL_LH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值