「站在上帝的角度」谈谈Element组件结构-Input

简介: 「站在上帝的角度」谈谈Element组件结构-Input

👋 前言


  • 用户就是上帝,站在上帝的角度也就是站在使用者的角度去看待组件。
  • 用过不少优秀的UI库,用的时候美滋滋,轮到自己搭组件库的时候往往会去参考别人的源码。
  • 看完源码后恍然大悟 噢!原来可以这样写,但心里难免会有疑惑别人是怎么想出来这种解决思路的?🤳
  • 这一系列文章主要是面向未理解或者有疑惑的同学所以讲的比较基础,就让我们站在用户的角度去思考结构,看看换一种思路去写代码是不是有变化?


⌨️关于Input组件


👻为什么我们会用到Input


👨‍💼 作为用户

  • input输入框是最常见的一种表单输入的控件,一般出现在问卷或者后台系统里面作为一个可以表达的组件。
  • 用户需要的输入框无非就是简洁好看的,如果搞的花里胡哨可能会有些不适应,特别是政务系统里面的表单更是需要同一色号。


👨‍💻 作为组件库使用者

  • 我们可以看到很多的组件库都有Input,相信大家都很熟悉了。
  • 当我们将组件库的Input组件放到我们的页面我们想要的效果是什么?
  • 可以实现输入的功能
  • 拥有原生input的所有功能
  • 可以满足基本的双向绑定
  • 可以在基本的需求上进行定制增加功能(比如: 禁用添加图标清空
  • 在某一个方面来说,Input的出现也让我们在制作页面时更加方便统一样式和功能,节省不少时间


⚒️ 搭建组件


接下来可能用尽可能少的代码搭配element的源码进行结构说明,配合element Input源码食用更加美味喔


🔨 基本架子

  • 要设计一个上图这种的Input不难,其实就是修改一下input的样式罢了
  • 总结起来总共也只有4个要点
  • 准备一个外部的容器包含input
  • 根据不同类型呈现texttextarea等类型的输入框
  • input可以使用原生的属性,例如(placeholder

<template>
  <div class="zl-input">
    <template v-if="type !== 'textarea'">
      <input ref="input" type="text" class="zl-input__inner" v-bind="$attrs">
    </template>
    <template v-else>
      <textarea ref="textarea"></textarea>
    </template>
  </div>
</template>
...
<script>
export default {
    props:{
        value: [String, Number],
        type: {
          type: String,
          default: 'text'
        }
       }
    };
</script>
...
复制代码
  • 以上就是element最简单的input结构,可以看到子组件通过分辨type来分辨是input类型还是textarea类型,这两种不同类型需要做不同处理,v-bind="$attrs"可以将没有在props出现的属性直接给到input上就例如placeholder可以直接作为input的属性本文就主要讲一讲input,两者其实没什么差别,关于具体样式可以看element 样式
  • 当然这只是一个架子我们还需要加上双向绑定和其他功能。


🎶 双向绑定

  • 单单只是一个架子可不行,我们需要记录下来输入的值,这时候就需要用到外面的v-model
  • 在父组件我们用v-model传入了一个值, 而v-model的语法糖会把这个值当成propsvalue传到子组件,子组件只要通过$emit时间改变外部的input事件就可以啦。
<template>
  <div class="zl-input">
    <template v-if="type !== 'textarea'">
      <input ref="input" type="text" class="zl-input__inner" v-bind="$attrs" @input="handleInput">
    </template>
    <template v-else>
      <textarea ref="textarea"></textarea>
    </template>
  </div>
</template>
···
   computed:{
    nativeInputValue() {
       return this.value === null || this.value === undefined ? '' : String(this.value);
     }
   },
   watch:{
     nativeInputValue() {
       this.setNativeInputValue();
     },
   },
   mounted () {
      this.setNativeInputValue();
   },
   methods:{
    handleInput(event) {
       this.$emit('input', event.target.value);
     },
    getInput() {
      return this.$refs.input || this.$refs.textarea;
    },
    setNativeInputValue() {
      const input = this.getInput();
      if (!input) return;
      if (input.value === this.nativeInputValue) return;
      input.value = this.nativeInputValue;
    },
   }
···
复制代码
  • 在这里要注意的是我们没有像往常做双向绑定一样直接在input绑定:value="xxx"而是通过手动赋值在setNativeInputValue控制外部传进来的value值,一开始看到element的源码的时候我也很疑惑?为什么要这样做,直接使用:value不是更方便吗,最后在一个issues找到了答案。

  • 意思大致就是elementinput组件在输入前后会有一些处理,而这些处理跟:value的模式冲突了,最后改成了手动赋值,如果我们自己写的组件没有这种bug的话两种方式都可以使用,就当是学到了一种方法吧。
  • 这样一来我们的一个最简单的input就做好了。


🧮 更多需求

  • 一个最简单的架子搭好了接下来就可以定制我们的组件了。
  • 比如说禁用啊,加图标啊,相信大家也已经很熟悉了,无非就是通过插槽获取通过props实现动态样式切换即可。
  • 除了样式的切换还加上了一些前置内容和后置内容插槽来便利使用者,实现也不难就是在不同的的地方加上具名插槽即可。
  • 在事件上也可以定制很多情况比如focusblur 这些都是在input绑定事件即可,更多的实现可以参考传送门进行学习~


👋 写在最后


  • 总的来说Input组件相对于其他复杂组件比较简单,只要把架子搭出来了剩下就是不断的优化加内容,大家也可以一起写写组件试试,难点在于合理制作双向绑定不跟其他事件冲突。
  • 对于组件库的搭建我也在慢慢的摸索,讲的都是我自己得出来的分享所以说可能对于大佬来说会比较基础,但我相信我的不断输出可以帮助到一些有疑惑的同学。
  • 如果您觉得这篇文章有帮助到您的的话不妨🍉关注+点赞+收藏+评论+转发🍉支持一下哟~~😛
相关文章
|
C语言 Android开发 Windows
解决windows下eclipse创建project时没有include导致出现“unresolved inclusion: &lt;stdio.h&gt;”错误的方法
解决windows下eclipse创建project时没有include导致出现“unresolved inclusion: &lt;stdio.h&gt;”错误的方法
解决windows下eclipse创建project时没有include导致出现“unresolved inclusion: &lt;stdio.h&gt;”错误的方法
|
3月前
|
存储 安全 前端开发
CC&LG实践|基于 LangGraph 一步步实现 Claude-Code 核心设计
本文旨在深入剖析 Claude-Code 的核心设计思想与关键技术实现,逆向分析其功能模块,结合 LangGraph 框架的能力,系统性地演示如何从一个最基础的 ReAct Agent 出发,逐步构建一个功能完备的简版 Claude-Code。
1692 19
CC&LG实践|基于 LangGraph 一步步实现 Claude-Code 核心设计
|
9月前
域名优惠包使用帮助文档
本文详细介绍域名优惠包的使用步骤,让您在优惠包使用过程中操作更便捷。
382 2
域名优惠包使用帮助文档
|
XML IDE 前端开发
IDEA忽略node_modules减少内存消耗,提升索引速度
在后端开发中,IDEA 在运行前端代码时,频繁扫描 `node_modules` 文件夹会导致高内存消耗和慢索引速度,甚至可能会导致软件卡死。为了改善这一问题,可以按照以下步骤将 `node_modules` 文件夹设为忽略:通过状态菜单右键排除该文件夹、在设置选项中将其加入忽略列表,并且手动修改项目的 `.iml` 文件以添加排除配置。这些操作可以有效提高IDE的运行性能、减少内存占用并简化项目结构,但需要注意的是,排除后将无法对该文件夹进行索引,操作文件时需谨慎。
1270 4
IDEA忽略node_modules减少内存消耗,提升索引速度
|
12月前
|
Web App开发 安全 网络协议
多域名 SSL 证书是什么? 多域名 SSL 证书申请流程
多域名SSL证书是保护多个网站时的高效选择,它使得单个证书能够保护多个域名(网站)。这种证书通过在用户的Web浏览器和托管网站的服务器之间建立安全的加密连接,确保了敏感信息(包括登录凭证、信用卡信息和其他个人数据)的安全传输。
865 1
|
安全 物联网 数据安全/隐私保护
车联网
对于车联网的操作,我们可以按照以下步骤进行,这些步骤涵盖了从初始设置到日常使用的大部分关键流程。请注意,具体步骤可能会因车型、汽车制造商以及所选的服务提供商而有所不同。
|
JavaScript
Nest.js 实战 (七):如何生成 SVG 图形验证码
这篇文章介绍了使用NestJS实现Session验证的图形验证码功能的具体步骤。首先,通过powershell代码安装依赖pnpmaddsvg-captcha。然后,在控制器中使用TypeScript代码引入相关依赖,创建一个图形验证码的接口,当请求该接口时,返回一张随机图片验证码。最后,进行了效果演示。
289 0
Nest.js 实战 (七):如何生成 SVG 图形验证码
|
存储 JavaScript 前端开发
JavaScript DOM 操作:什么是文档碎片(Document Fragment)?有什么作用?
JavaScript DOM 操作:什么是文档碎片(Document Fragment)?有什么作用?
635 0
|
安全 算法 API
如何在DocuSign中设置PKCE(Proof Key for Code Exchange)
在使用DocuSign进行电子签名时,安全性至关重要。PKCE提供了一个额外的安全层,特别是在移动设备或基于浏览器的应用中,有效防止授权码泄露或被未授权的第三方使用。
373 0
如何在DocuSign中设置PKCE(Proof Key for Code Exchange)