VUE3 + element-plus, this.$emit失效,为什么?

新手上路,请多包涵

VUE3 + element-plus,子组件向父组件发送消息(调用父组件函数没有反应),this.$emit方法,请大佬们帮俺看看,谢谢
image.png
image.png
image.png
全部的代码

<template>
  <!--  <el-text class="mx-1">条件 {{": "}}</el-text>-->
  <div style="margin-bottom: 10px" v-if="dynamicTags.length !=0">
    <el-text tag="b"> 条件:</el-text>
    <el-tag v-for="tag in dynamicTags"
            :key="tag"
            :size="'default'"
            :hit="true"
            closable
            :disable-transitions="false"
            @close="handleClose(tag)"
            style="margin-left: 10px"
            effect="dark"
            round
    >
      {{ tag }}
    </el-tag>
  </div>
  <div>
    <el-table :data="tableData" style="width: 100%" max-height="500" border stripe highlight-current-row
              @header-click="headClick"
              @selection-change="handleSelectionChange"
    >
      <el-table-column
          v-for="[p,f] in props"
          :prop="p"
          :label="p"
          :fixed="f"
          :width="150"
          :align="'center'"
          :sortable="true"
          :min-width="100"
      >
        <template #header>
          <newnew v-if="click_value==p" :column="p" :column_filter_type="'scope'"
                  :select_items="select_item"></newnew>
        </template>
      </el-table-column>
      <el-table-column label="Info" width="150" :align="'center'">
        <template #default="scope">
          <el-button type="primary" size="small" @click="more_about(scope.$index)"
          >ShowMore
          </el-button
          >
        </template>
      </el-table-column>
      <el-table-column type="selection" width="55" :fixed="'right'"/>
    </el-table>
    <el-pagination
        style="margin-top : 10px; text-align:center"
        v-model:current-page="currentPage3"
        v-model:page-size="pageSize3"
        :small=true
        :background=true
        layout="total, prev, pager, next, jumper"
        :total="100"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
    />
  </div>
</template>

<script lang="ts" setup>
import {get_filter_type, legal_judge, zip} from '../../api/utils'
import {nextTick, ref} from 'vue'
import {ElMessage, ElMessageBox, ElInput} from 'element-plus'
import type {Action} from 'element-plus'
import {getTableData, getTableProps} from "../../api/test-data"
import customHeader from "./customHeader.vue";
import newnew from "./newnew.vue"

let click_value = ref("")
let pageSize3 = ref(20)
let currentPage3 = ref(1)

function handleSizeChange(value) {
  // 页面大小改变
  console.log("handleSizeChange " + value)
}

function handleCurrentChange(value) {
  // 当前页码改变
  console.log("handleCurrentChange " + value)
}

function log() {
  console.log("stop")
}


const row_labels = getTableProps()
const tableData = getTableData()
const fixed = Array(row_labels.length)
fixed[0] = true
for (let i = 1; i < row_labels.length; i++) {
  fixed[i] = false
}
const props = zip(row_labels, fixed)

const inputValue = ref('')
const dynamicTags = ref(['Tag 1', 'Tag 2', 'Tag 3'])
const inputVisible = ref(false)
const InputRef = ref<InstanceType<typeof ElInput>>()
const select_item = [[0, '0'], [1, '1']]
const handleClose = (tag) => {
  dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1)
  console.log(`delete tag: ${tag}`)
}

function headClick(column, event) {
  console.log(`${column.label}`)
  click_value.value = column.label
}

function handleSelectionChange(value) {
  console.log("handleSelectionChange" + value)
}


function conditionUpdate(data) {
  /**
   * @param data {column, column_filter_type, condition}
   * des: 用户传来筛选条件来更新表格
   */
  let {column, column_filter_type, condition} = data
  let filter_type = get_filter_type()
  if (column_filter_type === filter_type['text']) {
  }
  if (column_filter_type === filter_type['scope']) {
  }
  if (column_filter_type === filter_type['date']) {
  }
  if (column_filter_type === filter_type['select']) {
  }
  console.log("conditionUpdate " + data)

}
<template>
  <div @click.stop style="display: inline-block ">
    <el-popover
        placement="bottom"
        title="查询条件"
        trigger="hover"
        width="300"
        :visible=open_flag
        ref="popoverRef"
    >
      <template #reference>
        <span @click="open_flag=true">{{ column }}</span>
      </template>
      <!--        text 文本简略搜索-->
      <div v-if="column_filter_type === filter_type['text']">
        <el-input style="width: 200px"
                  v-model="this.condition.value_start"
                  placeholder="请输入查询内容"
        >
        </el-input>
      </div>
      <!-- scope 范围 数值类型-->
      <div v-else-if="column_filter_type === filter_type['scope']">
        <el-input
            style="width: 120px"
            v-model="this.condition.value_start"
            placeholder="条件1"
        ></el-input>
        -
        <el-input
            style="width: 120px"
            v-model.trim="condition.value_end"
            placeholder="条件2"
        ></el-input>
      </div>
      <!-- date 日期-->
      <div v-else-if="column_filter_type === filter_type['date']">
        <el-date-picker
            style="width: 120px; margin-top: 10px;margin-right: 10px"
            v-model="condition.value_start"
            type="date"
            clearable
            placeholder="开始时间"
            value-format="YYYY-MM-DD"
        ></el-date-picker>
        <el-date-picker
            style="width: 120px; margin-top: 10px;"
            v-model="condition.value_end"
            type="date"
            clearable
            placeholder="结束时间"
            value-format="YYYY-MM-DD"
        ></el-date-picker>
      </div>
      <!-- select 选择框-->
      <div v-else-if="column_filter_type===filter_type['select']">
        <el-select
            v-model="condition.value_start"
            placeholder="请选择"
            style="width: 100%"
            clearable
        >
          <el-option
              v-for="[value, index] in select_items"
              :key="index"
              :label="value"
              :value="value"
          >
          </el-option>
        </el-select>
      </div>
      <div v-else>
        <el-text type="warning" tag="b">此数据类型暂不支持查询</el-text>
      </div>
      <br>
      <div style="text-align: right; margin-left: 20px">
        <el-button text @click="open_flag=false">cancel</el-button>
        <el-button type="primary" @click="confirm">confirm</el-button>
      </div>

    </el-popover>
  </div>
