【青山vue小笔记】教你封装一个点击显示输入框的组件(上)

这是我参与更文挑战的第8天,活动详情查看: 更文挑战

原来自己写东西的时候用过那种点击文字显示输入框的东西,就像下面这样

QQ录屏20210608125042[00_00_00--00_00_20].gif

刚好来新公司之后,接到的新任务就是写一个这样的公共组件,写的时候遇到了很多问题,也学到了很多,特此记录一下,希望也可以帮到你。

功能

思路

首先的功能就是要接收一个值用来显示,之后点击这个值显示一个输入框,输入新的值进行保存。看,功能是不是很简单,那就来跟着我一起实现一下吧,看看我遇到的问题你有没有遇到过。

首先我们接收一个value值,这个值就是我们用来显示的值。再接收一个type,告诉我们要展示的是那种类型的组件,比如单行输入框还是多行输入框。

props: {
    value: {
      default: '默认值',
      type: [String, Number]
    },
    type: {
      type: String,
      default: 'input'
    }
}
复制代码

在html部分,我们需要显示的有两部分,一部分是默认展示的值,另一部分是点击之后展示的输入框

  <div class="input-wrap" v-if="type === 'input'">
    <div class="input-text" @click="showEdit" v-show="!editVisible">
      {{ value }}
    </div>
    <div class="input-edit" v-show="editVisible">
      <input
        class="customer-input"
        type="text"
        v-model="editValue"
        ref="editInput"
      />
    </div>
  </div>
复制代码
/**
 * @name: 显示编辑框
 * @param {*}
 * @return {*}
 */
showEdit () {
  this.editVisible = true // 1
  this.editValue = this.value // 2
  switch (this.type) { // 3
    case 'input':
      this.$nextTick(() => {
        this.$refs.editInput.focus()
      })
      break

    case 'textarea':
      this.$nextTick(() => {
        this.$refs.editTextarea.focus()
      })
      break
  }
},
复制代码

这里我们首先判断了type的类型是哪种,这个不用解释。

之后给展示的值添加点击事件showEdit

  1. 点击之后切换用来控制编辑框显示的变量
  2. 将展示的值赋值给我们用来储存新值的变量,因为我们要确保修改失败的话不能影响原值(并且我们也不能直接修改prop传进来的值)
  3. 之后为了用户体验更好一点,我们在切换之后要使输入框自动获取到焦点,这里用到了 $nextTick()函数,是因为我们在更新了date里的值的时候,数据变动并不是实时渲染到dom上的,我们需要等dom更新完毕之后才可以获取到输入框。

之后再给输入框加上焦点消失事件和回车事件,如果发生这两个事件则隐藏输入框,并把新值传送给父组件,这里我把事件名也传给了父组件,以防不同的地方有不同的需求,记得要先给新值空值判定哦,也可以根据自己的业务场景添加其他验证,我这里因为是自己人用的组件,就不加那么多判断了。

/**
 * @name: 确认编辑事件
 * @param {String} handleName // 事件名称 enter / blur ……
 * @return {*}
*/
editSubmit (handleName) {
  // 由于回车事件触发后隐藏输入框会同时触发输入框的blur事件,所以要判断输入框当前是否为隐藏状态
  if (this.editVisible) {
    this.editVisible = false
    if (!this.editValue) return false
    this.$emit('edit', {
      value: this.editValue,
      handleName
    })
  }
}
复制代码

怎么样,一个简单的小组件是不是就完成了,我们的项目都是基础element-ui的,不过这里我没用element的输入框,因为自己写的话,它的大小可以用em,那样就会随着父元素的字体大小而变化了。

input完成了,多行文本也是一样的道理,我这里多行文本用的是原生的textarea,高度可以随着内容的高度变化,至于怎么实现的,可以去看看我这篇文章 记录一个小知识点,textarea如何根据内容自动变化高度及踩坑

  <!-- textarea -->
  <div class="textarea-wrap" v-if="type === 'textarea'">
    <div class="textarea-text" @click="showEdit" v-show="!editVisible">
      {{ value }}
    </div>
    <div class="textarea-edit" v-show="editVisible">
      <pre class="pre">{{ editValue }} </pre>
      <textarea
        class="customer-input textarea"
        type="text"
        v-model="editValue"
        :placeholder="options.placeholder"
        @blur="editSubmit('blur')"
        ref="editTextarea"
        :style="'border-color:' + options.border"
      />
    </div>
  </div>
复制代码

多行文本,搞定!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享