项目实现|封装一个带眼睛的密码子组件

1,142 阅读1分钟

image-20230914225926014.png

眼睛的icon使用的是阿里的图标库www.iconfont.cn/

【思路分析】:

首先这个密码组件是input+icon完成的(也可以是img但是我很懒,不想写css)

对于input来说:要做2件事情

  • 眼睛睁开:type是text,眼睛闭上:type是password

  • 给父组件提交用户输入的值

对于图标来说:要做2件事

  • 可以点击

  • 保证 密码-闭眼 文本-睁眼 这个效果

【核心代码】:

  1. flagType绑定动态的值 data中的flagType:'password',

  2. :class="[flag ? 'iconfont icon-yanjing_yincang_o': 'iconfont icon-yanjing_xianshi_o']"动态样式

  3. toShowPassword函数,眼睛的点击事件

        <el-input
            v-model="value"
            :type="flagType"
            ref="password"
            @input="emitInput"
        >
            <i
                slot="suffix"
                class="el-input__icon eye-wrapper"
                :class="[flag ? 'iconfont icon-yanjing_yincang_o': 'iconfont icon-yanjing_xianshi_o']"
                @click="toShowPassword">
            </i>
        </el-input>
    

【script代码】:

```js
    data() {
        return {
            value: '',
            flag: true,
            flagType: 'password',
        }
    },
```

```js
    methods: {
        toShowPassword() {
            this.flag = !this.flag
            this.flagType = this.flag ? 'password' : 'text'
            this.$nextTick(() => {
                this.$refs.password.focus()
            })
        },
        //提交数据
        emitInput() {
            this.$emit('input', this.value)
        },
    }
```

【父组件引用】:

我在父组件中设置了展示密码的按钮

    <div style="width: 200px">
        <h1>密码组件</h1>
        <toggle-passowrd v-model="form.password"></toggle-passowrd>
        <el-button @click="getPassword">展示密码</el-button>
    </div>

在子组件中emitInput这个方法将子组件的数据提交到了父组件,父组件通过v-model就可以拿到这个值

这里其实还涉及一个知识点,就是v-model是怎么实现的?其实上面的代码可以进行原生的改下,请看下面的代码

<toggle-passowrd v-model="form.password"></toggle-passowrd>
// 原生
<toggle-passowrd @input="setPassword" :value="form.password"></toggle-passowrd>

原生需要的方法:

    setPassword(val) {
        this.form.password = val
    },

这样知识就串联了起来,子组件通过emit将数据给了父组件,父组件通过子组件提交的input事件去取数据,而vue为此,提供了一个vue的指令,就是v-model,v-model就是获取数据,并赋值数据,实现绑定。

结合之前遇到的google会出现密码回填的问题,【封装了一个不会触发回填的密码子组件】

因为出现回填的根本原因就是type=“password”,所以使用text=“text”去规避这个问题,然后密文效果通过css去实现,最后封装了一个密码子组件可以参考

<!--
 * @Author: Kvon
 * @Date: 2023-09-14 20:56:57
 * @Description: 
-->
<template>
	<div>
		<el-input
			v-model="value"
			type="text"
			ref="password"
			@input="emitInput"
			:class="['input-content', className, flag ? 'disc' : 'none']"
		>
			<i
				slot="suffix"
				class="el-input__icon eye-wrapper"
				:class="[
					flag
						? 'iconfont icon-yanjing_yincang_o'
						: 'iconfont icon-yanjing_xianshi_o'
				]"
				@click="toShowPassword"
			>
			</i>
		</el-input>
	</div>
</template>
<script>
export default {
	name: 'PasswordCss',
	data() {
		return {
			value: '',
			flag: true
		}
	},
	methods: {
		/**
		 * @Author: Kvon
		 * @Date: 2023-09-14 21:14:30
		 * @Description: 展示密码
		 */
		toShowPassword() {
			this.flag = !this.flag
			this.$nextTick(() => {
				this.$refs.password.focus()
			})
		},
		/**
		 * @Author: Kvon
		 * @Date: 2023-09-14 22:52:13
		 * @Description:  提交子组件数据
		 */
		emitInput() {
			this.$emit('input', this.value)
		}
	}
}
</script>
<style lang="less" scoped>
.disc {
	/* Use -webkit-text-security if the browser supports it */
	-webkit-text-security: disc;
}
.none {
	/* Use -webkit-text-security if the browser supports it */
	-webkit-text-security: none;
}
.eye-wrapper {
	font-size: 16px;
    -webkit-text-security: none;
}
</style>