</template>
<script>
import {ref} from "vue";
import {get_filter_type, legal_judge} from "../../api/utils.ts";

export default {
  name: "newnew",
  props: ["column", "column_filter_type", "select_items"],
  data() {
    return {
      open_flag: ref(true),
      condition: {
        value_start: "",
        value_end: ""
      },
      filter_type: get_filter_type()
    }
  },
  methods: {
    confirm() {
      this.open_flag = false
      if (this.column_filter_type === this.filter_type['text']) {
        if (!legal_judge('text', this.condition)) {
          return this.$message.warning("请正确筛选条件");
        }
      } else if (this.column_filter_type === this.filter_type['scope']) {
        if (!legal_judge('scope', this.condition)) {
          return this.$message.warning("请正确筛选条件");
        }
      } else if (this.column_filter_type === this.filter_type['date']) {
        if (!legal_judge('date', this.condition)) {
          return this.$message.warning("请正确筛选条件");
        }
      } else if (this.column_filter_type === this.filter_type['select']) {
        if (!legal_judge('select', this.condition)) {
          return this.$message.warning("请正确筛选条件");
        }
      } else {
        return null
      }
      console.log(this.condition.value_start)
      console.log(this.condition.value_end)
      this.$emit("conditionUpdate", {
        column: this.column,
        column_filter_type: this.column_filter_type,
        condition: this.condition
      })
    },
  }
}
</script>

百度了好久都怎么管用的,刚学不太懂

阅读 862
avatarAI BotBETA

从你给出的代码和描述来看,你在使用 Vue 3 和 Element Plus 时遇到了 this.$emit 失效的问题。this.$emit 通常用于子组件向父组件发送消息。首先,我们需要确认几个可能的问题来源:

  1. 拼写和大小写:确保你正确拼写了事件名称,并且大小写是正确的。
  2. 事件监听:在父组件中,确保你正确监听了子组件发出的事件。例如,如果你在子组件中使用了 this.$emit('conditionUpdate', data),那么在父组件中,你应该有一个类似于 @condition-update="handleConditionUpdate" 的监听器。
  3. 组件的引用:确保你正确引用了子组件,并且子组件已经被正确注册和导入。
  4. setup 函数中的 emit:在 Vue 3 中,this 不再是可用的,所以你不能使用 this.$emit。相反,你应该在 setup 函数的参数中接收 emit。例如:
<script lang="ts" setup>
// ... 其他代码 ...

const emit = defineEmits(['conditionUpdate']);

// ... 其他代码 ...

function handleClose(tag) {
  dynamicTags.value.splice(dynamicTags.value.indexOf(tag), 1)
  console.log(`delete tag: ${tag}`)
  emit('conditionUpdate', { /* 你的数据 */ });
}

// ... 其他代码 ...
</script>
  1. propsemits 选项:在子组件的定义中,确保你声明了 emits 选项,这样 Vue 就知道这个组件会发出哪些事件。
<script>
export default {
  name: "newnew",
  props: ["column", "column_filter_type", "select_items"],
  emits: ['conditionUpdate'], // 这里声明
  // ... 其他代码 ...
}
</script>
  1. Vue 版本和 Element Plus 版本:确保你使用的 Vue 和 Element Plus 的版本是兼容的。

如果以上都没有问题,那么可能需要进一步检查你的代码以找出具体的问题所在。你可以尝试简化代码,逐步排除可能的问题,或者考虑创建一个最小化的可复现问题的示例,这样更容易找到问题的根源。

1 个回答

你理解错了,子组件想调用父组件的函数一般有两个方法,一种是把函数当成一个 props 传入

// 父组件
<newnew
    ...
    :update="conditionUpdate"
/>

// 子组件
<script>
    props: [..., 'update'],
    ...
    methods: {
        confirm() {
            this.update(xxx)
        }
    }
    
</script>

或者是子组件去触发注册的事件,比如你的子组件触发了一个 update 事件,父组件在触发 update 的时候调用这个方法

// 父组件
<newnew
    ...
    @update="conditionUpdate"
/>

// 子组件
<script>
    props: [..., 'update'],
    ...
    methods: {
        confirm() {
            this.emit('update', xxx) // 子组件在这里触发了 update 事件,就调用了 update 事件绑定的函数 conditionUpdate
        }
    }
    
</script>
推荐问题
logo
Microsoft
子站问答
访问
宣传栏