Vue 组件封装之 Content 列表(处理多行输入框 textarea)

一、Content 列表

组件说明:
实现 Content 列表布局排版。

效果展示:

在这里插入图片描述

实现的功能:

  1. 在一个 List 中实现文本和输入框(单行/多行)的上下布局;
  2. 上面为文本 label 标签,纯文字展示。可通过 require 字段来判断是否必填,必填项则前面会有红色的 *。
  3. 下面为输入值 input/textarea 标签。

二、使用案例

<template>
     <div>
     <el-context
          :list="contentList"        
          :result="contentItem"        
        />
      </div>
</template>
<script>
export default {
    
    
  data(){
    
    
     return {
    
    
        contentList:[
            {
    
    title:"工作内容",require:true,field:"content",placeholder:'请输入工作内容。如休假请填休假(240字以内)',
              renderType:'textarea',
              maxLength:"240"
            },
            {
    
    title:"时长",require:true,field:"time",placeholder:'请输入小时数,保留一位小数。如休假请填0',renderType:'number'},
            {
    
    title:"备注",require:false,field:"remark",placeholder:'请输入备注(240字以内)',
              renderType:'textarea',maxLength:"240",dealWithKeyboard:true},
          ],
        contentItem:{
    
    
          content:'',
          time:'',
          remark:'',
        },
     
    }
  }
}
</script>	

三、API 使用指南

属性 说明 类型 默认值
list 页面展示的静态内容集合 Array []
renderType 组件类型 String
maxLength 最大长度限制 String
label 展示文本 String
field 输入值字段 String
placeholder 提示 String
require 是否为必输字段 Boolean
disabled 值是 true 或者 disabled 则为反显值,否则为输入值 Boolean false
dealWithKeyboard 是否要处理安卓键盘遮挡问题 Boolean false
result 对应的字段值集合 Object {}

四、源代码

Context.vue
文件路径:share/context/Context.vue

<template>
  <div>
    <div v-for="item in list">
      <div class="cm-p-02 cm-bottom">
        <div class="cm-fs-030">
          <span class="cm-c-red" v-if="item.require">*</span>
          <span :class="[focusText==item.field?'edit-focus-text':'',!item.require?'cm-ml-02':'']">{
    
    {
    
    item.title}}</span>
        </div>
        <el-input
          v-if="item.renderType==='number'"
          @focus="changeStyle(item)"
          type="text"
          @input.native="changeNumber"
          :placeholder="item.placeholder"
          class="edit-input cm-w-full cm-fs-028 cm-c-333"
          v-model="result[item.field]"></el-input>
        <el-input
          :type="item.renderType"
          v-else
          @focus="changeStyle(item)"
          :autosize="{ minRows: 2, maxRows: 4}"
          :maxlength="item.maxLength"
          class="edit-input cm-w-full cm-fs-028 cm-c-333"
          :placeholder="item.placeholder"
          rows="2"
          v-model="result[item.field]">
        </el-input>
      </div>
    </div>
  </div>
</template>
<script>
  import {
    
    autoTextarea,isAndroid} from '../../utils/common';
  export default {
    
    
    name: "ElContent",
    data(){
    
    
      return{
    
    
        focusText:""
      }
    },
    //获取子组件传过来的激活tab
    props:{
    
    
      list:{
    
    
        type: Array,
        default: function () {
    
    
          return [];
        }
      },
      result:{
    
    
        type:Object,
        default:{
    
    }
      },
    },
    mounted(){
    
    
        //为了适应苹果浏览器初始时展现多行状态。
      setTimeout(() => {
    
    
        autoTextarea();
      }, 100);
    },
    methods:{
    
    
      changeNumber({
    
    target}){
    
    
        //此为数字输入框,控制非数字输入
        target.value=(target.value.match(/^\d*(\.?\d{0,1})/g)[0]) || null
      },
      changeStyle(item){
    
    
        //聚焦时改变label样式
        this.focusText = item.field;
        //避免安卓手机输入法弹出框挡住输入框
        if(item.dealWithKeyboard && isAndroid()){
    
    
          document.body.style.height = document.body.clientHeight + 100 +'px';
        }
      }
    }
  }
</script>

<style scoped>
  .edit-focus-text{
    
    
    color: #3296FA;
    font-size: 0.22rem;
  }
</style>
export function isAndroid(){
    
    
  var u = navigator.userAgent;
  var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
  if (isAndroid) {
    
    
    return true
  }else {
    
    
    return false
  }
}
export function autoTextarea(){
    
    
  var textarea = document.getElementsByTagName("textarea");
  for(var i=0;i<textarea.length;i++){
    
    
    textarea[i].style.height = 'auto';
    textarea[i].scrollTop = 0; //防抖动
    textarea[i].style.height = textarea[i].scrollHeight + 'px';
    textarea[i].addEventListener('input',function (e) {
    
    
      console.log(e.target.scrollHeight);
      e.target.style.height = 'auto';
      e.target.scrollTop = 0;
      if(e.target.scrollHeight>=100){
    
    
        //控制最高4行
        e.target.style.height = 100 + 'px';
      }else {
    
    
        e.target.style.height = e.target.scrollHeight + 'px';
      }
      //}
    })
  }
}

index.js
文件路径:share/context/index.js

import Content from './Content.vue';

/* istanbul ignore next */
Content.install = function(Vue) {
    
    
  Vue.component(Content.name, Content);
};

export default Content;

注:里面用到一些公共样式,公共样式内容比较多,就不贴出来了。有需要的留言。

猜你喜欢

转载自blog.csdn.net/weixin_44135121/article/details/109114465