vue3+vite+electron+element-plus在el-form中使用el-input,为什么el-input获取到焦点之后只能输入一个字符?

vue3 + vite + electron + element-plus 创建的界面使用的 el-form + el-input
每次获取焦点之后只能输入一个字符,单独使用 el-input 没有问题,放到 el-form 里面之后就有问题了。

<template>
  <div class="login-container">
    <div class="login-box">
      <el-card class="box-card">
        <el-form ref="loginForm" :model="loginForm" :rules="rules" label-width="80px">
          <el-form-item label="用户名:" prop="username">
            <el-input v-model="loginForm.username"></el-input>
          </el-form-item>
          <el-form-item label="密码:" prop="password">
            <el-input type="password" v-model="loginForm.password"></el-input>
          </el-form-item>
          <el-form-item class="login-btn">
            <el-button type="primary" @click="handleLogin">登录</el-button>
          </el-form-item>
        </el-form>
      </el-card>
    </div>
  </div>
</template>

<script setup>
import { ref, getCurrentInstance } from 'vue';
import { useRouter } from 'vue-router';
import { ElCard, ElForm, ElFormItem, ElInput, ElButton } from 'element-plus';

const { proxy } = getCurrentInstance();
const router = useRouter();
const loginForm = ref({
  username: '',
  password: '',
});
const rules = ref({
  username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
  password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
});

const handleLogin = () => {
  proxy.$refs['loginForm'].validate((valid) => {
    if (valid) {
      router.push({ name: 'Interface' });
    }
  });
};
</script>

单独使用 el-input,不用el-form 没有问题,使用 el-form + 原生input 也没问题。

阅读 1.4k
3 个回答

很简单,你的 $refs 注册的key和你 ref() 声明的 loginForm 重合了。
在组件实例挂载之后会被覆盖成 el-form 的模板引用,所以你没办法修改 loginForm.username了。

  • 也不是不能修改,而是不会响应了。并且因为 el-input受控组件 所以会有OP你说的问题现象。

要解决的话,改成不一样的key就行了。
另外最好不要再使用 getCurrentInstance 获取当前组件实例了。

<template>
  <div class="login-container">
    <div class="login-box">
      <el-card class="box-card">
        <el-form ref="elFormRef" :model="loginForm" :rules="rules" label-width="80px">
          <el-form-item label="用户名:" prop="username">
            <el-input v-model="loginForm.username"></el-input>
          </el-form-item>
          <el-form-item label="密码:" prop="password">
            <el-input type="password" v-model="loginForm.password"></el-input>
          </el-form-item>
          <el-form-item class="login-btn">
            <el-button type="primary" @click="handleLogin">登录</el-button>
          </el-form-item>
        </el-form>
      </el-card>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { ElCard, ElForm, ElFormItem, ElInput, ElButton } from 'element-plus';

const loginForm = ref({
  username: '',
  password: '',
});

const rules = ref({
  username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
  password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
});

const elFormRef = ref(null)

const handleLogin = () => {
  elFormRef.value.validate((valid) => {
    if (valid) {
      router.push({ name: 'Interface' });
    }
  });
};
</script>

我对你的代码做了一些改进。主要是确保 loginForm 使用 reactive 而不是 ref,并且去掉了 ref 属性。以下是改进后的代码:

<template>
<div class="login-container">

<div class="login-box">
  <el-card class="box-card">
    <el-form :model="loginForm" :rules="rules" label-width="80px">
      <el-form-item label="用户名:" prop="username">
        <el-input v-model="loginForm.username"></el-input>
      </el-form-item>
      <el-form-item label="密码:" prop="password">
        <el-input type="password" v-model="loginForm.password"></el-input>
      </el-form-item>
      <el-form-item class="login-btn">
        <el-button type="primary" @click="handleLogin">登录</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</div>

</div>
</template>

<script setup>
import { reactive, getCurrentInstance } from 'vue';
import { useRouter } from 'vue-router';
import { ElCard, ElForm, ElFormItem, ElInput, ElButton } from 'element-plus';

const { proxy } = getCurrentInstance();
const router = useRouter();
const loginForm = reactive({
username: '',
password: '',
});
const rules = reactive({
username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
});

const handleLogin = () => {
proxy.$refs['loginForm'].validate((valid) => {

if (valid) {
  router.push({ name: 'Interface' });
}

});
};
</script>

这样修改后,loginForm 使用 reactive 创建,并且去掉了 ref 属性,避免了可能的冲突。

ref 的使用:ref 创建的是一个包含 value 的响应式引用。el-input 需要访问直接的字符串值(如 username),而不是 loginForm.value.username。

Vue 的响应式系统:el-input 组件在内部使用 Vue 的响应式系统。如果给它传递的是 ref 的引用,它可能无法正确处理这个引用,从而导致只能输入一个字符。

reactive 的优势:使用 reactive 创建的对象本身就是响应式的,直接可以通过 loginForm.username 访问属性,el-input 能够正常识别并更新这个值。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