VueJS 在不改变 "type" 属性 的情况下切换密码可见性

VueJS toggle password visibilty without mutating the "type" property

我有一个正在使用的基本输入组件,它具有 type 作为 属性,并且到目前为止一直运行良好。但是,尝试将其用于密码并实施混淆有点棘手。

如何在不改变 prop 的情况下切换 hide/show 密码?我认为将 type = 'password' 变为 type = 'text 是最好的方法,但显然不是。

我已经制作了一个 Codesandbox 来复制组件的那部分,但是任何建议或指导将不胜感激!

PasswordInput.vue:

<template>
  <div>
    <input :type="type" />
    <button @click="obfuscateToggle" class="ml-auto pl-sm _eye">
      <div>
        <img :src="`/${eyeSvg}.svg`" alt="" />
      </div>
    </button>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      passwordVisible: false,
      eyeSvg: "eye-closed",
    };
  },
  props: {
    type: { type: String, default: "text" },
  },
  methods: {
    obfuscateToggle() {
      if (this.eyeSvg === "eye-closed") {
        this.eyeSvg = "eye";
      } else this.eyeSvg = "eye-closed";
      // this.eyeSvg = "eye-closed" ? "" : (this.eyeSvg = "eye");
      if ((this.type = "password")) {
        this.type = "text";
      } else this.type = "password";
    },
  },
};
</script>

App.vue

<template>
  <div id="app">
    <PasswordInput type="password" />
  </div>
</template>

唯一的方法是改变类型属性。因为这就是浏览器决定将其呈现为文本框还是密码的方式。因此,您这样做 的方式是正确的

您将遇到的一个问题是,您将在控制台中抛出错误,因为您正试图改变一个道具。

修复起来既快速又容易。首先,您将创建一个新数据 属性,并将其分配给默认值 type

data(){
   return{
      fieldType:'text'
   }
}

然后您将使用 on mounted lifecycle hook,并更新您的数据 属性 以匹配您的道具的价值`

mounted(){
   this.fieldType = this.type;
}

如果您知道 type 道具将从父组件更改,您还可以使用 watcher 进行更改并分配 type

watch:{
   type(val){
      this.fieldType = val;
   }
}

然后您将更新 obfuscateToggle 方法以使用字段类型变量:

obfuscateToggle() {
  if (this.eyeSvg === "eye-closed") {
    this.eyeSvg = "eye";
  } else this.eyeSvg = "eye-closed";


  //You can simplify this by using this.fieldType = this.fieldType == "text" ? "password" : "text"
  if (this.fieldType == "password") {
    this.fieldType = "text";
  } else this.fieldType = "password";
}

最后,在您的模板中,您需要将 type 更改为 fieldType

<template>
  <div>
    <input :type="fieldType" />
    <button @click="obfuscateToggle" class="ml-auto pl-sm _eye">
      <div>
        <img :src="`/${eyeSvg}.svg`" alt="" />
      </div>
    </button>
  </div>
</template>

综合起来

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      passwordVisible: false,
      eyeSvg: "eye-closed",
      fieldType: "text"
    };
  },
  props: {
    type: { type: String, default: "text" },
  },
  methods: {
    obfuscateToggle() {
      if (this.eyeSvg === "eye-closed") {
        this.eyeSvg = "eye";
      } else this.eyeSvg = "eye-closed";
 

      //You can simplify this by using this.fieldType = this.fieldType == "text" ? "password" : "text"
      if (this.fieldType == "password") {
        this.fieldType = "text";
      } else this.fieldType = "password";


    },
  },
  watch:{
    type(val){
       this.fieldType = val;
    }
  },
  mounted(){
    this.fieldType = this.type;
  },
};
</script>

这是 CodeSandBox

上的示例

此外,您的 obfuscateToggle 方法中有一个小错字。

if(this.type = 'password')

这是在分配 type 而不是将其与文字进行比较 :)